diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 04e2248e67003..73ffa0896a398 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -19,7 +19,10 @@ If the issue is not fully described in the ticket, add more information here (ju * ... +The changelogs will be integrated by the core maintainers after the merge. +The changelog entry should be in the imperative mood; e.g., write "do this"/"return that" rather than "does this"/"returns that". +For examples, see: https://www.jenkins.io/changelog/ +--> ### Proposed upgrade guidelines @@ -28,9 +31,10 @@ N/A ### Submitter checklist - [ ] (If applicable) Jira issue is well described -- [ ] Changelog entries and upgrade guidelines are appropriate for the audience affected by the change (users or developer, depending on the change). [Examples](https://github.com/jenkins-infra/jenkins.io/blob/master/content/_data/changelogs/weekly.yml) +- [ ] Changelog entries and upgrade guidelines are appropriate for the audience affected by the change (users or developer, depending on the change) and are in the imperative mood. [Examples](https://github.com/jenkins-infra/jenkins.io/blob/master/content/_data/changelogs/weekly.yml) * Fill-in the `Proposed changelog entries` section only if there are breaking changes or other changes which may require extra steps from users during the upgrade - [ ] Appropriate autotests or explanation to why this change has no tests +- [ ] New public classes, fields, and methods are annotated with `@Restricted` or have `@since TODO` Javadoc, as appropriate. - [ ] For dependency updates: links to external changelogs and, if possible, full diffs @@ -49,7 +53,7 @@ Before the changes are marked as `ready-for-merge`: - [ ] There are at least 2 approvals for the pull request and no outstanding requests for change - [ ] Conversations in the pull request are over OR it is explicit that a reviewer does not block the change -- [ ] Changelog entries in the PR title and/or `Proposed changelog entries` are correct +- [ ] Changelog entries in the PR title and/or `Proposed changelog entries` are accurate, human-readable, and in the imperative mood - [ ] Proper changelog labels are set so that the changelog can be generated automatically - [ ] If the change needs additional upgrade steps from users, `upgrade-guide-needed` label is set and there is a `Proposed upgrade guidelines` section in the PR title. ([example](https://github.com/jenkinsci/jenkins/pull/4387)) - [ ] If it would make sense to backport the change to LTS, a Jira issue must exist, be a _Bug_ or _Improvement_, and be labeled as `lts-candidate` to be considered (see [query](https://issues.jenkins-ci.org/issues/?filter=12146)). diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 9cec7116807de..2598142fdb152 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -23,6 +23,9 @@ updates: - dependency-name: "javax.servlet.servlet-api" # needs a jakarta upgrade project, imports changed - dependency-name: "jakarta.servlet.jsp.jstl.jakarta.servlet.jsp.jstl-api" + # Starting with version 2.0.2, this library requires Java 11 + - dependency-name: "org.glassfish.tyrus.bundles:tyrus-standalone-client-jdk" + versions: [">=2.0.2"] # see https://github.com/jenkinsci/jenkins/pull/4224 can't be updated without breaking api - dependency-name: "org.jfree:jfreechart" # the dependency is actually provided by the Web container, hence it is aligned with Jetty. See https://github.com/jenkinsci/jenkins/pull/5211 @@ -34,7 +37,8 @@ updates: # Must remain within jetty 9.x until Java 8 support is removed, ignore jetty 10.x and jetty 11.x updates - dependency-name: "org.eclipse.jetty:jetty-maven-plugin" versions: [">=10.0.0"] - # Pending https://github.com/siom79/japicmp/pull/266 - - dependency-name: "com.github.siom79.japicmp:japicmp-maven-plugin" # Winstone upgrades require multiple changes in pom.xml. See https://github.com/jenkinsci/jenkins/pull/5439#discussion_r616418468 - dependency-name: "org.jenkins-ci:winstone" + # Starting with version 10.0, this library requires Java 11 + - dependency-name: "com.puppycrawl.tools:checkstyle" + versions: [">=10.0"] diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index e7b74ccfd717d..10007762203c5 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -17,7 +17,7 @@ jobs: # Drafts your next Release notes as Pull Requests are merged into "master" - name: Generate GitHub Release Draft id: release-drafter - uses: release-drafter/release-drafter@v5.15.0 + uses: release-drafter/release-drafter@v5.19.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Generates a YAML changelog file using https://github.com/jenkinsci/jenkins-core-changelog-generator @@ -28,7 +28,7 @@ jobs: env: GITHUB_AUTH: github-actions:${{ secrets.GITHUB_TOKEN }} - name: Upload Changelog YAML - uses: actions/upload-artifact@v2.3.1 + uses: actions/upload-artifact@v3 with: name: changelog.yaml path: changelog.yaml @@ -44,7 +44,7 @@ jobs: private_key: ${{ secrets.JENKINS_CHANGELOG_UPDATER_PRIVATE_KEY }} repository: jenkins-infra/jenkins.io - name: Check out - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Publish jenkins.io changelog draft diff --git a/.github/workflows/publish-release-artifact.yml b/.github/workflows/publish-release-artifact.yml index 1d8277be3f2dd..7d2571883aec5 100644 --- a/.github/workflows/publish-release-artifact.yml +++ b/.github/workflows/publish-release-artifact.yml @@ -11,7 +11,7 @@ jobs: project-version: ${{ steps.set-version.outputs.project-version }} is-lts: ${{ steps.set-version.outputs.is-lts }} steps: - - uses: actions/checkout@v2.4.0 + - uses: actions/checkout@v3 - name: Set up JDK 8 uses: actions/setup-java@v2 with: diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml index 43d62816190d2..a65d82e1b6479 100644 --- a/.mvn/extensions.xml +++ b/.mvn/extensions.xml @@ -2,6 +2,6 @@ io.jenkins.tools.incrementals git-changelist-maven-extension - 1.2 + 1.3 diff --git a/.perltidyrc b/.perltidyrc new file mode 100644 index 0000000000000..60845ad9c9cd1 --- /dev/null +++ b/.perltidyrc @@ -0,0 +1,104 @@ +################################################# +# Categories outlined in this config +# are based on the categories in the +# perltidy man page: +# http://perltidy.sourceforge.net/perltidy.html +################################################# + +################################### +# I/O Control +################################### + +# Send all errors to standard output rather than a file. +--standard-error-output + +# All non-critical warnings will be reported as errors. +--warning-output + +################################### +# Basic Options +################################### + +# Maximum number of characters per line. +--maximum-line-length=80 + +################################### +# Code Indentation Control +################################### + +# The number of spaces to indent a line when a new block starts. +--indent-columns=4 + +# If a line continues, it should be indented 2 spaces. +--continuation-indentation=4 + +# If a comment is longer than the maximum line length, break it up for +# readability. +--outdent-long-comments + +# If a quoted string is longer than the maximum line length, do not break it up +# for readability. +--no-outdent-long-quotes + +################################### +# Whitespace Control +################################### + +# Stack opening braces in order to avoid having a brace sitting by itself on +# a line. +--stack-opening-tokens + +# Stack closing tokens in order to avoid having a brace sitting by itself on +# a line. +--stack-closing-tokens + +# Spaces between parentheses e.g. if ((my $len_tab = length($tabstr)) > 0) { +--paren-tightness=2 + +# Spaces between brackets e.g. $width = $col[$j + $k] - $col[$j]; +--square-bracket-tightness=2 + +# Spaces between braces in expression e.g. $obj->{$parsed_sql->{'table'}[0]}; +--brace-tightness=2 + +# Spaces between braches with blocks of code +# e.g. %bf = map { $_ => -M $_ } grep { /\.deb$/ } dirents '.'; +--block-brace-tightness=0 + +# Do not add spaces between semicolons within for loops. +--nospace-for-semicolon + +################################### +# Comment Controls +################################### + +# Indent comments to be at the same level as the code. +--indent-block-comments + +################################### +# Line Break Control +################################### + +# The else is on the same line as the brace. +--cuddled-else + +# Create a break after -> and period if a break is required. +--want-break-after='-> .' + +################################### +# Blank Line Control +################################### + +# Do not force blank lines before full line comments. +--noblanks-before-comments + +# Do not force blank lines before blocks starting with for, foreach, while, +# until, and if,unless. +--noblanks-before-blocks + +################################### +# Vertical Alignment +################################### + +# Turn off vertical alignment. +-novalign diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d981755ee1375..23053598b75a8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,12 +9,10 @@ This page provides information about contributing code to the Jenkins core codeb 1. Fork the repository on GitHub 2. Clone the forked repository to your machine 3. Install the necessary development tools. In order to develop Jenkins, you need the following: - * Java Development Kit (JDK) 8 or 11. - In the Jenkins project we usually use [OpenJDK](http://openjdk.java.net/) or [AdoptOpenJDK](https://adoptopenjdk.net/), but you can use other JDKs as well. - * For JDK 11 there might be some compatibility issues in developer tools, - please see [this page](https://wiki.jenkins.io/display/JENKINS/Java+11+Developer+Guidelines#Java11DeveloperGuidelines-Knowndevelopertoolsissues) for more info. - If you find a new issue, please report it with a `java11-devtools-compatibility` label in our issue tracker. - * Maven 3.5.4 or above. You can [download Maven here]. + * Java Development Kit (JDK) 11 or 8. + In the Jenkins project we usually use [Eclipse Adoptium](https://adoptium.net/) or [OpenJDK](https://openjdk.java.net/), but you can use other JDKs as well. + * Apache Maven 3.8.1 or above. You can [download Maven here]. + In the Jenkins project we usually use the most recent Maven release. * Any IDE which supports importing Maven projects. * Install [NodeJS](https://nodejs.org/en/). **Note:** only needed to work on the frontend assets found in the `war` module. * Frontend tasks are run using [yarn](https://yarnpkg.com/lang/en/). Run `npm install -g yarn` to install it. @@ -92,7 +90,7 @@ cd war; yarn test ## Proposing Changes The Jenkins project source code repositories are hosted at GitHub. -All proposed changes are submitted, and code reviewed, using the _GitHub Pull Request_ process. +All proposed changes are submitted, and code reviewed, using a [GitHub pull request] process. To submit a pull request: @@ -123,6 +121,7 @@ This will help minimize the diff, which makes reviewing PRs easier. We also do not recommend `*` imports in the production code. Please disable them in Settings > Editor > Codestyle > Java by setting _Class count to use import with '*'_ and Names count to use import with '*'_ to a high value, e.g. 100. + ## Copyright The Jenkins core is licensed under [MIT license], with a few exceptions in bundled classes. @@ -150,15 +149,15 @@ just submit a pull request. # Links * [Jenkins Contribution Landing Page](https://www.jenkins.io/participate/) -* [Jenkins IRC Channel](https://www.jenkins.io/chat/) -* [Beginners Guide To Contributing](https://wiki.jenkins.io/display/JENKINS/Beginners+Guide+to+Contributing) +* [Jenkins Chat Channels](https://www.jenkins.io/chat/) +* [Beginners Guide To Contributing](https://www.jenkins.io/participate/) * [List of newbie-friendly issues in the core](https://issues.jenkins.io/issues/?jql=project%20%3D%20JENKINS%20AND%20status%20in%20(Open%2C%20%22In%20Progress%22%2C%20Reopened)%20AND%20component%20%3D%20core%20AND%20labels%20in%20(newbie-friendly)) [Preparing for Plugin Development]: https://www.jenkins.io/doc/developer/tutorial/prepare/ [newbie friendly issues]: https://issues.jenkins.io/issues/?jql=project%20%3D%20JENKINS%20AND%20status%20in%20(Open%2C%20%22In%20Progress%22%2C%20Reopened)%20AND%20component%20%3D%20core%20AND%20labels%20in%20(newbie-friendly) [Participate]: https://www.jenkins.io/participate/ [building and debugging process here]: https://www.jenkins.io/doc/developer/building/ -[guide]: https://wiki.jenkins.io/display/JENKINS/Starting+and+Accessing+Jenkins +[guide]: https://www.jenkins.io/doc/book/installing/war-file/#run-the-war-file [Remote Debug Flags]: https://stackoverflow.com/questions/975271/remote-debugging-a-java-application [Acceptance Test Harness (ATH)]: https://github.com/jenkinsci/acceptance-test-harness [backporting process]: https://www.jenkins.io/download/lts/ @@ -170,3 +169,4 @@ just submit a pull request. [Jenkins Pipeline]: https://www.jenkins.io/doc/book/pipeline/ [Jenkinsfile]: ./Jenkinsfile [download Maven here]: https://maven.apache.org/download.cgi +[GitHub pull request]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index 4cd19525f6e94..ba2eebe049214 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -7,129 +7,162 @@ def buildNumber = BUILD_NUMBER as int; if (buildNumber > 1) milestone(buildNumber - 1); milestone(buildNumber) // JENKINS-43353 / JENKINS-58625 -// TEST FLAG - to make it easier to turn on/off unit tests for speeding up access to later stuff. -def runTests = true def failFast = false // Same memory sizing for both builds and ATH -def javaOpts = ["JAVA_OPTS=-Xmx1536m -Xms512m","MAVEN_OPTS=-Xmx1536m -Xms512m"] +def javaOpts = [ + 'JAVA_OPTS=-Xmx1536m -Xms512m', + 'MAVEN_OPTS=-Xmx1536m -Xms512m', +] properties([ - buildDiscarder(logRotator(numToKeepStr: '50', artifactNumToKeepStr: '3')), - disableConcurrentBuilds(abortPrevious: true) + buildDiscarder(logRotator(numToKeepStr: '50', artifactNumToKeepStr: '3')), + disableConcurrentBuilds(abortPrevious: true) ]) -// TODO: Restore 'Windows' once https://groups.google.com/forum/#!topic/jenkinsci-dev/v9d-XosOp2s is resolved -def buildTypes = ['Linux'] -def jdks = [8, 11] +def buildTypes = ['Linux', 'Windows'] +def jdks = [8, 11, 17] def builds = [:] -for(i = 0; i < buildTypes.size(); i++) { -for(j = 0; j < jdks.size(); j++) { +for (i = 0; i < buildTypes.size(); i++) { + for (j = 0; j < jdks.size(); j++) { def buildType = buildTypes[i] def jdk = jdks[j] + if (buildType == 'Windows' && jdk == 8) { + continue // unnecessary use of hardware + } + if (buildType == 'Windows' && jdk == 17) { + continue // TODO pending jenkins-infra/helpdesk#2822 + } builds["${buildType}-jdk${jdk}"] = { - // see https://github.com/jenkins-infra/documentation/blob/master/ci.adoc#node-labels for information on what node types are available - node(buildType == 'Linux' ? (jdk == 8 ? 'maven' : 'maven-11') : buildType.toLowerCase()) { - // First stage is actually checking out the source. Since we're using Multibranch - // currently, we can use "checkout scm". - stage('Checkout') { - checkout scm - } - - def changelistF = "${pwd tmp: true}/changelist" - def m2repo = "${pwd tmp: true}/m2repo" + // see https://github.com/jenkins-infra/documentation/blob/master/ci.adoc#node-labels for information on what node types are available + def agentContainerLabel = jdk == 8 ? 'maven' : 'maven-' + jdk + if (buildType == 'Windows') { + agentContainerLabel += '-windows' + } + node(agentContainerLabel) { + // First stage is actually checking out the source. Since we're using Multibranch + // currently, we can use "checkout scm". + stage('Checkout') { + checkout scm + } - // Now run the actual build. - stage("${buildType} Build / Test") { - timeout(time: 300, unit: 'MINUTES') { - // -Dmaven.repo.local=… tells Maven to create a subdir in the temporary directory for the local Maven repository - // -ntp requires Maven >= 3.6.1 - def mvnCmd = "mvn -Pdebug -Pjapicmp -U -Dset.changelist help:evaluate -Dexpression=changelist -Doutput=$changelistF clean install ${runTests ? '-Dmaven.test.failure.ignore' : '-DskipTests'} -V -B -ntp -Dmaven.repo.local=$m2repo -Dspotbugs.failOnError=false -Dcheckstyle.failOnViolation=false -e" - infra.runWithMaven(mvnCmd, jdk.toString(), javaOpts, true) + def changelistF = "${pwd tmp: true}/changelist" + def m2repo = "${pwd tmp: true}/m2repo" - if(isUnix()) { - sh 'git add . && git diff --exit-code HEAD' - } - } - } + // Now run the actual build. + stage("${buildType} Build / Test") { + timeout(time: 5, unit: 'HOURS') { + realtimeJUnit(healthScaleFactor: 20.0, testResults: '*/target/surefire-reports/*.xml,war/junit.xml') { + def mavenOptions = [ + '-Pdebug', + '--update-snapshots', + "-Dmaven.repo.local=$m2repo", + '-Dmaven.test.failure.ignore', + '-Dspotbugs.failOnError=false', + '-Dcheckstyle.failOnViolation=false', + '-Dset.changelist', + 'help:evaluate', + '-Dexpression=changelist', + "-Doutput=$changelistF", + 'clean', + 'install', + ] + infra.runMaven(mavenOptions, jdk.toString(), javaOpts, null, true) + if (isUnix()) { + sh 'git add . && git diff --exit-code HEAD' + } + } + } + } - // Once we've built, archive the artifacts and the test results. - stage("${buildType} Publishing") { - if (runTests) { - junit healthScaleFactor: 20.0, testResults: '*/target/surefire-reports/*.xml,war/junit.xml' - archiveArtifacts allowEmptyArchive: true, artifacts: '**/target/surefire-reports/*.dumpstream' - if (! fileExists('core/target/surefire-reports/TEST-jenkins.Junit4TestsRanTest.xml') ) { - error 'junit 4 tests are no longer being run for the core package' - } - if (! fileExists('test/target/surefire-reports/TEST-jenkins.Junit4TestsRanTest.xml') ) { - error 'junit 4 tests are no longer being run for the test package' - } // cli has been migrated to junit 5 - if (failFast && currentBuild.result == 'UNSTABLE') { - error 'There were test failures; halting early' - } - } - if (buildType == 'Linux' && jdk == jdks[0]) { - def folders = env.JOB_NAME.split('/') - if (folders.length > 1) { - discoverGitReferenceBuild(scm: folders[1]) - } + // Once we've built, archive the artifacts and the test results. + stage("${buildType} Publishing") { + archiveArtifacts allowEmptyArchive: true, artifacts: '**/target/surefire-reports/*.dumpstream' + if (!fileExists('core/target/surefire-reports/TEST-jenkins.Junit4TestsRanTest.xml')) { + error 'JUnit 4 tests are no longer being run for the core package' + } + if (!fileExists('test/target/surefire-reports/TEST-jenkins.Junit4TestsRanTest.xml')) { + error 'JUnit 4 tests are no longer being run for the test package' + } + // cli has been migrated to JUnit 5 + if (failFast && currentBuild.result == 'UNSTABLE') { + error 'There were test failures; halting early' + } + if (buildType == 'Linux' && jdk == jdks[0]) { + def folders = env.JOB_NAME.split('/') + if (folders.length > 1) { + discoverGitReferenceBuild(scm: folders[1]) + } - echo "Recording static analysis results for '${buildType}'" - recordIssues enabledForFailure: true, - tools: [java(), javaDoc()], - filters: [excludeFile('.*Assert.java')], - sourceCodeEncoding: 'UTF-8', - skipBlames: true, - trendChartType: 'TOOLS_ONLY' - recordIssues([tool: spotBugs(pattern: '**/target/spotbugsXml.xml'), - sourceCodeEncoding: 'UTF-8', - skipBlames: true, - trendChartType: 'TOOLS_ONLY', - qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]]) - recordIssues([tool: checkStyle(pattern: '**/target/checkstyle-result.xml'), - sourceCodeEncoding: 'UTF-8', - skipBlames: true, - trendChartType: 'TOOLS_ONLY', - qualityGates: [[threshold: 1, type: 'TOTAL', unstable: true]]]) - if (failFast && currentBuild.result == 'UNSTABLE') { - error 'Static analysis quality gates not passed; halting early' - } + echo "Recording static analysis results for '${buildType}'" + recordIssues( + enabledForFailure: true, + tools: [java(), javaDoc()], + filters: [excludeFile('.*Assert.java')], + sourceCodeEncoding: 'UTF-8', + skipBlames: true, + trendChartType: 'TOOLS_ONLY' + ) + recordIssues([tool: spotBugs(pattern: '**/target/spotbugsXml.xml'), + sourceCodeEncoding: 'UTF-8', + skipBlames: true, + trendChartType: 'TOOLS_ONLY', + qualityGates: [ + [threshold: 1, type: 'NEW', unstable: true], + ]]) + recordIssues([tool: checkStyle(pattern: '**/target/checkstyle-result.xml'), + sourceCodeEncoding: 'UTF-8', + skipBlames: true, + trendChartType: 'TOOLS_ONLY', + qualityGates: [ + [threshold: 1, type: 'TOTAL', unstable: true], + ]]) + if (failFast && currentBuild.result == 'UNSTABLE') { + error 'Static analysis quality gates not passed; halting early' + } - def changelist = readFile(changelistF) - dir(m2repo) { - archiveArtifacts artifacts: "**/*$changelist/*$changelist*", - excludes: '**/*.lastUpdated,**/jenkins-test*/', - allowEmptyArchive: true, // in case we forgot to reincrementalify - fingerprint: true - } - publishHTML([allowMissing: true, alwaysLinkToLastBuild: false, includes: 'japicmp.html', keepAll: false, reportDir: 'core/target/japicmp', reportFiles: 'japicmp.html', reportName: 'API compatibility', reportTitles: 'japicmp report']) - } - } + def changelist = readFile(changelistF) + dir(m2repo) { + archiveArtifacts( + artifacts: "**/*$changelist/*$changelist*", + excludes: '**/*.lastUpdated,**/jenkins-test*/', + allowEmptyArchive: true, // in case we forgot to reincrementalify + fingerprint: true + ) + } + } } + } } -}} + } +} -// TODO: Restore ATH once https://groups.google.com/forum/#!topic/jenkinsci-dev/v9d-XosOp2s is resolved -// TODO: ATH flow now supports Java 8 only, it needs to be reworked (INFRA-1690) builds.ath = { - node("docker-highmem") { - // Just to be safe - deleteDir() - def fileUri - def metadataPath - dir("sources") { - checkout scm - def mvnCmd = 'mvn --batch-mode --show-version -ntp -Pquick-build -am -pl war package -Dmaven.repo.local=$WORKSPACE_TMP/m2repo' - infra.runWithMaven(mvnCmd, "8", javaOpts, true) - dir("war/target") { - fileUri = "file://" + pwd() + "/jenkins.war" - } - metadataPath = pwd() + "/essentials.yml" - } - dir("ath") { - runATH jenkins: fileUri, metadataFile: metadataPath - } + node('docker-highmem') { + // Just to be safe + deleteDir() + def fileUri + def metadataPath + dir('sources') { + checkout scm + def mavenOptions = [ + '-Pquick-build', + '-Dmaven.repo.local=$WORKSPACE_TMP/m2repo', + '-am', + '-pl', + 'war', + 'package', + ] + infra.runMaven(mavenOptions, '11', javaOpts, null, true) + dir('war/target') { + fileUri = 'file://' + pwd() + '/jenkins.war' + } + metadataPath = pwd() + '/essentials.yml' + } + dir('ath') { + runATH jenkins: fileUri, metadataFile: metadataPath } + } } builds.failFast = failFast diff --git a/bom/pom.xml b/bom/pom.xml index bb8ab745f8fdf..30e339c9bec3e 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -37,274 +37,262 @@ THE SOFTWARE. Jenkins BOM The module contains dependencies that are used by a specific Jenkins version - 9.2 - 1.7.32 - 1593.v0e838714faae + 1.7.36 + 1669.v95a_4b_919a_b_a_2 2.4.21 - + + com.google.inject + guice-bom + 5.0.1 + pom + import + + + org.springframework.security spring-security-bom - 5.6.0 + 5.6.2 pom import - com.github.spotbugs - spotbugs-annotations - ${spotbugs-annotations.version} + antlr + antlr + 2.7.7 - net.jcip - jcip-annotations - 1.0 + + args4j + args4j + 2.33 - org.apache.ant - ant - 1.10.12 + com.github.spotbugs + spotbugs-annotations + ${spotbugs-annotations.version} - commons-io - commons-io - 2.11.0 + com.google.guava + guava + 31.1-jre - commons-lang - commons-lang - 2.6 + + com.jcraft + jzlib + 1.1.3-kohsuke-1 - commons-httpclient - commons-httpclient - 3.1-jenkins-3 + com.sun.solaris + embedded_su4j + 1.1 - org.jenkins-ci.main - remoting - ${remoting.version} + com.sun.xml.txw2 + txw2 + 20110809 - com.google.guava - guava - 31.0.1-jre + com.thoughtworks.xstream + xstream + 1.4.19 - com.google.inject - guice-bom - 5.0.1 - pom - import + commons-beanutils + commons-beanutils + 1.9.4 - - - org.slf4j - slf4j-api - ${slf4jVersion} + commons-codec + commons-codec + 1.15 - org.slf4j - slf4j-jdk14 - ${slf4jVersion} + commons-collections + commons-collections + 3.2.2 - org.slf4j - jcl-over-slf4j - ${slf4jVersion} + commons-fileupload + commons-fileupload + 1.4 - commons-logging - commons-logging - 1.2 - provided + commons-httpclient + commons-httpclient + 3.1-jenkins-3 - org.slf4j - log4j-over-slf4j - ${slf4jVersion} + commons-io + commons-io + 2.11.0 - log4j - log4j - 1.2.17 - provided + commons-jelly + commons-jelly-tags-fmt + 1.0 - org.samba.jcifs - jcifs - 1.3.18-kohsuke-1 + commons-jelly + commons-jelly-tags-xml + 1.1 - org.kohsuke - access-modifier-annotation - ${access-modifier.version} + commons-lang + commons-lang + 2.6 - - - javax.servlet - - servlet-api - [0] - - provided - true + io.jenkins.stapler + jenkins-stapler-support + 1.1 - - commons-codec - commons-codec - 1.15 + jakarta.servlet.jsp.jstl + jakarta.servlet.jsp.jstl-api + 1.2.7 - - org.jenkins-ci - annotation-indexer - 1.15 + jaxen + jaxen + 1.2.0 - - org.jenkins-ci - version-number - 1.8 + net.java.dev.jna + jna + 5.10.0 - org.jenkins-ci - crypto-util - 1.6 + net.java.sezpoz + sezpoz + 1.13 - org.connectbot.jbcrypt - jbcrypt - 1.0.0 + net.jcip + jcip-annotations + 1.0 - org.ow2.asm - asm - ${asm.version} + net.sf.kxml + kxml2 + 2.3.0 - org.ow2.asm - asm-analysis - ${asm.version} + org.apache.ant + ant + 1.10.12 - org.ow2.asm - asm-commons - ${asm.version} + org.apache.commons + commons-compress + 1.21 - org.ow2.asm - asm-tree - ${asm.version} + org.codehaus.groovy + groovy-all + ${groovy.version} - org.ow2.asm - asm-util - ${asm.version} + org.connectbot.jbcrypt + jbcrypt + 1.0.0 - com.github.jnr - jnr-posix - 3.1.14 + + org.fusesource.jansi + jansi + 1.11 - org.kohsuke - windows-package-checker - 1.2 + org.jenkins-ci + annotation-indexer + 1.16 - - args4j - args4j - 2.33 + + org.jenkins-ci + commons-jexl + 1.1-jenkins-20111212 org.jenkins-ci - task-reactor - 1.6 + crypto-util + 1.7 - org.jvnet.localizer - localizer - 1.31 + org.jenkins-ci + memory-monitor + 1.11 - antlr - antlr - 2.7.7 + org.jenkins-ci + symbol-annotation + 1.1 - org.jfree - jfreechart - 1.0.19 + org.jenkins-ci + task-reactor + 1.7 - commons-beanutils - commons-beanutils - 1.9.4 + org.jenkins-ci + version-number + 1.9 - org.apache.commons - commons-compress - 1.21 + org.jenkins-ci.main + remoting + ${remoting.version} - commons-collections - commons-collections - 3.2.2 + org.jenkins-ci.modules + instance-identity + 2.2 - commons-fileupload - commons-fileupload - 1.4 + org.jenkins-ci.modules + launchd-slave-installer + 1.2 - com.sun.xml.txw2 - txw2 - 20110809 + org.jenkins-ci.modules + slave-installer + 1.7 - org.jvnet.winp - winp - 1.28 + org.jenkins-ci.modules + systemd-slave-installer + 1.1 - org.jenkins-ci - memory-monitor - 1.10 + org.jenkins-ci.modules + upstart-slave-installer + 1.1 - net.java.dev.jna - jna - 5.10.0 + org.jenkins-ci.modules + windows-slave-installer + 2.0 - com.sun.solaris - embedded_su4j - 1.1 + org.jfree + jfreechart + 1.0.19 - net.java.sezpoz - sezpoz - 1.13 + org.jvnet.hudson + commons-jelly-tags-define + 1.0.1-hudson-20071021 - org.kohsuke.jinterop - j-interop - 2.0.8-kohsuke-1 + org.jvnet.localizer + localizer + 1.31 org.jvnet.robust-http-client @@ -312,41 +300,30 @@ THE SOFTWARE. 1.2 - org.jenkins-ci - symbol-annotation - 1.1 + org.jvnet.winp + winp + 1.28 - com.sun.mail - jakarta.mail - 1.6.5 + org.kohsuke + access-modifier-annotation + ${access-modifier.version} - - - com.thoughtworks.xstream - xstream - 1.4.18 + org.kohsuke + windows-package-checker + 1.2 - net.sf.kxml - kxml2 - 2.3.0 + org.kohsuke.jinterop + j-interop + 2.0.8-kohsuke-1 - - - org.codehaus.groovy - groovy-all - ${groovy.version} - - - org.fusesource.jansi - jansi - 1.11 + org.kohsuke.stapler + json-lib + 2.4-jenkins-3 - - org.kohsuke.stapler stapler @@ -354,8 +331,8 @@ THE SOFTWARE. org.kohsuke.stapler - stapler-groovy - ${stapler.version} + stapler-adjunct-codemirror + 1.3 org.kohsuke.stapler @@ -364,88 +341,91 @@ THE SOFTWARE. org.kohsuke.stapler - stapler-adjunct-codemirror - 1.3 - - - io.jenkins.stapler - jenkins-stapler-support - 1.1 - - - org.kohsuke.stapler - json-lib - 2.4-jenkins-3 + stapler-groovy + ${stapler.version} - - com.jcraft - jzlib - 1.1.3-kohsuke-1 + org.ow2.asm + asm + ${asm.version} - - - commons-jelly - commons-jelly-tags-fmt - 1.0 + org.ow2.asm + asm-analysis + ${asm.version} - commons-jelly - commons-jelly-tags-xml - 1.1 + org.ow2.asm + asm-commons + ${asm.version} - org.jvnet.hudson - commons-jelly-tags-define - 1.0.1-hudson-20071021 + org.ow2.asm + asm-tree + ${asm.version} - org.jenkins-ci - commons-jexl - 1.1-jenkins-20111212 + org.ow2.asm + asm-util + ${asm.version} - jakarta.servlet.jsp.jstl - jakarta.servlet.jsp.jstl-api - 1.2.7 + org.samba.jcifs + jcifs + 1.3.18-kohsuke-1 - jaxen - jaxen - 1.2.0 + org.slf4j + jcl-over-slf4j + ${slf4jVersion} - - - org.jenkins-ci.modules - instance-identity - 2.2 + org.slf4j + log4j-over-slf4j + ${slf4jVersion} - org.jenkins-ci.modules - slave-installer - 1.7 + + org.slf4j + slf4j-api + ${slf4jVersion} - org.jenkins-ci.modules - windows-slave-installer - 2.0 + org.slf4j + slf4j-jdk14 + ${slf4jVersion} - org.jenkins-ci.modules - launchd-slave-installer + + commons-logging + commons-logging 1.2 + provided - org.jenkins-ci.modules - upstart-slave-installer - 1.1 + + + javax.servlet + + servlet-api + [0] + + provided + true - org.jenkins-ci.modules - systemd-slave-installer - 1.1 + + log4j + log4j + 1.2.17 + provided @@ -464,10 +444,10 @@ THE SOFTWARE. flatten - process-resources flatten + process-resources bom diff --git a/cli/pom.xml b/cli/pom.xml index 0a296a810e000..c67f713b0e19a 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -32,41 +32,26 @@ - org.junit.jupiter - junit-jupiter-api - ${junit.jupiter.version} - test - - - org.junit.jupiter - junit-jupiter-engine - ${junit.jupiter.version} - test - - - org.junit.jupiter - junit-jupiter - ${junit.jupiter.version} - test - - - org.kohsuke - access-modifier-annotation - provided + commons-io + commons-io + true - org.jenkins-ci - annotation-indexer + commons-lang + commons-lang true - commons-io - commons-io + + net.i2p.crypto + eddsa + 0.3.0 true - org.jvnet.localizer - localizer + org.apache.sshd + sshd-common + ${mina-sshd.version} true @@ -76,38 +61,60 @@ true - org.apache.sshd - sshd-common - ${mina-sshd.version} + org.glassfish.tyrus.bundles + tyrus-standalone-client-jdk + 2.0.1 true - - net.i2p.crypto - eddsa - 0.3.0 + org.jenkins-ci + annotation-indexer true - org.slf4j - slf4j-jdk14 + org.jvnet.localizer + localizer true - org.glassfish.tyrus.bundles - tyrus-standalone-client-jdk - 2.0.1 + org.slf4j + slf4j-jdk14 true com.github.spotbugs spotbugs-annotations provided + true + + + com.google.code.findbugs + jsr305 + + - commons-lang - commons-lang - true + org.kohsuke + access-modifier-annotation + provided + + + org.junit.jupiter + junit-jupiter + ${junit.jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-api + ${junit.jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit.jupiter.version} + test @@ -123,10 +130,10 @@ 3.2.4 - package shade + package false @@ -142,6 +149,14 @@ net io.jenkins.cli.shaded.net + + com + io.jenkins.cli.shaded.com + + + jakarta + io.jenkins.cli.shaded.jakarta + @@ -180,10 +195,10 @@ add-source - generate-sources add-source + generate-sources ${project.build.directory}/generated-sources/localizer diff --git a/cli/src/main/java/hudson/cli/CLI.java b/cli/src/main/java/hudson/cli/CLI.java index 06baf6be13e6a..a6a33c6f800e9 100644 --- a/cli/src/main/java/hudson/cli/CLI.java +++ b/cli/src/main/java/hudson/cli/CLI.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import static java.util.logging.Level.FINE; @@ -80,9 +81,10 @@ private CLI() {} * @throws NotTalkingToJenkinsException when connection is not made to Jenkins service. */ /*package*/ static void verifyJenkinsConnection(URLConnection c) throws IOException { - if (c.getHeaderField("X-Hudson")==null && c.getHeaderField("X-Jenkins")==null) + if (c.getHeaderField("X-Hudson") == null && c.getHeaderField("X-Jenkins") == null) throw new NotTalkingToJenkinsException(c); } + /*package*/ static final class NotTalkingToJenkinsException extends IOException { NotTalkingToJenkinsException(String s) { super(s); @@ -106,16 +108,17 @@ public static void main(final String[] _args) throws Exception { } } - private enum Mode {HTTP, SSH, WEB_SOCKET} + private enum Mode { HTTP, SSH, WEB_SOCKET } + public static int _main(String[] _args) throws Exception { List args = Arrays.asList(_args); PrivateKeyProvider provider = new PrivateKeyProvider(); String url = System.getenv("JENKINS_URL"); - if (url==null) + if (url == null) url = System.getenv("HUDSON_URL"); - + boolean noKeyAuth = false; // TODO perhaps allow mode to be defined by environment variable too (assuming $JENKINS_USER_ID can be used for -user) @@ -130,10 +133,10 @@ public static int _main(String[] _args) throws Exception { boolean strictHostKey = false; - while(!args.isEmpty()) { + while (!args.isEmpty()) { String head = args.get(0); if (head.equals("-version")) { - System.out.println("Version: "+computeVersion()); + System.out.println("Version: " + computeVersion()); return 0; } if (head.equals("-http")) { @@ -167,9 +170,9 @@ public static int _main(String[] _args) throws Exception { printUsage("-remoting mode is no longer supported"); return -1; } - if(head.equals("-s") && args.size()>=2) { + if (head.equals("-s") && args.size() >= 2) { url = args.get(1); - args = args.subList(2,args.size()); + args = args.subList(2, args.size()); continue; } if (head.equals("-noCertificateCheck")) { @@ -185,15 +188,15 @@ public boolean verify(String s, SSLSession sslSession) { return true; } }); - args = args.subList(1,args.size()); + args = args.subList(1, args.size()); continue; } if (head.equals("-noKeyAuth")) { - noKeyAuth = true; - args = args.subList(1,args.size()); - continue; + noKeyAuth = true; + args = args.subList(1, args.size()); + continue; } - if(head.equals("-i") && args.size()>=2) { + if (head.equals("-i") && args.size() >= 2) { File f = getFileFromArguments(args); if (!f.exists()) { printUsage(Messages.CLI_NoSuchFileExists(f)); @@ -202,7 +205,7 @@ public boolean verify(String s, SSLSession sslSession) { provider.readFrom(f); - args = args.subList(2,args.size()); + args = args.subList(2, args.size()); continue; } if (head.equals("-strictHostKey")) { @@ -239,7 +242,7 @@ public boolean verify(String s, SSLSession sslSession) { break; } - if(url==null) { + if (url == null) { printUsage(Messages.CLI_NoURL()); return -1; } @@ -263,7 +266,7 @@ public boolean verify(String s, SSLSession sslSession) { url += '/'; } - if(args.isEmpty()) + if (args.isEmpty()) args = Collections.singletonList("help"); // default to help if (mode == null) { @@ -338,6 +341,7 @@ class CLIEndpoint extends Endpoint { @Override public void onOpen(Session session, EndpointConfig config) {} } + class Authenticator extends ClientEndpointConfig.Configurator { @Override public void beforeRequest(Map> headers) { @@ -346,6 +350,7 @@ public void beforeRequest(Map> headers) { } } } + ClientManager client = ClientManager.createClient(JdkClientContainer.class.getName()); // ~ ContainerProvider.getWebSocketContainer() client.getProperties().put(ClientProperties.REDIRECT_ENABLED, true); // https://tyrus-project.github.io/documentation/1.13.1/index/tyrus-proprietary-config.html#d0e1775 Session session = client.connectToServer(new CLIEndpoint(), ClientEndpointConfig.Builder.create().configurator(new Authenticator()).build(), URI.create(url.replaceFirst("^http", "ws") + "cli/ws")); @@ -354,6 +359,7 @@ public void beforeRequest(Map> headers) { public void send(byte[] data) throws IOException { session.getBasicRemote().sendBinary(ByteBuffer.wrap(data)); } + @Override public void close() throws IOException { session.close(); @@ -479,7 +485,7 @@ private static String computeVersion() { Properties props = new Properties(); try { InputStream is = CLI.class.getResourceAsStream("/jenkins/cli/jenkins-cli-version.properties"); - if(is!=null) { + if (is != null) { try { props.load(is); } finally { @@ -489,7 +495,7 @@ private static String computeVersion() { } catch (IOException e) { e.printStackTrace(); // if the version properties is missing, that's OK. } - return props.getProperty("version","?"); + return props.getProperty("version", "?"); } /** @@ -520,7 +526,7 @@ static String usage() { } private static void printUsage(String msg) { - if(msg!=null) System.out.println(msg); + if (msg != null) System.out.println(msg); System.err.println(usage()); } diff --git a/cli/src/main/java/hudson/cli/CLIConnectionFactory.java b/cli/src/main/java/hudson/cli/CLIConnectionFactory.java index eceff79eff3c7..9b4295b07cb34 100644 --- a/cli/src/main/java/hudson/cli/CLIConnectionFactory.java +++ b/cli/src/main/java/hudson/cli/CLIConnectionFactory.java @@ -1,10 +1,11 @@ package hudson.cli; +import java.nio.charset.StandardCharsets; import java.util.Base64; /** * Fluent-API to instantiate {@link CLI}. - * + * * @author Kohsuke Kawaguchi */ public class CLIConnectionFactory { @@ -25,7 +26,7 @@ public CLIConnectionFactory authorization(String value) { * Currently unused. */ public CLIConnectionFactory basicAuth(String username, String password) { - return basicAuth(username+':'+password); + return basicAuth(username + ':' + password); } /** @@ -33,7 +34,7 @@ public CLIConnectionFactory basicAuth(String username, String password) { * Cf. {@code BasicHeaderApiTokenAuthenticator}. */ public CLIConnectionFactory basicAuth(String userInfo) { - return authorization("Basic " + Base64.getEncoder().encodeToString(userInfo.getBytes())); + return authorization("Basic " + Base64.getEncoder().encodeToString(userInfo.getBytes(StandardCharsets.UTF_8))); } /** diff --git a/cli/src/main/java/hudson/cli/DiagnosedStreamCorruptionException.java b/cli/src/main/java/hudson/cli/DiagnosedStreamCorruptionException.java index 4708b425dbb77..a701cb3033474 100644 --- a/cli/src/main/java/hudson/cli/DiagnosedStreamCorruptionException.java +++ b/cli/src/main/java/hudson/cli/DiagnosedStreamCorruptionException.java @@ -41,14 +41,14 @@ public String toString() { buf.append(super.toString()).append("\n"); buf.append("Read back: ").append(HexDump.toHex(readBack)).append('\n'); buf.append("Read ahead: ").append(HexDump.toHex(readAhead)); - if (diagnoseFailure!=null) { + if (diagnoseFailure != null) { StringWriter w = new StringWriter(); PrintWriter p = new PrintWriter(w); diagnoseFailure.printStackTrace(p); p.flush(); buf.append("\nDiagnosis problem:\n "); - buf.append(w.toString().trim().replace("\n","\n ")); + buf.append(w.toString().trim().replace("\n", "\n ")); } return buf.toString(); } diff --git a/cli/src/main/java/hudson/cli/FlightRecorderInputStream.java b/cli/src/main/java/hudson/cli/FlightRecorderInputStream.java index 4dc9700e9371e..5a1167c4fdc5d 100644 --- a/cli/src/main/java/hudson/cli/FlightRecorderInputStream.java +++ b/cli/src/main/java/hudson/cli/FlightRecorderInputStream.java @@ -52,13 +52,13 @@ public DiagnosedStreamCorruptionException analyzeCrash(Exception problem, String final ByteArrayOutputStream readAhead = new ByteArrayOutputStream(); final IOException[] error = new IOException[1]; - Thread diagnosisThread = new Thread(diagnosisName+" stream corruption diagnosis thread") { + Thread diagnosisThread = new Thread(diagnosisName + " stream corruption diagnosis thread") { @Override public void run() { int b; try { // not all InputStream will look for the thread interrupt flag, so check that explicitly to be defensive - while (!Thread.interrupted() && (b=source.read())!=-1) { + while (!Thread.interrupted() && (b = source.read()) != -1) { readAhead.write(b); } } catch (IOException e) { @@ -81,14 +81,14 @@ public void run() { if (diagnosisThread.isAlive()) diagnosisThread.interrupt(); // if it's not dead, kill - return new DiagnosedStreamCorruptionException(problem,diagnosisProblem,getRecord(),readAhead.toByteArray()); + return new DiagnosedStreamCorruptionException(problem, diagnosisProblem, getRecord(), readAhead.toByteArray()); } @Override public int read() throws IOException { int i = source.read(); - if (i>=0) + if (i >= 0) recorder.write(i); return i; } @@ -96,8 +96,8 @@ public int read() throws IOException { @Override public int read(@NonNull byte[] b, int off, int len) throws IOException { len = source.read(b, off, len); - if (len>0) - recorder.write(b,off,len); + if (len > 0) + recorder.write(b, off, len); return len; } @@ -106,8 +106,8 @@ public int read(@NonNull byte[] b, int off, int len) throws IOException { */ @Override public long skip(long n) throws IOException { - byte[] buf = new byte[(int)Math.min(n,64*1024)]; - return read(buf,0,buf.length); + byte[] buf = new byte[(int) Math.min(n, 64 * 1024)]; + return read(buf, 0, buf.length); } @Override @@ -157,7 +157,7 @@ public synchronized byte[] toByteArray() { System.arraycopy(data, 0, ret, capacity - pos, pos); return ret; } - + /** @author @roadrunner2 */ @Override public synchronized void write(@NonNull byte[] buf, int off, int len) { // no point in trying to copy more than capacity; this also simplifies logic below diff --git a/cli/src/main/java/hudson/cli/FullDuplexHttpStream.java b/cli/src/main/java/hudson/cli/FullDuplexHttpStream.java index fec9d7d3b9d3c..ae8917ab3aa6d 100644 --- a/cli/src/main/java/hudson/cli/FullDuplexHttpStream.java +++ b/cli/src/main/java/hudson/cli/FullDuplexHttpStream.java @@ -18,7 +18,7 @@ */ public class FullDuplexHttpStream { private final URL base; - + private final OutputStream output; private final InputStream input; @@ -65,7 +65,7 @@ public FullDuplexHttpStream(URL base, String relativeTarget, String authorizatio con.setDoOutput(true); // request POST to avoid caching con.setRequestMethod("POST"); con.addRequestProperty("Session", uuid.toString()); - con.addRequestProperty("Side","download"); + con.addRequestProperty("Side", "download"); if (authorization != null) { con.addRequestProperty("Authorization", authorization); } @@ -83,11 +83,11 @@ public FullDuplexHttpStream(URL base, String relativeTarget, String authorizatio con.setDoOutput(true); // request POST con.setRequestMethod("POST"); con.setChunkedStreamingMode(0); - con.setRequestProperty("Content-type","application/octet-stream"); + con.setRequestProperty("Content-type", "application/octet-stream"); con.addRequestProperty("Session", uuid.toString()); - con.addRequestProperty("Side","upload"); + con.addRequestProperty("Side", "upload"); if (authorization != null) { - con.addRequestProperty ("Authorization", authorization); + con.addRequestProperty("Authorization", authorization); } output = con.getOutputStream(); LOGGER.fine("established upload side"); @@ -118,5 +118,5 @@ private URL tryToResolveRedirects(URL base, String authorization) { static final int BLOCK_SIZE = 1024; static final Logger LOGGER = Logger.getLogger(FullDuplexHttpStream.class.getName()); - + } diff --git a/cli/src/main/java/hudson/cli/HexDump.java b/cli/src/main/java/hudson/cli/HexDump.java index ad37158bc16d0..0132f47f130da 100644 --- a/cli/src/main/java/hudson/cli/HexDump.java +++ b/cli/src/main/java/hudson/cli/HexDump.java @@ -9,13 +9,14 @@ class HexDump { private static final String CODE = "0123456789abcdef"; public static String toHex(byte[] buf) { - return toHex(buf,0,buf.length); + return toHex(buf, 0, buf.length); } + public static String toHex(byte[] buf, int start, int len) { - StringBuilder r = new StringBuilder(len*2); + StringBuilder r = new StringBuilder(len * 2); boolean inText = false; - for (int i=0; i= 0x20 && b <= 0x7e) { if (!inText) { inText = true; @@ -28,8 +29,8 @@ public static String toHex(byte[] buf, int start, int len) { inText = false; } r.append("0x"); - r.append(CODE.charAt((b>>4)&15)); - r.append(CODE.charAt(b&15)); + r.append(CODE.charAt((b >> 4) & 15)); + r.append(CODE.charAt(b & 15)); if (i < len - 1) { if (b == 10) { r.append('\n'); diff --git a/cli/src/main/java/hudson/cli/PlainCLIProtocol.java b/cli/src/main/java/hudson/cli/PlainCLIProtocol.java index 0c14433d10196..4f4fcfc49a664 100644 --- a/cli/src/main/java/hudson/cli/PlainCLIProtocol.java +++ b/cli/src/main/java/hudson/cli/PlainCLIProtocol.java @@ -73,6 +73,7 @@ private enum Op { STDERR(false); /** True if sent from the client to the server; false if sent from the server to the client. */ final boolean clientSide; + Op(boolean clientSide) { this.clientSide = clientSide; } @@ -233,10 +234,12 @@ protected final OutputStream stream(final Op op) { public void write(int b) throws IOException { send(op, new byte[] {(byte) b}); } + @Override public void write(@NonNull byte[] b, int off, int len) throws IOException { send(op, b, off, len); } + @Override public void write(@NonNull byte[] b) throws IOException { send(op, b); diff --git a/cli/src/main/java/hudson/cli/PrivateKeyProvider.java b/cli/src/main/java/hudson/cli/PrivateKeyProvider.java index 1ab1eff330498..64c84fc2074de 100644 --- a/cli/src/main/java/hudson/cli/PrivateKeyProvider.java +++ b/cli/src/main/java/hudson/cli/PrivateKeyProvider.java @@ -21,9 +21,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; -import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.logging.Level.FINE; import java.io.ByteArrayInputStream; @@ -32,6 +32,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Paths; @@ -110,15 +111,15 @@ public void readFrom(File keyFile) throws IOException, GeneralSecurityException privateKeys.add(loadKey(keyFile, password)); } - private static boolean isPemEncrypted(File f) throws IOException{ + private static boolean isPemEncrypted(File f) throws IOException { //simple check if the file is encrypted return readPemFile(f).contains("4,ENCRYPTED"); } - private static String askForPasswd(String filePath){ + private static String askForPasswd(String filePath) { Console cons = System.console(); String passwd = null; - if (cons != null){ + if (cons != null) { char[] p = cons.readPassword("%s", "Enter passphrase for " + filePath + ":"); passwd = String.valueOf(p); } @@ -129,12 +130,12 @@ public static KeyPair loadKey(File f, String passwd) throws IOException, General return loadKey(readPemFile(f), passwd); } - private static String readPemFile(File f) throws IOException{ + private static String readPemFile(File f) throws IOException { try (InputStream is = Files.newInputStream(f.toPath()); DataInputStream dis = new DataInputStream(is)) { byte[] bytes = new byte[(int) f.length()]; dis.readFully(bytes); - return new String(bytes); + return new String(bytes, StandardCharsets.UTF_8); } catch (InvalidPathException e) { throw new IOException(e); } @@ -143,7 +144,7 @@ private static String readPemFile(File f) throws IOException{ public static KeyPair loadKey(String pemString, String passwd) throws IOException, GeneralSecurityException { Iterable itr = SecurityUtils.loadKeyPairIdentities(null, new PathResource(Paths.get("key")), - new ByteArrayInputStream(pemString.getBytes(UTF_8)), + new ByteArrayInputStream(pemString.getBytes(StandardCharsets.UTF_8)), FilePasswordProvider.of(passwd)); long numLoaded = itr == null ? 0 : StreamSupport.stream(itr.spliterator(), false).count(); if (numLoaded <= 0) { diff --git a/cli/src/main/java/hudson/cli/SSHCLI.java b/cli/src/main/java/hudson/cli/SSHCLI.java index d9fa4911df84c..5badd296fbf0e 100644 --- a/cli/src/main/java/hudson/cli/SSHCLI.java +++ b/cli/src/main/java/hudson/cli/SSHCLI.java @@ -85,7 +85,7 @@ static int sshConnection(String jenkinsUrl, String user, List args, Priv command.append(' '); } - try(SshClient client = SshClient.setUpDefaultClient()) { + try (SshClient client = SshClient.setUpDefaultClient()) { KnownHostsServerKeyVerifier verifier = new DefaultKnownHostsServerKeyVerifier(new ServerKeyVerifier() { @Override @@ -116,7 +116,7 @@ public boolean verifyServerKey(ClientSession clientSession, SocketAddress remote Set waitMask = channel.waitFor(Collections.singletonList(ClientChannelEvent.CLOSED), 0L); - if(waitMask.contains(ClientChannelEvent.TIMEOUT)) { + if (waitMask.contains(ClientChannelEvent.TIMEOUT)) { throw new SocketTimeoutException("Failed to retrieve command result in time: " + command); } diff --git a/cli/src/main/java/hudson/util/QuotedStringTokenizer.java b/cli/src/main/java/hudson/util/QuotedStringTokenizer.java index 6b8a6f43f7811..6f77b758bc1f3 100644 --- a/cli/src/main/java/hudson/util/QuotedStringTokenizer.java +++ b/cli/src/main/java/hudson/util/QuotedStringTokenizer.java @@ -33,6 +33,7 @@ // See the License for the specific language governing permissions and // limitations under the License. // ======================================================================== + package hudson.util; import java.util.ArrayList; @@ -55,24 +56,24 @@ public class QuotedStringTokenizer extends StringTokenizer { - private static final String __delim=" \t\n\r"; + private static final String __delim = " \t\n\r"; private String _string; private String _delim = __delim; - private boolean _returnQuotes=false; - private boolean _returnDelimiters=false; + private boolean _returnQuotes = false; + private boolean _returnDelimiters = false; private StringBuilder _token; - private boolean _hasToken=false; - private int _i=0; - private int _lastStart=0; - private boolean _double=true; - private boolean _single=true; + private boolean _hasToken = false; + private int _i = 0; + private int _lastStart = 0; + private boolean _double = true; + private boolean _single = true; public static String[] tokenize(String str) { return new QuotedStringTokenizer(str).toArray(); } public static String[] tokenize(String str, String delimiters) { - return new QuotedStringTokenizer(str,delimiters).toArray(); + return new QuotedStringTokenizer(str, delimiters).toArray(); } /* ------------------------------------------------------------ */ @@ -94,17 +95,17 @@ public QuotedStringTokenizer(String str, boolean returnQuotes) { super(""); - _string=str; - if (delim!=null) - _delim=delim; - _returnDelimiters=returnDelimiters; - _returnQuotes=returnQuotes; + _string = str; + if (delim != null) + _delim = delim; + _returnDelimiters = returnDelimiters; + _returnQuotes = returnQuotes; - if (_delim.indexOf('\'')>=0 || - _delim.indexOf('"')>=0) - throw new Error("Can't use quotes as delimiters: "+_delim); + if (_delim.indexOf('\'') >= 0 || + _delim.indexOf('"') >= 0) + throw new Error("Can't use quotes as delimiters: " + _delim); - _token=new StringBuilder(_string.length()>1024?512:_string.length()/2); + _token = new StringBuilder(_string.length() > 1024 ? 512 : _string.length() / 2); } /* ------------------------------------------------------------ */ @@ -112,25 +113,25 @@ public QuotedStringTokenizer(String str, String delim, boolean returnDelimiters) { - this(str,delim,returnDelimiters,false); + this(str, delim, returnDelimiters, false); } /* ------------------------------------------------------------ */ public QuotedStringTokenizer(String str, String delim) { - this(str,delim,false,false); + this(str, delim, false, false); } /* ------------------------------------------------------------ */ public QuotedStringTokenizer(String str) { - this(str,null,false,false); + this(str, null, false, false); } public String[] toArray() { List r = new ArrayList<>(); - while(hasMoreTokens()) + while (hasMoreTokens()) r.add(nextToken()); return r.toArray(new String[r.size()]); } @@ -144,75 +145,75 @@ public boolean hasMoreTokens() if (_hasToken) return true; - _lastStart=_i; + _lastStart = _i; - int state=0; - boolean escape=false; - while (_i<_string.length()) + int state = 0; + boolean escape = false; + while (_i < _string.length()) { - char c=_string.charAt(_i++); + char c = _string.charAt(_i++); switch (state) { case 0: // Start - if(_delim.indexOf(c)>=0) + if (_delim.indexOf(c) >= 0) { if (_returnDelimiters) { _token.append(c); - return _hasToken=true; + return _hasToken = true; } } - else if (c=='\'' && _single) + else if (c == '\'' && _single) { if (_returnQuotes) _token.append(c); - state=2; + state = 2; } - else if (c=='\"' && _double) + else if (c == '\"' && _double) { if (_returnQuotes) _token.append(c); - state=3; + state = 3; } else { _token.append(c); - _hasToken=true; - state=1; + _hasToken = true; + state = 1; } continue; case 1: // Token - _hasToken=true; + _hasToken = true; if (escape) { - escape=false; - if(ESCAPABLE_CHARS.indexOf(c)<0) + escape = false; + if (ESCAPABLE_CHARS.indexOf(c) < 0) _token.append('\\'); _token.append(c); } - else if(_delim.indexOf(c)>=0) + else if (_delim.indexOf(c) >= 0) { if (_returnDelimiters) _i--; return _hasToken; } - else if (c=='\'' && _single) + else if (c == '\'' && _single) { if (_returnQuotes) _token.append(c); - state=2; + state = 2; } - else if (c=='\"' && _double) + else if (c == '\"' && _double) { if (_returnQuotes) _token.append(c); - state=3; + state = 3; } - else if (c=='\\') + else if (c == '\\') { - escape=true; + escape = true; } else _token.append(c); @@ -220,25 +221,25 @@ else if (c=='\\') case 2: // Single Quote - _hasToken=true; + _hasToken = true; if (escape) { - escape=false; - if(ESCAPABLE_CHARS.indexOf(c)<0) + escape = false; + if (ESCAPABLE_CHARS.indexOf(c) < 0) _token.append('\\'); _token.append(c); } - else if (c=='\'') + else if (c == '\'') { if (_returnQuotes) _token.append(c); - state=1; + state = 1; } - else if (c=='\\') + else if (c == '\\') { if (_returnQuotes) _token.append(c); - escape=true; + escape = true; } else _token.append(c); @@ -246,25 +247,25 @@ else if (c=='\\') case 3: // Double Quote - _hasToken=true; + _hasToken = true; if (escape) { - escape=false; - if(ESCAPABLE_CHARS.indexOf(c)<0) + escape = false; + if (ESCAPABLE_CHARS.indexOf(c) < 0) _token.append('\\'); _token.append(c); } - else if (c=='\"') + else if (c == '\"') { if (_returnQuotes) _token.append(c); - state=1; + state = 1; } - else if (c=='\\') + else if (c == '\\') { if (_returnQuotes) _token.append(c); - escape=true; + escape = true; } else _token.append(c); @@ -283,11 +284,11 @@ else if (c=='\\') public String nextToken() throws NoSuchElementException { - if (!hasMoreTokens() || _token==null) + if (!hasMoreTokens() || _token == null) throw new NoSuchElementException(); - String t=_token.toString(); + String t = _token.toString(); _token.setLength(0); - _hasToken=false; + _hasToken = false; return t; } @@ -296,10 +297,10 @@ public String nextToken() public String nextToken(String delim) throws NoSuchElementException { - _delim=delim; - _i=_lastStart; + _delim = delim; + _i = _lastStart; _token.setLength(0); - _hasToken=false; + _hasToken = false; return nextToken(); } @@ -338,19 +339,19 @@ public int countTokens() */ public static String quote(String s, String delim) { - if (s==null) + if (s == null) return null; - if (s.length()==0) + if (s.length() == 0) return "\"\""; - for (int i=0;i=0) + if (c == '\\' || c == '"' || c == '\'' || Character.isWhitespace(c) || delim.indexOf(c) >= 0) { - StringBuffer b=new StringBuffer(s.length()+8); - quote(b,s); + StringBuffer b = new StringBuffer(s.length() + 8); + quote(b, s); return b.toString(); } } @@ -368,13 +369,13 @@ public static String quote(String s, String delim) */ public static String quote(String s) { - if (s==null) + if (s == null) return null; - if (s.length()==0) + if (s.length() == 0) return "\"\""; - StringBuffer b=new StringBuffer(s.length()+8); - quote(b,s); + StringBuffer b = new StringBuffer(s.length() + 8); + quote(b, s); return b.toString(); } @@ -388,13 +389,13 @@ public static String quote(String s) */ public static void quote(StringBuffer buf, String s) { - synchronized(buf) + synchronized (buf) { buf.append('"'); - for (int i=0;i= '0' && b <= '9') return (byte) (b - '0'); if (b >= 'a' && b <= 'f') return (byte) (b - 'a' + 10); @@ -546,7 +547,7 @@ public static byte convertHexDigit( byte b ) * * Others, like, say, \W will be left alone instead of becoming just W. * This is important to keep Hudson behave on Windows, which uses '\' as - * the directory separator. + * the directory separator. */ private static final String ESCAPABLE_CHARS = "\\\"' "; } diff --git a/cli/src/main/resources/hudson/cli/client/Messages_pt_BR.properties b/cli/src/main/resources/hudson/cli/client/Messages_pt_BR.properties index 84f4b80bb04d7..b2a4bfac065a8 100644 --- a/cli/src/main/resources/hudson/cli/client/Messages_pt_BR.properties +++ b/cli/src/main/resources/hudson/cli/client/Messages_pt_BR.properties @@ -20,17 +20,17 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -CLI.VersionMismatch=A vers\u00e3o n\u00e3o coincide. Esta CLI n\u00e3o pode funcionar com este servidor Jenkins CLI.Usage=Jenkins CLI\n\ - Uso: java -jar jenkins-cli.jar [-s URL] comando [op\u00e7\u00f5es...] par\u00e2metros...\n\ - Op\u00e7\u00f5es:\n\ - -s URL : a URL do servidor (por padr\u00e3o a vari\u00e1vel de ambiente JENKINS_URL \u00e9 usada)\n\ - -i KEY : arquivo contendo a chave SSH privada usada para autentica\u00e7\u00e3o\n\ + Uso: java -jar jenkins-cli.jar [-s URL] comando [op\u00E7\u00F5es...] par\u00E2metros...\n\ + Op\u00E7\u00F5es:\n\ + -s URL : a URL do servidor (por padr\u00E3o a vari\u00E1vel de ambiente JENKINS_URL \u00E9 usada)\n\ + -i KEY : arquivo contendo a chave SSH privada usada para autentica\u00E7\u00E3o\n\ -p HOST:PORT : host e porta do proxy HTTP para tunelamento de proxy HTTPS. Veja https://www.jenkins.io/redirect/cli-https-proxy-tunnel\n\ - -noCertificateCheck : ignora completamente a valida\u00e7\u00e3o dos certificados HTTPS. Use com cautela\n\ - -noKeyAuth : n\u00e3o tenta carregar a chave privada para autentica\u00e7\u00e3o SSH. Conflita com -i\n\ + -noCertificateCheck : ignora completamente a valida\u00E7\u00E3o dos certificados HTTPS. Use com cautela\n\ + -noKeyAuth : n\u00E3o tenta carregar a chave privada para autentica\u00E7\u00E3o SSH. Conflita com -i\n\ \n\ - Os comandos dispon\u00edveis dependem do servidor. Execute o comando 'help' para\n\ + Os comandos dispon\u00EDveis dependem do servidor. Execute o comando 'help' para\n\ ver a lista. -CLI.NoURL=N\u00e3o foi especificado nem '-s' e nem a vari\u00e1vel de ambiente JENKINS_URL -CLI.NoSuchFileExists=O arquivo n\u00e3o existe: {0} +CLI.NoURL=N\u00E3o foi especificado nem '-s' e nem a vari\u00E1vel de ambiente JENKINS_URL +CLI.NoSuchFileExists=O arquivo n\u00E3o existe: {0} +CLI.BadAuth=As vari\u00E1veis de ambiente JENKINS_USER_ID e JENKINS_API_TOKEN precisam ser ambas configuradas ou deixadas vazias. diff --git a/cli/src/test/java/hudson/cli/HexDumpTest.java b/cli/src/test/java/hudson/cli/HexDumpTest.java index 52b6c2e631f41..9e15de1453cbc 100644 --- a/cli/src/test/java/hudson/cli/HexDumpTest.java +++ b/cli/src/test/java/hudson/cli/HexDumpTest.java @@ -24,9 +24,9 @@ public void testToHex1(String expected, byte[] buf) { static Stream testToHex1Sources() { return Stream.of( arguments("'fooBar'", new byte[] {'f', 'o', 'o', 'B', 'a', 'r'}), - arguments("0xc3", new byte[] {(byte)'Ã'}), - arguments("0xac '100'", new byte[] {(byte)'€', '1', '0', '0'}), - arguments("'1' 0xf7 '2'", new byte[] {'1', (byte)'÷', '2'}), + arguments("0xc3", new byte[] {(byte) 'Ã'}), + arguments("0xac '100'", new byte[] {(byte) '€', '1', '0', '0'}), + arguments("'1' 0xf7 '2'", new byte[] {'1', (byte) '÷', '2'}), arguments("'foo' 0x0a\n'Bar'", new byte[] {'f', 'o', 'o', '\n', 'B', 'a', 'r'}) ); } @@ -41,9 +41,9 @@ public void testToHex2(String expected, byte[] buf, int start, int len) { static Stream testToHex2Sources() { return Stream.of( arguments("'ooBa'", new byte[] {'f', 'o', 'o', 'B', 'a', 'r'}, 1, 4), - arguments("0xc3", new byte[] {(byte)'Ã'}, 0, 1), - arguments("0xac '10'", new byte[] {(byte)'€', '1', '0', '0'}, 0, 3), - arguments("0xf7 '2'", new byte[] {'1', (byte)'÷', '2'}, 1, 2), + arguments("0xc3", new byte[] {(byte) 'Ã'}, 0, 1), + arguments("0xac '10'", new byte[] {(byte) '€', '1', '0', '0'}, 0, 3), + arguments("0xf7 '2'", new byte[] {'1', (byte) '÷', '2'}, 1, 2), arguments("'Bar'", new byte[] {'f', 'o', 'o', '\n', 'B', 'a', 'r'}, 4, 3), arguments("", new byte[] {'f', 'o', 'o', 'B', 'a', 'r'}, 0, 0) ); diff --git a/cli/src/test/java/hudson/cli/PlainCLIProtocolTest.java b/cli/src/test/java/hudson/cli/PlainCLIProtocolTest.java index 3eb29728fd71b..98a4fefd8001f 100644 --- a/cli/src/test/java/hudson/cli/PlainCLIProtocolTest.java +++ b/cli/src/test/java/hudson/cli/PlainCLIProtocolTest.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; +import java.nio.charset.Charset; import org.junit.jupiter.api.Test; public class PlainCLIProtocolTest { @@ -42,27 +43,34 @@ public void ignoreUnknownOperations() throws Exception { class Client extends PlainCLIProtocol.ClientSide { int code = -1; final ByteArrayOutputStream stdout = new ByteArrayOutputStream(); + Client() throws IOException { super(new PlainCLIProtocol.FramedOutput(upload)); } + @Override protected synchronized void onExit(int code) { this.code = code; notifyAll(); } + @Override protected void onStdout(byte[] chunk) throws IOException { stdout.write(chunk); } + @Override protected void onStderr(byte[] chunk) throws IOException {} + @Override protected void handleClose() {} + void send() throws IOException { sendArg("command"); sendStart(); - streamStdin().write("hello".getBytes()); + streamStdin().write("hello".getBytes(Charset.defaultCharset())); } + void newop() throws IOException { DataOutputStream dos = new DataOutputStream(upload); dos.writeInt(0); @@ -70,26 +78,33 @@ void newop() throws IOException { dos.flush(); } } + class Server extends PlainCLIProtocol.ServerSide { String arg; boolean started; final ByteArrayOutputStream stdin = new ByteArrayOutputStream(); + Server() throws IOException { super(new PlainCLIProtocol.FramedOutput(download)); } + @Override protected void onArg(String text) { arg = text; } + @Override protected void onLocale(String text) {} + @Override protected void onEncoding(String text) {} + @Override protected synchronized void onStart() { started = true; notifyAll(); } + @Override protected void onStdin(byte[] chunk) throws IOException { /* To inject a race condition: @@ -101,14 +116,18 @@ protected void onStdin(byte[] chunk) throws IOException { */ stdin.write(chunk); } + @Override protected void onEndStdin() throws IOException {} + @Override protected void handleClose() {} + void send() throws IOException { - streamStdout().write("goodbye".getBytes()); + streamStdout().write("goodbye".getBytes(Charset.defaultCharset())); sendExit(2); } + void newop() throws IOException { DataOutputStream dos = new DataOutputStream(download); dos.writeInt(0); @@ -116,6 +135,7 @@ void newop() throws IOException { dos.flush(); } } + Client client = new Client(); Server server = new Server(); new PlainCLIProtocol.FramedReader(client, new PipedInputStream(download)).start(); @@ -137,9 +157,9 @@ void newop() throws IOException { while (server.stdin.size() == 0) { Thread.sleep(100); } - assertEquals("hello", server.stdin.toString()); + assertEquals("hello", server.stdin.toString(Charset.defaultCharset().name())); assertEquals("command", server.arg); - assertEquals("goodbye", client.stdout.toString()); + assertEquals("goodbye", client.stdout.toString(Charset.defaultCharset().name())); assertEquals(2, client.code); } diff --git a/cli/src/test/java/hudson/cli/PrivateKeyProviderTest.java b/cli/src/test/java/hudson/cli/PrivateKeyProviderTest.java index 9205c853f8ce2..8d960e87a4611 100644 --- a/cli/src/test/java/hudson/cli/PrivateKeyProviderTest.java +++ b/cli/src/test/java/hudson/cli/PrivateKeyProviderTest.java @@ -50,7 +50,7 @@ public void loadKeyDSAPassword() throws IOException, GeneralSecurityException { String password = "password"; assertKeyPairNotNull(file, password); } - + /** key command: ssh-keygen -f rsa -t rsa -b 1024 -m PEM */ @@ -69,7 +69,7 @@ public void loadKeyRSAPassword() throws IOException, GeneralSecurityException { String password = "password"; assertKeyPairNotNull(file, password); } - + /** key command: ssh-keygen -f openssh -t rsa -b 1024 */ @@ -78,7 +78,7 @@ public void loadKeyOpenSSH() throws IOException, GeneralSecurityException { File file = new File(this.getClass().getResource("openssh").getFile()); assertKeyPairNotNull(file, null); } - + /** key command: ssh-keygen -f openssh-unsupported -t rsa -b 1024 -m PKCS8 -p password */ @@ -123,7 +123,7 @@ public void loadBlankKey() throws IOException, GeneralSecurityException { /** key command: ssh-keygen -f openssh -t rsa -b 1024 in this key we remove some lines to break the key. - */ + */ @Test public void loadKeyBroken() throws IOException, GeneralSecurityException { File file = new File(this.getClass().getResource("openssh-broken").getFile()); diff --git a/cli/src/test/java/hudson/util/QuotedStringTokenizerTest.java b/cli/src/test/java/hudson/util/QuotedStringTokenizerTest.java index 9af792ca7b2fb..e5c546d11c3ee 100644 --- a/cli/src/test/java/hudson/util/QuotedStringTokenizerTest.java +++ b/cli/src/test/java/hudson/util/QuotedStringTokenizerTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.util; import static org.junit.jupiter.api.Assertions.assertArrayEquals; @@ -38,19 +39,19 @@ public class QuotedStringTokenizerTest { @Test public void test1() { check("foo bar", - "foo","bar"); + "foo", "bar"); } @Test public void test2() { check("foo \"bar zot\"", - "foo","bar zot"); + "foo", "bar zot"); } @Test public void test3() { check("foo bar=\"quote zot\"", - "foo","bar=quote zot"); + "foo", "bar=quote zot"); } @Test @@ -68,7 +69,7 @@ public void test5() { @Test public void test6() { check("foo\\\\ bar", - "foo\\","bar"); + "foo\\", "bar"); } // see http://www.nabble.com/Error-parsing-%22-in-msbuild-task-to20535754.html diff --git a/core/pom.xml b/core/pom.xml index b85438f1c60bf..5e35d68b41875 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -41,7 +41,7 @@ THE SOFTWARE. true 2.2 - 2.8.3 + 2.9.0 @@ -56,34 +56,52 @@ THE SOFTWARE. - ${project.groupId} - remoting + cli + ${project.version} ${project.groupId} - cli - ${project.version} + remoting - org.jenkins-ci - version-number + antlr + antlr - org.jenkins-ci - crypto-util + args4j + args4j - - - org.jenkins-ci - core-annotation-processors - 1.0 - provided - true + + com.github.spotbugs + spotbugs-annotations + + + com.google.code.findbugs + jsr305 + + + + + com.google.guava + guava + + + com.google.errorprone + error_prone_annotations + + + com.google.j2objc + j2objc-annotations + + + org.checkerframework + checker-qual + + - com.google.inject guice @@ -95,232 +113,291 @@ THE SOFTWARE. - - org.connectbot.jbcrypt - jbcrypt + com.infradna.tool + bridge-method-annotation + ${bridge-method-injector.version} - com.github.jnr - jnr-posix + + com.jcraft + jzlib - org.ow2.asm - asm + com.sun.solaris + embedded_su4j - org.ow2.asm - asm-analysis + com.sun.xml.txw2 + txw2 + + + + javax.xml.stream + stax-api + + - org.ow2.asm - asm-commons + com.thoughtworks.xstream + xstream + + + xmlpull + xmlpull + + + xpp3 + xpp3_min + + - org.ow2.asm - asm-tree + commons-beanutils + commons-beanutils - org.ow2.asm - asm-util + commons-codec + commons-codec - org.kohsuke.stapler - stapler - - - com.google.code.findbugs - jsr305 - - + commons-collections + commons-collections - org.kohsuke.stapler - stapler-groovy + commons-fileupload + commons-fileupload + + + commons-httpclient + commons-httpclient + + + commons-io + commons-io + + + commons-jelly + commons-jelly-tags-fmt + + + commons-jelly + commons-jelly-tags-xml commons-jelly commons-jelly + + commons-jelly + commons-jelly-tags-junit + commons-jexl commons-jexl - org.jvnet.hudson - commons-jexl + dom4j + dom4j - - org.codehaus.groovy - groovy + xalan + xalan + + + xerces + xercesImpl + + + xml-apis + xml-apis - org.kohsuke - windows-package-checker + + commons-lang + commons-lang - org.kohsuke.stapler - stapler-adjunct-timeline + io.jenkins.stapler + jenkins-stapler-support - org.kohsuke.stapler - stapler-adjunct-codemirror + + jakarta.servlet.jsp.jstl + jakarta.servlet.jsp.jstl-api - - org.kohsuke.stapler - stapler-adjunct-timeline - 1.5 - tests - test + + jaxen + jaxen + + + dom4j + dom4j + + + jdom + jdom + + + xerces + xercesImpl + + + xml-apis + xml-apis + + + xom + xom + + - io.jenkins.stapler - jenkins-stapler-support + + jline + jline + 2.14.6 + compile - org.hamcrest - hamcrest - ${hamcrest.version} - test + net.java.dev.jna + jna - org.hamcrest - hamcrest-library - ${hamcrest.version} - test + net.java.sezpoz + sezpoz - - com.infradna.tool - bridge-method-annotation - ${bridge-method-injector.version} + net.jcip + jcip-annotations - - - org.kohsuke.stapler - json-lib + + net.sf.kxml + kxml2 - commons-httpclient - commons-httpclient + org.apache.ant + ant - args4j - args4j + org.apache.commons + commons-compress + + + org.codehaus.groovy + groovy-all + + + org.connectbot.jbcrypt + jbcrypt + + + + org.fusesource.jansi + jansi org.jenkins-ci annotation-indexer + + org.jenkins-ci + commons-jexl + + + org.jenkins-ci + crypto-util + + + org.jenkins-ci + memory-monitor + + + org.jenkins-ci + symbol-annotation + org.jenkins-ci task-reactor - org.jvnet.localizer - localizer + org.jenkins-ci + version-number - antlr - antlr + org.jfree + jfreechart - com.thoughtworks.xstream - xstream + org.jvnet.hudson + commons-jelly-tags-define - xmlpull - xmlpull + commons-cli + commons-cli - xpp3 - xpp3_min + dom4j + dom4j + + + org.jvnet.hudson + commons-jelly - - xpp3 - xpp3 - 1.1.4c + org.jvnet.localizer + localizer - net.sf.kxml - kxml2 + org.jvnet.robust-http-client + robust-http-client - org.jfree - jfreechart + org.jvnet.winp + winp - org.apache.ant - ant + org.kohsuke + access-modifier-annotation - javax.servlet - javax.servlet-api - 3.1.0 - provided + org.kohsuke + windows-package-checker - commons-io - commons-io - - - commons-lang - commons-lang + org.kohsuke.jinterop + j-interop - commons-beanutils - commons-beanutils + + org.kohsuke.metainf-services + metainf-services + 1.8 + true - org.apache.commons - commons-compress + org.kohsuke.stapler + json-lib - com.sun.mail - jakarta.mail + org.kohsuke.stapler + stapler - jaxen - jaxen - - - dom4j - dom4j - - - xom - xom - - - xml-apis - xml-apis - - - xerces - xercesImpl - - - jdom - jdom - - + org.kohsuke.stapler + stapler-adjunct-codemirror - commons-jelly - commons-jelly-tags-fmt + org.kohsuke.stapler + stapler-adjunct-timeline - commons-jelly - commons-jelly-tags-xml + org.kohsuke.stapler + stapler-groovy commons-jelly @@ -331,48 +408,43 @@ THE SOFTWARE. commons-jexl - commons-jelly - commons-jelly-tags-junit - - - xml-apis - xml-apis - - - xalan - xalan - - - xerces - xercesImpl + + org.codehaus.groovy + groovy - dom4j - dom4j + org.jvnet.hudson + commons-jexl - org.jvnet.hudson - commons-jelly-tags-define - - - dom4j - dom4j - - - commons-cli - commons-cli - - - org.jvnet.hudson - commons-jelly - - + org.ow2.asm + asm - org.jenkins-ci - commons-jexl + org.ow2.asm + asm-analysis + + + org.ow2.asm + asm-commons + + + org.ow2.asm + asm-tree + + + org.ow2.asm + asm-util + + + org.slf4j + jcl-over-slf4j + + + org.slf4j + log4j-over-slf4j org.springframework.security @@ -385,24 +457,59 @@ THE SOFTWARE. - org.codehaus.groovy - groovy-all + + xpp3 + xpp3 + 1.1.4c - - jline - jline - 2.14.6 - compile + + javax.servlet + javax.servlet-api + 3.1.0 + provided - - org.fusesource.jansi - jansi + + + org.jenkins-ci + core-annotation-processors + 1.0 + provided + true + + + + + org.hamcrest + hamcrest + ${hamcrest.version} + test + + + org.hamcrest + hamcrest-library + ${hamcrest.version} + test org.jenkins-ci test-annotations test + + org.junit.jupiter + junit-jupiter + ${junit.jupiter.version} + test + org.junit.jupiter junit-jupiter-api @@ -422,9 +529,11 @@ THE SOFTWARE. test - org.junit.jupiter - junit-jupiter - ${junit.jupiter.version} + + org.kohsuke.stapler + stapler-adjunct-timeline + 1.5 + tests test @@ -433,135 +542,11 @@ THE SOFTWARE. ${mockito.version} test - - jakarta.servlet.jsp.jstl - jakarta.servlet.jsp.jstl-api - - - org.slf4j - jcl-over-slf4j - - - org.slf4j - log4j-over-slf4j - org.slf4j slf4j-jdk14 test - - com.sun.xml.txw2 - txw2 - - - - javax.xml.stream - stax-api - - - - - commons-collections - commons-collections - - - org.jvnet.winp - winp - - - org.jenkins-ci - memory-monitor - - - net.java.dev.jna - jna - - - com.sun.solaris - embedded_su4j - - - net.java.sezpoz - sezpoz - - - org.kohsuke.jinterop - j-interop - - - org.kohsuke.metainf-services - metainf-services - 1.8 - true - - - org.jvnet.robust-http-client - robust-http-client - - - org.jenkins-ci - symbol-annotation - - - - commons-codec - commons-codec - - - - org.kohsuke - access-modifier-annotation - - - - com.github.spotbugs - spotbugs-annotations - true - - - net.jcip - jcip-annotations - true - - - - commons-fileupload - commons-fileupload - - - - - - - com.google.guava - guava - - - com.google.errorprone - error_prone_annotations - - - com.google.j2objc - j2objc-annotations - - - org.checkerframework - checker-qual - - - - - - com.jcraft - jzlib - org.xmlunit xmlunit-core @@ -585,10 +570,10 @@ THE SOFTWARE. add-source - generate-sources add-source + generate-sources ${project.build.directory}/generated-sources/antlr @@ -641,7 +626,8 @@ THE SOFTWARE. maven-stapler-plugin - ${staplerFork} + + ${staplerFork} 128m @@ -706,11 +692,11 @@ THE SOFTWARE. winsw - generate-resources copy + generate-resources @@ -735,7 +721,8 @@ THE SOFTWARE. false - + + maven-jar-plugin @@ -753,7 +740,8 @@ THE SOFTWARE. - + + org.kohsuke.stapler maven-stapler-plugin @@ -763,7 +751,8 @@ THE SOFTWARE. - + + maven-project-info-reports-plugin @@ -830,37 +819,17 @@ THE SOFTWARE. - japicmp + jdk-9-and-above + + [9,) + - com.github.siom79.japicmp - japicmp-maven-plugin - 0.14.4-20200728.214757-1 + maven-surefire-plugin - - - \d+[.]\d+ - - true - - - - javax.servlet - javax.servlet-api - 3.1.0 - provided - - + --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED - - - verify - - cmp - - - diff --git a/core/src/main/java/hudson/AbortException.java b/core/src/main/java/hudson/AbortException.java index b68276e8eec12..d3d58122c87ee 100644 --- a/core/src/main/java/hudson/AbortException.java +++ b/core/src/main/java/hudson/AbortException.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import java.io.IOException; diff --git a/core/src/main/java/hudson/AboutJenkins.java b/core/src/main/java/hudson/AboutJenkins.java index c94bbb48f7c36..8f355b21b0308 100644 --- a/core/src/main/java/hudson/AboutJenkins.java +++ b/core/src/main/java/hudson/AboutJenkins.java @@ -14,14 +14,14 @@ /** * Show "About Jenkins" link. - * + * * @author Kohsuke Kawaguchi */ @Extension @Symbol("about") public class AboutJenkins extends ManagementLink { @Override public String getIconFileName() { - return "help.png"; + return "symbol-jenkins"; } @Override diff --git a/core/src/main/java/hudson/AbstractMarkupText.java b/core/src/main/java/hudson/AbstractMarkupText.java index 59e65e9bcba02..b13eeaad3edd0 100644 --- a/core/src/main/java/hudson/AbstractMarkupText.java +++ b/core/src/main/java/hudson/AbstractMarkupText.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import hudson.MarkupText.SubText; @@ -74,15 +75,15 @@ public final int length() { * For example, if the text was "abc", then {@code addMarkup(1,2,"","")} * would generate {@code "abc"} */ - public abstract void addMarkup( int startPos, int endPos, String startTag, String endTag ); + public abstract void addMarkup(int startPos, int endPos, String startTag, String endTag); /** * Inserts an A tag that surrounds the given position. * * @since 1.349 */ - public void addHyperlink( int startPos, int endPos, String url ) { - addMarkup(startPos,endPos,"",""); + public void addHyperlink(int startPos, int endPos, String url) { + addMarkup(startPos, endPos, "", ""); } /** @@ -91,22 +92,22 @@ public void addHyperlink( int startPos, int endPos, String url ) { * * @since 1.395 */ - public void addHyperlinkLowKey( int startPos, int endPos, String url ) { - addMarkup(startPos,endPos,"",""); + public void addHyperlinkLowKey(int startPos, int endPos, String url) { + addMarkup(startPos, endPos, "", ""); } /** * Hides the given text. */ - public void hide( int startPos, int endPos ) { - addMarkup(startPos,endPos,"",""); + public void hide(int startPos, int endPos) { + addMarkup(startPos, endPos, "", ""); } /** * Adds a start tag and end tag around the entire text */ public final void wrapBy(String startTag, String endTag) { - addMarkup(0,length(),startTag,endTag); + addMarkup(0, length(), startTag, endTag); } /** @@ -118,7 +119,7 @@ public MarkupText.SubText findToken(Pattern pattern) { String text = getText(); Matcher m = pattern.matcher(text); - if(m.find()) + if (m.find()) return createSubText(m); return null; @@ -142,17 +143,17 @@ public List findTokens(Pattern pattern) { Matcher m = pattern.matcher(text); List r = new ArrayList<>(); - while(m.find()) { + while (m.find()) { int idx = m.start(); - if(idx>0) { - char ch = text.charAt(idx-1); - if(Character.isLetter(ch) || Character.isDigit(ch)) + if (idx > 0) { + char ch = text.charAt(idx - 1); + if (Character.isLetter(ch) || Character.isDigit(ch)) continue; // not at a word boundary } idx = m.end(); - if(idx optionalDependencies) { String pluginName = atts.getValue("Short-Name"); - + String jenkinsVersion = atts.getValue("Jenkins-Version"); - if (jenkinsVersion==null) + if (jenkinsVersion == null) jenkinsVersion = atts.getValue("Hudson-Version"); for (Dependency d : DetachedPluginsUtil.getImpliedDependencies(pluginName, jenkinsVersion)) { @@ -278,7 +279,7 @@ public static List getImpliedDependencies(String plugi @Deprecated protected ClassLoader createClassLoader(List paths, ClassLoader parent) throws IOException { - return createClassLoader( paths, parent, null ); + return createClassLoader(paths, parent, null); } /** @@ -322,7 +323,7 @@ protected ClassLoader createClassLoader(List paths, ClassLoader parent, At */ private ClassLoader getBaseClassLoader(Attributes atts, ClassLoader base) { String masked = atts.getValue("Mask-Classes"); - if(masked!=null) + if (masked != null) base = new MaskingClassLoader(base, masked.trim().split("[ \t\r\n]+")); return base; } @@ -335,7 +336,7 @@ public void initializeComponents(PluginWrapper plugin) { public List> findComponents(Class type, Hudson hudson) { List finders; - if (type==ExtensionFinder.class) { + if (type == ExtensionFinder.class) { // Avoid infinite recursion of using ExtensionFinders to find ExtensionFinders finders = Collections.singletonList(new ExtensionFinder.Sezpoz()); } else { @@ -346,7 +347,7 @@ public List> findComponents(Class type, Hudson huds * See ExtensionFinder#scout(Class, Hudson) for the dead lock issue and what this does. */ if (LOGGER.isLoggable(Level.FINER)) - LOGGER.log(Level.FINER, "Scout-loading ExtensionList: "+type, new Throwable()); + LOGGER.log(Level.FINER, "Scout-loading ExtensionList: " + type, new Throwable()); for (ExtensionFinder finder : finders) { finder.scout(type, hudson); } @@ -364,7 +365,7 @@ public List> findComponents(Class type, Hudson huds List> filtered = new ArrayList<>(); for (ExtensionComponent e : r) { - if (ExtensionFilter.isAllowed(type,e)) + if (ExtensionFilter.isAllowed(type, e)) filtered.add(e); } @@ -379,21 +380,21 @@ public void load(PluginWrapper wrapper) throws IOException { Thread.currentThread().setContextClassLoader(wrapper.classLoader); try { String className = wrapper.getPluginClass(); - if(className==null) { + if (className == null) { // use the default dummy instance wrapper.setPlugin(new DummyImpl()); } else { try { Class clazz = wrapper.classLoader.loadClass(className); Object o = clazz.getDeclaredConstructor().newInstance(); - if(!(o instanceof Plugin)) { - throw new IOException(className+" doesn't extend from hudson.Plugin"); + if (!(o instanceof Plugin)) { + throw new IOException(className + " doesn't extend from hudson.Plugin"); } wrapper.setPlugin((Plugin) o); } catch (LinkageError | ClassNotFoundException e) { - throw new IOException("Unable to load " + className + " from " + wrapper.getShortName(),e); + throw new IOException("Unable to load " + className + " from " + wrapper.getShortName(), e); } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new IOException("Unable to create instance of " + className + " from " + wrapper.getShortName(),e); + throw new IOException("Unable to create instance of " + className + " from " + wrapper.getShortName(), e); } } @@ -402,9 +403,9 @@ public void load(PluginWrapper wrapper) throws IOException { Plugin plugin = wrapper.getPluginOrFail(); plugin.setServletContext(pluginManager.context); startPlugin(wrapper); - } catch(Throwable t) { + } catch (Throwable t) { // gracefully handle any error in plugin. - throw new IOException("Failed to initialize",t); + throw new IOException("Failed to initialize", t); } } finally { Thread.currentThread().setContextClassLoader(old); @@ -428,14 +429,14 @@ private DependencyClassLoader findAncestorDependencyClassLoader(ClassLoader clas { for (; classLoader != null; classLoader = classLoader.getParent()) { if (classLoader instanceof DependencyClassLoader) { - return (DependencyClassLoader)classLoader; + return (DependencyClassLoader) classLoader; } - + if (classLoader instanceof AntClassLoader) { // AntClassLoaders hold parents not only as AntClassLoader#getParent() // but also as AntClassLoader#getConfiguredParent() DependencyClassLoader ret = findAncestorDependencyClassLoader( - ((AntClassLoader)classLoader).getConfiguredParent() + ((AntClassLoader) classLoader).getConfiguredParent() ); if (ret != null) { return ret; @@ -448,29 +449,29 @@ private DependencyClassLoader findAncestorDependencyClassLoader(ClassLoader clas @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "Administrator action installing a plugin, which could do far worse.") private static File resolve(File base, String relative) { File rel = new File(relative); - if(rel.isAbsolute()) + if (rel.isAbsolute()) return rel; else - return new File(base.getParentFile(),relative); + return new File(base.getParentFile(), relative); } private static void parseClassPath(Manifest manifest, File archive, List paths, String attributeName, String separator) throws IOException { String classPath = manifest.getMainAttributes().getValue(attributeName); - if(classPath==null) return; // attribute not found + if (classPath == null) return; // attribute not found for (String s : classPath.split(separator)) { File file = resolve(archive, s); - if(file.getName().contains("*")) { + if (file.getName().contains("*")) { // handle wildcard FileSet fs = new FileSet(); File dir = file.getParentFile(); fs.setDir(dir); fs.setIncludes(file.getName()); - for( String included : fs.getDirectoryScanner(new Project()).getIncludedFiles() ) { - paths.add(new File(dir,included)); + for (String included : fs.getDirectoryScanner(new Project()).getIncludedFiles()) { + paths.add(new File(dir, included)); } } else { - if(!file.exists()) - throw new IOException("No such file: "+file); + if (!file.exists()) + throw new IOException("No such file: " + file); paths.add(file); } } @@ -480,11 +481,11 @@ private static void parseClassPath(Manifest manifest, File archive, List p * Explodes the plugin into a directory, if necessary. */ private static void explode(File archive, File destDir) throws IOException { - Files.createDirectories(Util.fileToPath(destDir)); + Util.createDirectories(Util.fileToPath(destDir)); // timestamp check - File explodeTime = new File(destDir,".timestamp2"); - if(explodeTime.exists() && explodeTime.lastModified()==archive.lastModified()) + File explodeTime = new File(destDir, ".timestamp2"); + if (explodeTime.exists() && explodeTime.lastModified() == archive.lastModified()) return; // no need to expand // delete the contents so that old files won't interfere with new files @@ -495,7 +496,7 @@ private static void explode(File archive, File destDir) throws IOException { unzipExceptClasses(archive, destDir, prj); createClassJarFromWebInfClasses(archive, destDir, prj); } catch (BuildException x) { - throw new IOException("Failed to expand " + archive,x); + throw new IOException("Failed to expand " + archive, x); } try { @@ -530,7 +531,7 @@ private static void createClassJarFromWebInfClasses(File archive, File destDir, try (ZipOutputStream wrappedZOut = new ZipOutputStream(NullOutputStream.NULL_OUTPUT_STREAM) { @Override public void putNextEntry(ZipEntry ze) throws IOException { - ze.setTime(dirTime+1999); // roundup + ze.setTime(dirTime + 1999); // roundup super.putNextEntry(ze); } }) { @@ -544,12 +545,12 @@ protected void zipDir(Resource dir, ZipOutputStream zOut, String vPath, int mode, ZipExtraField[] extra) throws IOException { // use wrappedZOut instead of zOut - super.zipDir(dir,wrappedZOut,vPath,mode,extra); + super.zipDir(dir, wrappedZOut, vPath, mode, extra); } }; z.setProject(prj); z.setTaskType("zip"); - Files.createDirectories(Util.fileToPath(classesJar.getParentFile())); + Util.createDirectories(Util.fileToPath(classesJar.getParentFile())); z.setDestFile(classesJar); z.add(mapper); z.execute(); @@ -617,7 +618,7 @@ protected List getEdges(PluginWrapper pw) { List dep = new ArrayList<>(); for (Dependency d : pw.getDependencies()) { PluginWrapper p = pluginManager.getPlugin(d.shortName); - if (p!=null && p.isActive()) + if (p != null && p.isActive()) dep.add(p); } return dep; @@ -627,7 +628,7 @@ protected List getEdges(PluginWrapper pw) { try { for (Dependency d : dependencies) { PluginWrapper p = pluginManager.getPlugin(d.shortName); - if (p!=null && p.isActive()) + if (p != null && p.isActive()) cgd.run(Collections.singleton(p)); } } catch (CycleDetectedException e) { @@ -654,7 +655,7 @@ protected Class findClass(String name) throws ClassNotFoundException { } else { for (Dependency dep : dependencies) { PluginWrapper p = pluginManager.getPlugin(dep.shortName); - if(p!=null) { + if (p != null) { try { return p.classLoader.loadClass(name); } catch (ClassNotFoundException ignored) { @@ -682,7 +683,7 @@ protected Enumeration findResources(String name) throws IOException { } else { for (Dependency dep : dependencies) { PluginWrapper p = pluginManager.getPlugin(dep.shortName); - if (p!=null) { + if (p != null) { Enumeration urls = p.classLoader.getResources(name); while (urls != null && urls.hasMoreElements()) result.add(urls.nextElement()); @@ -698,14 +699,14 @@ protected URL findResource(String name) { if (PluginManager.FAST_LOOKUP) { for (PluginWrapper pw : getTransitiveDependencies()) { URL url = ClassLoaderReflectionToolkit._findResource(pw.classLoader, name); - if (url!=null) return url; + if (url != null) return url; } } else { for (Dependency dep : dependencies) { PluginWrapper p = pluginManager.getPlugin(dep.shortName); - if(p!=null) { + if (p != null) { URL url = p.classLoader.getResource(name); - if (url!=null) + if (url != null) return url; } } diff --git a/core/src/main/java/hudson/CloseProofOutputStream.java b/core/src/main/java/hudson/CloseProofOutputStream.java index 5a9090e79cc40..0fc4aee48a5ce 100644 --- a/core/src/main/java/hudson/CloseProofOutputStream.java +++ b/core/src/main/java/hudson/CloseProofOutputStream.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import hudson.util.DelegatingOutputStream; diff --git a/core/src/main/java/hudson/CopyOnWrite.java b/core/src/main/java/hudson/CopyOnWrite.java index ff6bc92d57565..04e737964a801 100644 --- a/core/src/main/java/hudson/CopyOnWrite.java +++ b/core/src/main/java/hudson/CopyOnWrite.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import static java.lang.annotation.ElementType.FIELD; diff --git a/core/src/main/java/hudson/DependencyRunner.java b/core/src/main/java/hudson/DependencyRunner.java index 914be79ffa6f7..b7db91fb94164 100644 --- a/core/src/main/java/hudson/DependencyRunner.java +++ b/core/src/main/java/hudson/DependencyRunner.java @@ -1,19 +1,19 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, * Brian Westrich, Jean-Baptiste Quenot - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import hudson.model.AbstractProject; @@ -41,7 +42,7 @@ public class DependencyRunner implements Runnable { private static final Logger LOGGER = Logger.getLogger(DependencyRunner.class.getName()); - + ProjectRunnable runnable; List polledProjects = new ArrayList<>(); @@ -72,11 +73,11 @@ public void run() { } private void populate(Collection projectList) { - for (AbstractProject p : projectList) { + for (AbstractProject p : projectList) { if (polledProjects.contains(p)) { // Project will be readded at the queue, so that we always use // the longest path - LOGGER.fine("removing project " + p.getName() + " for re-add"); + LOGGER.fine("removing project " + p.getName() + " for re-add"); polledProjects.remove(p); } diff --git a/core/src/main/java/hudson/DescriptorExtensionList.java b/core/src/main/java/hudson/DescriptorExtensionList.java index 25f1191706509..7c9fbbddccacc 100644 --- a/core/src/main/java/hudson/DescriptorExtensionList.java +++ b/core/src/main/java/hudson/DescriptorExtensionList.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -71,8 +72,8 @@ public class DescriptorExtensionList, D extends Descrip * Creates a new instance. */ @SuppressWarnings({"unchecked", "rawtypes"}) - public static ,D extends Descriptor> - DescriptorExtensionList createDescriptorList(Jenkins jenkins, Class describableType) { + public static , D extends Descriptor> + DescriptorExtensionList createDescriptorList(Jenkins jenkins, Class describableType) { if (describableType == Publisher.class) { return (DescriptorExtensionList) new Publisher.DescriptorExtensionListImpl(jenkins); } @@ -84,9 +85,9 @@ DescriptorExtensionList createDescriptorList(Jenkins jenkins, Class desc * Use {@link #create(Jenkins, Class)} */ @Deprecated - public static ,D extends Descriptor> - DescriptorExtensionList createDescriptorList(Hudson hudson, Class describableType) { - return (DescriptorExtensionList)createDescriptorList((Jenkins)hudson,describableType); + public static , D extends Descriptor> + DescriptorExtensionList createDescriptorList(Hudson hudson, Class describableType) { + return (DescriptorExtensionList) createDescriptorList((Jenkins) hudson, describableType); } /** @@ -100,11 +101,11 @@ DescriptorExtensionList createDescriptorList(Hudson hudson, Class descri */ @Deprecated protected DescriptorExtensionList(Hudson hudson, Class describableType) { - this((Jenkins)hudson,describableType); + this((Jenkins) hudson, describableType); } protected DescriptorExtensionList(Jenkins jenkins, Class describableType) { - super(jenkins, (Class)Descriptor.class, (CopyOnWriteArrayList)getLegacyDescriptors(describableType)); + super(jenkins, (Class) Descriptor.class, (CopyOnWriteArrayList) getLegacyDescriptors(describableType)); this.describableType = describableType; } @@ -117,7 +118,7 @@ protected DescriptorExtensionList(Jenkins jenkins, Class describableType) { */ @Deprecated public D find(String fqcn) { - return Descriptor.find(this,fqcn); + return Descriptor.find(this, fqcn); } /** @@ -126,7 +127,7 @@ public D find(String fqcn) { */ public D find(Class type) { for (D d : this) - if (d.clazz==type) + if (d.clazz == type) return d; return null; } @@ -141,10 +142,10 @@ public D find(Class type) { */ @CheckForNull public T newInstanceFromRadioList(JSONObject config) throws FormException { - if(config.isNullObject()) + if (config.isNullObject()) return null; // none was selected int idx = config.getInt("value"); - return get(idx).newInstance(Stapler.getCurrentRequest(),config); + return get(idx).newInstance(Stapler.getCurrentRequest(), config); } /** @@ -171,7 +172,7 @@ public T newInstanceFromRadioList(@NonNull JSONObject parent, @NonNull String na */ public @CheckForNull D findByName(String id) { for (D d : this) - if(d.getId().equals(id)) + if (d.getId().equals(id)) return d; return null; } @@ -219,11 +220,11 @@ protected Collection> load(ExtensionComponentSet delta) { private List> _load(Iterable> set) { List> r = new ArrayList<>(); - for( ExtensionComponent c : set ) { + for (ExtensionComponent c : set) { Descriptor d = c.getInstance(); try { - if(d.getT()==describableType) - r.add((ExtensionComponent)c); + if (d.getT() == describableType) + r.add((ExtensionComponent) c); } catch (IllegalStateException e) { LOGGER.log(Level.SEVERE, d.getClass() + " doesn't extend Descriptor with a type parameter", e); // skip this one } @@ -253,8 +254,8 @@ public static Iterable listLegacyInstances() { return new Iterable() { @Override public Iterator iterator() { - return new AdaptedIterator,Descriptor>( - new FlattenIterator,CopyOnWriteArrayList>>(legacyDescriptors.values()) { + return new AdaptedIterator, Descriptor>( + new FlattenIterator, CopyOnWriteArrayList>>(legacyDescriptors.values()) { @Override protected Iterator> expand(CopyOnWriteArrayList> v) { return v.iterator(); diff --git a/core/src/main/java/hudson/EnvVars.java b/core/src/main/java/hudson/EnvVars.java index 673396061a6c3..cce69ede9ee84 100644 --- a/core/src/main/java/hudson/EnvVars.java +++ b/core/src/main/java/hudson/EnvVars.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Red Hat, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -71,7 +72,7 @@ * * @author Kohsuke Kawaguchi */ -public class EnvVars extends TreeMap { +public class EnvVars extends TreeMap { private static final long serialVersionUID = 4320331661987259022L; private static Logger LOGGER = Logger.getLogger(EnvVars.class.getName()); /** @@ -84,7 +85,7 @@ public class EnvVars extends TreeMap { * So this property remembers that information. */ private Platform platform; - + /** * Gets the platform for which these env vars targeted. * @since 2.144 @@ -102,11 +103,12 @@ public class EnvVars extends TreeMap { public void setPlatform(@NonNull Platform platform) { this.platform = platform; } + public EnvVars() { super(String.CASE_INSENSITIVE_ORDER); } - public EnvVars(@NonNull Map m) { + public EnvVars(@NonNull Map m) { this(); putAll(m); @@ -121,7 +123,7 @@ public EnvVars(@NonNull Map m) { @SuppressWarnings("CopyConstructorMissesField") // does not set #platform, see its Javadoc public EnvVars(@NonNull EnvVars m) { // this constructor is so that in future we can get rid of the downcasting. - this((Map)m); + this((Map) m); } /** @@ -129,10 +131,10 @@ public EnvVars(@NonNull EnvVars m) { */ public EnvVars(String... keyValuePairs) { this(); - if(keyValuePairs.length%2!=0) + if (keyValuePairs.length % 2 != 0) throw new IllegalArgumentException(Arrays.asList(keyValuePairs).toString()); - for( int i=0; i0) { - String realKey = key.substring(0,idx); + if (idx > 0) { + String realKey = key.substring(0, idx); String v = get(realKey); - if(v==null) v=value; + if (v == null) v = value; else { // we might be handling environment variables for a agent that can have different path separator // than the controller, so the following is an attempt to get it right. // it's still more error prone that I'd like. - char ch = platform==null ? File.pathSeparatorChar : platform.pathSeparator; - v=value+ch+v; + char ch = platform == null ? File.pathSeparatorChar : platform.pathSeparator; + v = value + ch + v; } - put(realKey,v); + put(realKey, v); return; } - put(key,value); + put(key, value); } /** @@ -171,18 +173,18 @@ public void override(String key, String value) { * See {@link #override(String, String)}. * @return this */ - public EnvVars overrideAll(Map all) { + public EnvVars overrideAll(Map all) { for (Map.Entry e : all.entrySet()) { - override(e.getKey(),e.getValue()); + override(e.getKey(), e.getValue()); } return this; } /** * Calculates the order to override variables. - * + * * Sort variables with topological sort with their reference graph. - * + * * This is package accessible for testing purpose. */ static class OverrideOrderCalculator { @@ -192,31 +194,31 @@ static class OverrideOrderCalculator { private static class TraceResolver implements VariableResolver { private final Comparator comparator; public Set referredVariables; - + TraceResolver(Comparator comparator) { this.comparator = comparator; clear(); } - + public void clear() { referredVariables = new TreeSet<>(comparator); } - + @Override public String resolve(String name) { referredVariables.add(name); return ""; } } - + private static class VariableReferenceSorter extends CyclicGraphDetector { // map from a variable to a set of variables that variable refers. private final Map> refereeSetMap; - + VariableReferenceSorter(Map> refereeSetMap) { this.refereeSetMap = refereeSetMap; } - + @Override protected Iterable getEdges(String n) { // return variables referred from the variable. @@ -229,32 +231,32 @@ protected Iterable getEdges(String n) { } private final Comparator comparator; - + @NonNull private final EnvVars target; @NonNull - private final Map overrides; - + private final Map overrides; + private Map> refereeSetMap; private List orderedVariableNames; - - OverrideOrderCalculator(@NonNull EnvVars target, @NonNull Map overrides) { + + OverrideOrderCalculator(@NonNull EnvVars target, @NonNull Map overrides) { comparator = target.comparator(); this.target = target; this.overrides = overrides; scan(); } - + public List getOrderedVariableNames() { return orderedVariableNames; } - + // Cut the reference to the variable in a cycle. private void cutCycleAt(String referee, List cycle) { // cycle contains variables in referrer-to-referee order. // This should not be negative, for the first and last one is same. int refererIndex = cycle.lastIndexOf(referee) - 1; - + assert refererIndex >= 0; String referrer = cycle.get(refererIndex); boolean removed = refereeSetMap.get(referrer).remove(referee); @@ -262,7 +264,7 @@ private void cutCycleAt(String referee, List cycle) { LOGGER.warning(String.format("Cyclic reference detected: %s", String.join(" -> ", cycle))); LOGGER.warning(String.format("Cut the reference %s -> %s", referrer, referee)); } - + // Cut the variable reference in a cycle. private void cutCycle(List cycle) { // if an existing variable is contained in that cycle, @@ -273,27 +275,27 @@ private void cutCycle(List cycle) { // PATH1=/usr/local/bin:${PATH} // PATH=/opt/something/bin:${PATH1} // then consider reference PATH1 -> PATH can be ignored. - for (String referee: cycle) { + for (String referee : cycle) { if (target.containsKey(referee)) { cutCycleAt(referee, cycle); return; } } - + // if not, cut the reference to the first one. cutCycleAt(cycle.get(0), cycle); } - + /** * Scan all variables and list all referring variables. */ public void scan() { refereeSetMap = new TreeMap<>(comparator); List extendingVariableNames = new ArrayList<>(); - + TraceResolver resolver = new TraceResolver(comparator); - - for (Map.Entry entry: overrides.entrySet()) { + + for (Map.Entry entry : overrides.entrySet()) { if (entry.getKey().indexOf('+') > 0) { // XYZ+AAA variables should be always processed in last. extendingVariableNames.add(entry.getKey()); @@ -301,20 +303,20 @@ public void scan() { } resolver.clear(); Util.replaceMacro(entry.getValue(), resolver); - + // Variables directly referred from the current scanning variable. Set refereeSet = resolver.referredVariables; // Ignore self reference. refereeSet.remove(entry.getKey()); refereeSetMap.put(entry.getKey(), refereeSet); } - + VariableReferenceSorter sorter; - while(true) { + while (true) { sorter = new VariableReferenceSorter(refereeSetMap); try { sorter.run(refereeSetMap.keySet()); - } catch(CycleDetectedException e) { + } catch (CycleDetectedException e) { // cyclic reference found. // cut the cycle and retry. @SuppressWarnings("unchecked") @@ -324,15 +326,15 @@ public void scan() { } break; } - + // When A refers B, the last appearance of B always comes after // the last appearance of A. List reversedDuplicatedOrder = new ArrayList<>(sorter.getSorted()); Collections.reverse(reversedDuplicatedOrder); - + orderedVariableNames = new ArrayList<>(overrides.size()); - for(String key: reversedDuplicatedOrder) { - if(overrides.containsKey(key) && !orderedVariableNames.contains(key)) { + for (String key : reversedDuplicatedOrder) { + if (overrides.containsKey(key) && !orderedVariableNames.contains(key)) { orderedVariableNames.add(key); } } @@ -340,14 +342,14 @@ public void scan() { orderedVariableNames.addAll(extendingVariableNames); } } - + /** * Overrides all values in the map by the given map. Expressions in values will be expanded. * See {@link #override(String, String)}. * @return {@code this} */ - public EnvVars overrideExpandingAll(@NonNull Map all) { + public EnvVars overrideExpandingAll(@NonNull Map all) { for (String key : new OverrideOrderCalculator(this, all).getOrderedVariableNames()) { override(key, expand(all.get(key))); } @@ -357,11 +359,11 @@ public EnvVars overrideExpandingAll(@NonNull Map all) { /** * Resolves environment variables against each other. */ - public static void resolve(Map env) { - for (Map.Entry entry: env.entrySet()) { - entry.setValue(Util.replaceMacro(entry.getValue(), env)); - } - } + public static void resolve(Map env) { + for (Map.Entry entry : env.entrySet()) { + entry.setValue(Util.replaceMacro(entry.getValue(), env)); + } + } /** * Convenience message @@ -369,14 +371,14 @@ public static void resolve(Map env) { **/ public String get(String key, String defaultValue) { String v = get(key); - if (v==null) v=defaultValue; + if (v == null) v = defaultValue; return v; } @Override public String put(String key, String value) { - if (value==null) throw new IllegalArgumentException("Null value not allowed as an environment variable: "+key); - return super.put(key,value); + if (value == null) throw new IllegalArgumentException("Null value not allowed as an environment variable: " + key); + return super.put(key, value); } /** @@ -384,8 +386,8 @@ public String put(String key, String value) { * @since 1.556 */ public void putIfNotNull(String key, String value) { - if (value!=null) - put(key,value); + if (value != null) + put(key, value); } /** @@ -396,14 +398,14 @@ public void putAllNonNull(Map map) { map.forEach(this::putIfNotNull); } - + /** * Takes a string that looks like "a=b" and adds that to this map. */ public void addLine(String line) { int sep = line.indexOf('='); - if(sep > 0) { - put(line.substring(0,sep),line.substring(sep+1)); + if (sep > 0) { + put(line.substring(0, sep), line.substring(sep + 1)); } } @@ -431,16 +433,17 @@ public static EnvVars createCookie() { * A fresh copy that can be owned and modified by the caller. */ public static EnvVars getRemote(VirtualChannel channel) throws IOException, InterruptedException { - if(channel==null) - return new EnvVars("N/A","N/A"); + if (channel == null) + return new EnvVars("N/A", "N/A"); return channel.call(new GetEnvVars()); } - private static final class GetEnvVars extends MasterToSlaveCallable { + private static final class GetEnvVars extends MasterToSlaveCallable { @Override public EnvVars call() { return new EnvVars(EnvVars.masterEnvVars); } + private static final long serialVersionUID = 1L; } @@ -456,12 +459,12 @@ public EnvVars call() { * If you access this field from agents, then this is the environment * variable of the agent. */ - public static final Map masterEnvVars = initMaster(); + public static final Map masterEnvVars = initMaster(); private static EnvVars initMaster() { EnvVars vars = new EnvVars(System.getenv()); vars.platform = Platform.current(); - if(Main.isUnitTest || Main.isDevelopmentMode) + if (Main.isUnitTest || Main.isDevelopmentMode) // if unit test is launched with maven debug switch, // we need to prevent forked Maven processes from seeing it, or else // they'll hang diff --git a/core/src/main/java/hudson/ExpressionFactory2.java b/core/src/main/java/hudson/ExpressionFactory2.java index e71202f4552b1..7fcec22e76047 100644 --- a/core/src/main/java/hudson/ExpressionFactory2.java +++ b/core/src/main/java/hudson/ExpressionFactory2.java @@ -72,14 +72,14 @@ public String getExpressionText() { public Object evaluate(JellyContext context) { try { CURRENT_CONTEXT.set(context); - JexlContext jexlContext = new JellyJexlContext( context ); + JexlContext jexlContext = new JellyJexlContext(context); return expression.evaluate(jexlContext); } catch (AccessDeniedException e) { // let the security exception pass through throw e; } catch (Exception e) { StaplerRequest currentRequest = Stapler.getCurrentRequest(); - LOGGER.log(Level.WARNING,"Caught exception evaluating: " + expression + " in " + (currentRequest != null ? currentRequest.getOriginalRequestURI() : "?") + ". Reason: " + e, e); + LOGGER.log(Level.WARNING, "Caught exception evaluating: " + expression + " in " + (currentRequest != null ? currentRequest.getOriginalRequestURI() : "?") + ". Reason: " + e, e); return null; } finally { CURRENT_CONTEXT.set(null); @@ -93,13 +93,13 @@ static final class JellyJexlContext implements JexlContext { private Map vars; JellyJexlContext(JellyContext context) { - this.vars = new JellyMap( context ); + this.vars = new JellyMap(context); } @Override public void setVars(Map vars) { this.vars.clear(); - this.vars.putAll( vars ); + this.vars.putAll(vars); } @Override @@ -119,7 +119,7 @@ static final class JellyMap implements Map { @Override public Object get(Object key) { - return context.getVariable( (String) key ); + return context.getVariable((String) key); } @Override diff --git a/core/src/main/java/hudson/Extension.java b/core/src/main/java/hudson/Extension.java index 0bcffcefbe294..b240e37f87db1 100644 --- a/core/src/main/java/hudson/Extension.java +++ b/core/src/main/java/hudson/Extension.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import static java.lang.annotation.ElementType.FIELD; diff --git a/core/src/main/java/hudson/ExtensionComponent.java b/core/src/main/java/hudson/ExtensionComponent.java index e80eb8edc1d63..4ef48d08008d0 100644 --- a/core/src/main/java/hudson/ExtensionComponent.java +++ b/core/src/main/java/hudson/ExtensionComponent.java @@ -50,11 +50,11 @@ public ExtensionComponent(T instance, double ordinal) { } public ExtensionComponent(T instance, Extension annotation) { - this(instance,annotation.ordinal()); + this(instance, annotation.ordinal()); } public ExtensionComponent(T instance) { - this(instance,0); + this(instance, 0); } /** @@ -79,7 +79,7 @@ public T getInstance() { * For example, {@code component.isDescriptorOf(Builder.class)} */ public boolean isDescriptorOf(Class c) { - return instance instanceof Descriptor && ((Descriptor)instance).isSubTypeOf(c); + return instance instanceof Descriptor && ((Descriptor) instance).isSubTypeOf(c); } /** diff --git a/core/src/main/java/hudson/ExtensionFinder.java b/core/src/main/java/hudson/ExtensionFinder.java index 10ca19bef5016..5bddd008f5f08 100644 --- a/core/src/main/java/hudson/ExtensionFinder.java +++ b/core/src/main/java/hudson/ExtensionFinder.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import com.google.inject.AbstractModule; @@ -38,6 +39,7 @@ import hudson.init.InitMilestone; import hudson.model.Descriptor; import hudson.model.Hudson; +import jakarta.annotation.PostConstruct; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; @@ -55,7 +57,6 @@ import java.util.logging.Logger; import java.util.stream.Collectors; import java.util.stream.StreamSupport; -import javax.annotation.PostConstruct; import jenkins.ExtensionComponentSet; import jenkins.ExtensionFilter; import jenkins.ExtensionRefreshException; @@ -98,7 +99,7 @@ public Collection findExtensions(Class type, Hudson hudson) { */ public boolean isRefreshable() { try { - return getClass().getMethod("refresh").getDeclaringClass()!=ExtensionFinder.class; + return getClass().getMethod("refresh").getDeclaringClass() != ExtensionFinder.class; } catch (NoSuchMethodException e) { return false; } @@ -153,7 +154,7 @@ public Collection> _find(Class type, Hudson hudson) } /** - * Performs class initializations without creating instances. + * Performs class initializations without creating instances. * * If two threads try to initialize classes in the opposite order, a dead lock will ensue, * and we can get into a similar situation with {@link ExtensionFinder}s. @@ -227,7 +228,7 @@ protected GuiceExtensionAnnotation(Class annotationType) { protected abstract boolean isOptional(T annotation); } - + /** * Discovers components via sezpoz but instantiates them by using Guice. */ @@ -246,15 +247,15 @@ public static class GuiceFinder extends ExtensionFinder { * Sezpoz index we are currently using in {@link #container} (and its ancestors.) * Needed to compute delta. */ - private List> sezpozIndex; + private List> sezpozIndex; - private final Map annotations = new HashMap<>(); + private final Map annotations = new HashMap<>(); private final Sezpoz moduleFinder = new Sezpoz(); /** * Map from {@link GuiceExtensionAnnotation#annotationType} to {@link GuiceExtensionAnnotation} */ - private Map,GuiceExtensionAnnotation> extensionAnnotations = new HashMap<>(); + private Map, GuiceExtensionAnnotation> extensionAnnotations = new HashMap<>(); public GuiceFinder() { refreshExtensionAnnotations(); @@ -280,14 +281,14 @@ protected void configure() { container = Guice.createInjector(modules); sezpozIndex = extensions.getLoadedIndex(); } catch (Throwable e) { - LOGGER.log(Level.SEVERE, "Failed to create Guice container from all the plugins",e); + LOGGER.log(Level.SEVERE, "Failed to create Guice container from all the plugins", e); // failing to load all bindings are disastrous, so recover by creating minimum that works // by just including the core container = Guice.createInjector(new SezpozModule(loadSezpozIndices(Jenkins.class.getClassLoader()))); } // expose Injector via lookup mechanism for interop with non-Guice clients - Jenkins.get().lookup.set(Injector.class,new ProxyInjector() { + Jenkins.get().lookup.set(Injector.class, new ProxyInjector() { @Override protected Injector resolve() { return getContainer(); @@ -298,12 +299,12 @@ protected Injector resolve() { private void refreshExtensionAnnotations() { for (ExtensionComponent ec : moduleFinder.find(GuiceExtensionAnnotation.class, Hudson.getInstance())) { GuiceExtensionAnnotation gea = ec.getInstance(); - extensionAnnotations.put(gea.annotationType,gea); + extensionAnnotations.put(gea.annotationType, gea); } } private List> loadSezpozIndices(ClassLoader classLoader) { - List> indices = new ArrayList<>(); + List> indices = new ArrayList<>(); for (GuiceExtensionAnnotation gea : extensionAnnotations.values()) { for (IndexItem indexItem : Index.load(gea.annotationType, Object.class, classLoader)) { indices.add(indexItem); @@ -330,7 +331,7 @@ public synchronized ExtensionComponentSet refresh() throws ExtensionRefreshExcep // figure out newly discovered sezpoz components List> delta = new ArrayList<>(); for (Class annotationType : extensionAnnotations.keySet()) { - delta.addAll(Sezpoz.listDelta(annotationType,sezpozIndex)); + delta.addAll(Sezpoz.listDelta(annotationType, sezpozIndex)); } SezpozModule deltaExtensions = new SezpozModule(delta); @@ -357,19 +358,19 @@ public Collection> find(Class type) { } }; } catch (Throwable e) { - LOGGER.log(Level.SEVERE, "Failed to create Guice container from newly added plugins",e); + LOGGER.log(Level.SEVERE, "Failed to create Guice container from newly added plugins", e); throw new ExtensionRefreshException(e); } } - private Object instantiate(IndexItem item) { + private Object instantiate(IndexItem item) { try { return item.instance(); } catch (LinkageError | Exception e) { // sometimes the instantiation fails in an indirect classloading failure, // which results in a LinkageError LOGGER.log(isOptional(item.annotation()) ? Level.FINE : Level.WARNING, - "Failed to load "+item.className(), e); + "Failed to load " + item.className(), e); } return null; } @@ -388,7 +389,7 @@ private boolean isActive(Annotation annotation, AnnotatedElement e) { public Collection> find(Class type, Hudson jenkins) { // the find method contract requires us to traverse all known components List> result = new ArrayList<>(); - for (Injector i=container; i!=null; i=i.getParent()) { + for (Injector i = container; i != null; i = i.getParent()) { _find(type, result, i); } return result; @@ -399,8 +400,8 @@ private void _find(Class type, List> result, Inject if (type.isAssignableFrom(e.getKey().getTypeLiteral().getRawType())) { Annotation a = annotations.get(e.getKey()); Object o = e.getValue().getProvider().get(); - if (o!=null) { - GuiceExtensionAnnotation gea = a!=null ? extensionAnnotations.get(a.annotationType()) : null; + if (o != null) { + GuiceExtensionAnnotation gea = a != null ? extensionAnnotations.get(a.annotationType()) : null; result.add(new ExtensionComponent<>(type.cast(o), gea != null ? gea.getOrdinal(a) : 0)); } } @@ -425,15 +426,17 @@ public void scout(Class extensionType, Hudson hudson) { */ public static final Scope FAULT_TOLERANT_SCOPE = new FaultTolerantScope(true); private static final Scope QUIET_FAULT_TOLERANT_SCOPE = new FaultTolerantScope(false); - + private static final class FaultTolerantScope implements Scope { private final boolean verbose; + FaultTolerantScope(boolean verbose) { this.verbose = verbose; } + @Override public Provider scope(final Key key, final Provider unscoped) { - final Provider base = Scopes.SINGLETON.scope(key,unscoped); + final Provider base = Scopes.SINGLETON.scope(key, unscoped); return new Provider() { @Override public T get() { @@ -444,6 +447,7 @@ public T get() { return null; } } + void error(Key key, Throwable x) { LOGGER.log(verbose ? Level.WARNING : Level.FINE, "Failed to instantiate " + key + "; skipping this component", x); } @@ -459,10 +463,10 @@ void error(Key key, Throwable x) { * so that we can take advantage of dependency injection. */ private class SezpozModule extends AbstractModule implements ProvisionListener { - private final List> index; - private final List> loadedIndex; + private final List> index; + private final List> loadedIndex; - SezpozModule(List> index) { + SezpozModule(List> index) { this.index = index; this.loadedIndex = new ArrayList<>(); } @@ -482,6 +486,7 @@ private class SezpozModule extends AbstractModule implements ProvisionListener { private void resolve(Class c) { resolve(c, new HashSet<>()); } + private void resolve(Class c, Set> encountered) { if (!encountered.add(c)) { return; @@ -503,7 +508,7 @@ private void resolve(Class c, Set> encountered) { } LOGGER.log(Level.FINER, "{0} looks OK", c); } catch (RuntimeException x) { - throw new LinkageError("Failed to resolve "+c, x); + throw new LinkageError("Failed to resolve " + c, x); } } @@ -513,26 +518,26 @@ protected void configure() { bindListener(Matchers.any(), this); - for (final IndexItem item : index) { + for (final IndexItem item : index) { boolean optional = isOptional(item.annotation()); try { AnnotatedElement e = item.element(); Annotation a = item.annotation(); - if (!isActive(a,e)) continue; + if (!isActive(a, e)) continue; Scope scope = optional ? QUIET_FAULT_TOLERANT_SCOPE : FAULT_TOLERANT_SCOPE; if (e instanceof Class) { - Key key = Key.get((Class)e); - resolve((Class)e); - annotations.put(key,a); + Key key = Key.get((Class) e); + resolve((Class) e); + annotations.put(key, a); bind(key).in(scope); } else { Class extType; if (e instanceof Field) { - extType = ((Field)e).getType(); + extType = ((Field) e).getType(); } else if (e instanceof Method) { - extType = ((Method)e).getReturnType(); + extType = ((Method) e).getReturnType(); } else { throw new AssertionError(); } @@ -541,15 +546,15 @@ protected void configure() { // make unique key, because Guice wants that. Key key = Key.get(extType, Names.named(item.className() + "." + item.memberName())); - annotations.put(key,a); + annotations.put(key, a); bind(key).toProvider(() -> instantiate(item)).in(scope); } loadedIndex.add(item); - } catch (Exception|LinkageError e) { + } catch (Exception | LinkageError e) { // sometimes the instantiation fails in an indirect classloading failure, // which results in a LinkageError LOGGER.log(optional ? Level.FINE : Level.WARNING, - "Failed to load "+item.className(), e); + "Failed to load " + item.className(), e); } } } @@ -575,7 +580,7 @@ public void onProvision(ProvisionInvocation provision) { Arrays.stream(c.getDeclaredMethods()) .map(m -> getMethodAndInterfaceDeclarations(m, interfaces)) .flatMap(Collection::stream) - .filter(m -> m.getAnnotation(PostConstruct.class) != null) + .filter(m -> m.getAnnotation(PostConstruct.class) != null || m.getAnnotation(javax.annotation.PostConstruct.class) != null) .findFirst() .ifPresent(method -> methods.add(0, method)); c = c.getSuperclass(); @@ -623,7 +628,7 @@ Collection getMethodAndInterfaceDeclarations(Method method, Collection> indices; + private volatile List> indices; /** * Loads indices (ideally once but as few times as possible), then reuse them later. @@ -631,14 +636,14 @@ public static final class Sezpoz extends ExtensionFinder { * {@link InitMilestone#PLUGINS_PREPARED} is attained, so this method is guaranteed to * see all the classes and indices. */ - private List> getIndices() { + private List> getIndices() { // this method cannot be synchronized because of a dead lock possibility in the following order of events: // 1. thread X can start listing indices, locking this object 'SZ' // 2. thread Y starts loading a class, locking a classloader 'CL' // 3. thread X needs to load a class, now blocked on CL // 4. thread Y decides to load extensions, now blocked on SZ. // 5. dead lock - if (indices==null) { + if (indices == null) { ClassLoader cl = Jenkins.get().getPluginManager().uberClassLoader; indices = Collections.unmodifiableList(StreamSupport.stream(Index.load(Extension.class, Object.class, cl).spliterator(), false).collect(Collectors.toList())); } @@ -653,28 +658,28 @@ private List> getIndices() { */ @Override public synchronized ExtensionComponentSet refresh() { - final List> old = indices; - if (old==null) return ExtensionComponentSet.EMPTY; // we haven't loaded anything + final List> old = indices; + if (old == null) return ExtensionComponentSet.EMPTY; // we haven't loaded anything - final List> delta = listDelta(Extension.class,old); + final List> delta = listDelta(Extension.class, old); - List> r = new ArrayList<>(old); + List> r = new ArrayList<>(old); r.addAll(delta); indices = Collections.unmodifiableList(r); return new ExtensionComponentSet() { @Override public Collection> find(Class type) { - return _find(type,delta); + return _find(type, delta); } }; } - static List> listDelta(Class annotationType, List> old) { + static List> listDelta(Class annotationType, List> old) { // list up newly discovered components - final List> delta = new ArrayList<>(); + final List> delta = new ArrayList<>(); ClassLoader cl = Jenkins.get().getPluginManager().uberClassLoader; - for (IndexItem ii : Index.load(annotationType, Object.class, cl)) { + for (IndexItem ii : Index.load(annotationType, Object.class, cl)) { if (!old.contains(ii)) { delta.add(ii); } @@ -684,28 +689,28 @@ static List> listDelta(Class annot @Override public Collection> find(Class type, Hudson jenkins) { - return _find(type,getIndices()); + return _find(type, getIndices()); } /** * Finds all the matching {@link IndexItem}s that match the given type and instantiate them. */ - private Collection> _find(Class type, List> indices) { + private Collection> _find(Class type, List> indices) { List> result = new ArrayList<>(); - for (IndexItem item : indices) { + for (IndexItem item : indices) { try { Class extType = getClassFromIndex(item); - if(type.isAssignableFrom(extType)) { + if (type.isAssignableFrom(extType)) { Object instance = item.instance(); - if(instance!=null) - result.add(new ExtensionComponent<>(type.cast(instance),item.annotation())); + if (instance != null) + result.add(new ExtensionComponent<>(type.cast(instance), item.annotation())); } - } catch (LinkageError|Exception e) { + } catch (LinkageError | Exception e) { // sometimes the instantiation fails in an indirect classloading failure, // which results in a LinkageError - LOGGER.log(logLevel(item), "Failed to load "+item.className(), e); + LOGGER.log(logLevel(item), "Failed to load " + item.className(), e); } } @@ -714,7 +719,7 @@ private Collection> _find(Class type, List item : getIndices()) { + for (IndexItem item : getIndices()) { try { // we might end up having multiple threads concurrently calling into element(), // but we can't synchronize this --- if we do, the one thread that's supposed to load a class @@ -722,9 +727,9 @@ public void scout(Class extensionType, Hudson hudson) { // looking at the sezpoz code, it should be safe to do so Class extType = getClassFromIndex(item); // according to JDK-4993813 this is the only way to force class initialization - Class.forName(extType.getName(),true,extType.getClassLoader()); + Class.forName(extType.getName(), true, extType.getClassLoader()); } catch (Exception | LinkageError e) { - LOGGER.log(logLevel(item), "Failed to scout "+item.className(), e); + LOGGER.log(logLevel(item), "Failed to scout " + item.className(), e); } } } diff --git a/core/src/main/java/hudson/ExtensionList.java b/core/src/main/java/hudson/ExtensionList.java index c453a46b3d302..7bae8ff5d83b1 100644 --- a/core/src/main/java/hudson/ExtensionList.java +++ b/core/src/main/java/hudson/ExtensionList.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -38,6 +39,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; @@ -61,7 +63,7 @@ * and {@link jenkins.model.Jenkins#getDescriptorList(Class)} to obtain the instances. * * @param - * Type of the extension point. This class holds instances of the subtypes of 'T'. + * Type of the extension point. This class holds instances of the subtypes of 'T'. * * @author Kohsuke Kawaguchi * @since 1.286 @@ -98,11 +100,11 @@ public class ExtensionList extends AbstractList implements OnMaster { */ @Deprecated protected ExtensionList(Hudson hudson, Class extensionType) { - this((Jenkins)hudson,extensionType); + this((Jenkins) hudson, extensionType); } protected ExtensionList(Jenkins jenkins, Class extensionType) { - this(jenkins,extensionType, new CopyOnWriteArrayList<>()); + this(jenkins, extensionType, new CopyOnWriteArrayList<>()); } /** @@ -111,7 +113,7 @@ protected ExtensionList(Jenkins jenkins, Class extensionType) { */ @Deprecated protected ExtensionList(Hudson hudson, Class extensionType, CopyOnWriteArrayList> legacyStore) { - this((Jenkins)hudson,extensionType,legacyStore); + this((Jenkins) hudson, extensionType, legacyStore); } /** @@ -119,10 +121,10 @@ protected ExtensionList(Hudson hudson, Class extensionType, CopyOnWriteArrayL * @param legacyStore * Place to store manually registered instances. The version of the constructor that * omits this uses a new {@link Vector}, making the storage lifespan tied to the life of {@link ExtensionList}. - * If the manually registered instances are scoped to VM level, the caller should pass in a static list. + * If the manually registered instances are scoped to VM level, the caller should pass in a static list. */ protected ExtensionList(Jenkins jenkins, Class extensionType, CopyOnWriteArrayList> legacyStore) { - this.hudson = (Hudson)jenkins; + this.hudson = (Hudson) jenkins; this.jenkins = jenkins; this.extensionType = extensionType; this.legacyInstances = legacyStore; @@ -145,7 +147,7 @@ public void addListener(@NonNull ExtensionListListener listener) { */ public @CheckForNull U get(@NonNull Class type) { for (T ext : this) - if(ext.getClass()==type) + if (ext.getClass() == type) return type.cast(ext); return null; } @@ -153,21 +155,21 @@ public void addListener(@NonNull ExtensionListListener listener) { /** * Looks for the extension instance of the given type (subclasses excluded), * or throws an IllegalStateException. - * + * * Meant to simplify call inside @Extension annotated class to retrieve their own instance. */ public @NonNull U getInstance(@NonNull Class type) throws IllegalStateException { for (T ext : this) - if(ext.getClass()==type) + if (ext.getClass() == type) return type.cast(ext); - + throw new IllegalStateException("The class " + type.getName() + " was not found, potentially not yet loaded"); } @Override public @NonNull Iterator iterator() { - // we need to intercept mutation, so for now don't allow Iterator.remove - return new AdaptedIterator,T>(Iterators.readOnly(ensureLoaded().iterator())) { + // we need to intercept mutation, so for now don't allow Iterator.remove + return new AdaptedIterator, T>(Iterators.readOnly(ensureLoaded().iterator())) { @Override protected T adapt(ExtensionComponent item) { return item.getInstance(); @@ -186,7 +188,7 @@ public List> getComponents() { public T get(int index) { return ensureLoaded().get(index).getInstance(); } - + @Override public int size() { return ensureLoaded().size(); @@ -199,7 +201,7 @@ public List reverseView() { return new AbstractList() { @Override public T get(int index) { - return ExtensionList.this.get(size()-index-1); + return ExtensionList.this.get(size() - index - 1); } @Override @@ -214,7 +216,7 @@ public boolean remove(Object o) { try { return removeSync(o); } finally { - if(extensions!=null) { + if (extensions != null) { fireOnChangeListeners(); } } @@ -237,9 +239,9 @@ public boolean removeAll(Collection c) { private synchronized boolean removeSync(Object o) { boolean removed = removeComponent(legacyInstances, o); - if(extensions!=null) { + if (extensions != null) { List> r = new ArrayList<>(extensions); - removed |= removeComponent(r,o); + removed |= removeComponent(r, o); extensions = sort(r); } return removed; @@ -273,7 +275,7 @@ public boolean add(T t) { try { return addSync(t); } finally { - if(extensions!=null) { + if (extensions != null) { fireOnChangeListeners(); } } @@ -282,7 +284,7 @@ public boolean add(T t) { private synchronized boolean addSync(T t) { legacyInstances.add(new ExtensionComponent<>(t)); // if we've already filled extensions, add it - if(extensions!=null) { + if (extensions != null) { List> r = new ArrayList<>(extensions); r.add(new ExtensionComponent<>(t)); extensions = sort(r); @@ -308,13 +310,13 @@ public T getDynamic(String className) { } private List> ensureLoaded() { - if(extensions!=null) + if (extensions != null) return extensions; // already loaded if (jenkins == null || jenkins.getInitLevel().compareTo(InitMilestone.PLUGINS_PREPARED) < 0) return legacyInstances; // can't perform the auto discovery until all plugins are loaded, so just make the legacy instances visible synchronized (getLoadLock()) { - if(extensions==null) { + if (extensions == null) { List> r = load(); r.addAll(legacyInstances); extensions = sort(r); @@ -327,7 +329,7 @@ private List> ensureLoaded() { * Chooses the object that locks the loading of the extension instances. */ protected Object getLoadLock() { - return jenkins.lookup.setIfNull(Lock.class,new Lock()); + return Objects.requireNonNull(jenkins).lookup.setIfNull(Lock.class, new Lock()); } /** @@ -337,7 +339,7 @@ protected Object getLoadLock() { public void refresh(ExtensionComponentSet delta) { boolean fireOnChangeListeners = false; synchronized (getLoadLock()) { - if (extensions==null) + if (extensions == null) return; // not yet loaded. when we load it, we'll load everything visible by then, so no work needed Collection> found = load(delta); @@ -379,7 +381,7 @@ protected List> load() { LOGGER.log(Level.FINER, String.format("Loading ExtensionList '%s' from", extensionType.getName()), new Throwable("Only present for stacktrace information")); } - return jenkins.getPluginManager().getPluginStrategy().findComponents(extensionType, hudson); + return Objects.requireNonNull(jenkins).getPluginManager().getPluginStrategy().findComponents(extensionType, hudson); } /** @@ -409,12 +411,12 @@ protected List> sort(List> r) { */ @Deprecated public static ExtensionList create(Hudson hudson, Class type) { - return create((Jenkins)hudson,type); + return create((Jenkins) hudson, type); } @SuppressWarnings({"unchecked", "rawtypes"}) public static ExtensionList create(Jenkins jenkins, Class type) { - if(type.getAnnotation(LegacyInstancesAreScopedToHudson.class)!=null) + if (type.getAnnotation(LegacyInstancesAreScopedToHudson.class) != null) return new ExtensionList<>(jenkins, type); else { return new ExtensionList(jenkins, type, staticLegacyInstances.computeIfAbsent(type, key -> new CopyOnWriteArrayList())); diff --git a/core/src/main/java/hudson/ExtensionListListener.java b/core/src/main/java/hudson/ExtensionListListener.java index f5c8528add399..af3c0e18b7f48 100644 --- a/core/src/main/java/hudson/ExtensionListListener.java +++ b/core/src/main/java/hudson/ExtensionListListener.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; /** @@ -35,7 +36,7 @@ public abstract class ExtensionListListener { * {@link ExtensionList} contents has changed. *

* This would be called when an entry gets added to or removed from the list for any reason e.g. - * when a dynamically loaded plugin introduces a new {@link ExtensionPoint} implementation + * when a dynamically loaded plugin introduces a new {@link ExtensionPoint} implementation * that adds an entry to the {@link ExtensionList} being listened to. */ public abstract void onChange(); diff --git a/core/src/main/java/hudson/ExtensionListView.java b/core/src/main/java/hudson/ExtensionListView.java index 3655085bb9513..0127752e46bd1 100644 --- a/core/src/main/java/hudson/ExtensionListView.java +++ b/core/src/main/java/hudson/ExtensionListView.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import hudson.tasks.UserNameResolver; diff --git a/core/src/main/java/hudson/ExtensionPoint.java b/core/src/main/java/hudson/ExtensionPoint.java index 73063ec8324d9..e04581798fc62 100644 --- a/core/src/main/java/hudson/ExtensionPoint.java +++ b/core/src/main/java/hudson/ExtensionPoint.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import static java.lang.annotation.ElementType.TYPE; @@ -51,7 +52,7 @@ public interface ExtensionPoint { /** * Used by designers of extension points (direct subtypes of {@link ExtensionPoint}) to indicate that * the legacy instances are scoped to {@link Jenkins} instance. By default, legacy instances are - * static scope. + * static scope. */ @Target(TYPE) @Retention(RUNTIME) diff --git a/core/src/main/java/hudson/FeedAdapter.java b/core/src/main/java/hudson/FeedAdapter.java index 981c5cfe8816f..632001ae360ae 100644 --- a/core/src/main/java/hudson/FeedAdapter.java +++ b/core/src/main/java/hudson/FeedAdapter.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import java.util.Calendar; diff --git a/core/src/main/java/hudson/FilePath.java b/core/src/main/java/hudson/FilePath.java index 5b79710b25f37..cfc05836dc21a 100644 --- a/core/src/main/java/hudson/FilePath.java +++ b/core/src/main/java/hudson/FilePath.java @@ -1,20 +1,20 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, * Eric Lefevre-Ardant, Erik Ramfelt, Michael B. Donohue, Alan Harder, * Manufacture Francaise des Pneumatiques Michelin, Romain Seguy - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,6 +23,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import static hudson.FilePath.TarCompression.GZIP; @@ -41,7 +42,6 @@ import hudson.model.Computer; import hudson.model.Item; import hudson.model.TaskListener; -import hudson.os.PosixException; import hudson.remoting.Callable; import hudson.remoting.Channel; import hudson.remoting.DelegatingCallable; @@ -69,7 +69,6 @@ import java.io.BufferedOutputStream; import java.io.File; import java.io.FileFilter; -import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; @@ -86,6 +85,7 @@ import java.net.URI; import java.net.URL; import java.net.URLConnection; +import java.nio.charset.Charset; import java.nio.file.FileSystemException; import java.nio.file.FileSystems; import java.nio.file.Files; @@ -118,10 +118,8 @@ import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; -import jenkins.FilePathFilter; import jenkins.MasterToSlaveFileCallable; import jenkins.SlaveToMasterFileCallable; -import jenkins.SoloFilePathFilter; import jenkins.model.Jenkins; import jenkins.security.MasterToSlaveCallable; import jenkins.util.ContextResettingExecutorService; @@ -199,7 +197,7 @@ *

* When {@link FileCallable} is transferred to a remote node, it will be done so * by using the same Java serialization scheme that the remoting module uses. - * See {@link Channel} for more about this. + * See {@link Channel} for more about this. * *

* {@link FilePath} itself can be sent over to a remote node as a part of {@link Callable} @@ -230,7 +228,7 @@ public final class FilePath implements SerializableOnlyOverRemoting { * This is used to determine whether we are running on the controller / the built-in node, or an agent. */ private transient VirtualChannel channel; - + /** * Represent the path to the file in the controller or the agent * Since the platform of the agent might be different, can't use java.io.File @@ -279,14 +277,14 @@ private Object readResolve() { } private String resolvePathIfRelative(@NonNull FilePath base, @NonNull String rel) { - if(isAbsolute(rel)) return rel; - if(base.isUnix()) { + if (isAbsolute(rel)) return rel; + if (base.isUnix()) { // shouldn't need this replace, but better safe than sorry - return base.remote+'/'+rel.replace('\\','/'); + return base.remote + '/' + rel.replace('\\', '/'); } else { // need this replace, see Slave.getWorkspaceFor and AbstractItem.getFullName, nested jobs on Windows // agents will always have a rel containing at least one '/' character. JENKINS-13649 - return base.remote+'\\'+rel.replace('/','\\'); + return base.remote + '\\' + rel.replace('/', '\\'); } } @@ -328,7 +326,7 @@ public static String normalize(@NonNull String path) { while (++i < end && ((c = path.charAt(i)) == '/' || c == '\\')) ; // Add token for separator unless we reached the end - if (i < end) tokens.add(path.substring(s, s+1)); + if (i < end) tokens.add(path.substring(s, s + 1)); s = i; } } @@ -351,7 +349,7 @@ public static String normalize(@NonNull String path) { // Normalize: remove something/.. plus separator before/after i -= 2; for (int j = 0; j < 3; j++) tokens.remove(i); - if (i > 0) tokens.remove(i-1); + if (i > 0) tokens.remove(i - 1); else if (tokens.size() > 0) tokens.remove(0); } } else @@ -368,14 +366,14 @@ public static String normalize(@NonNull String path) { */ boolean isUnix() { // if the path represents a local path, there' no need to guess. - if(!isRemote()) - return File.pathSeparatorChar!=';'; - + if (!isRemote()) + return File.pathSeparatorChar != ';'; + // note that we can't use the usual File.pathSeparator and etc., as the OS of // the machine where this code runs and the OS that this FilePath refers to may be different. // Windows absolute path is 'X:\...', so this is usually a good indication of Windows path - if(remote.length()>3 && remote.charAt(1)==':' && remote.charAt(2)=='\\') + if (remote.length() > 3 && remote.charAt(1) == ':' && remote.charAt(2) == '\\') return false; // Windows can handle '/' as a path separator but Unix can't, // so err on Unix side @@ -404,7 +402,7 @@ public void createZipArchive(OutputStream os) throws IOException, InterruptedExc * Creates a zip file from this directory or a file and sends that to the given output stream. */ public void zip(OutputStream os) throws IOException, InterruptedException { - zip(os,(FileFilter)null); + zip(os, (FileFilter) null); } public void zip(FilePath dst) throws IOException, InterruptedException { @@ -412,7 +410,7 @@ public void zip(FilePath dst) throws IOException, InterruptedException { zip(os); } } - + /** * Creates a zip file from this directory by using the specified filter, * and sends the result to the given output stream. @@ -423,7 +421,7 @@ public void zip(FilePath dst) throws IOException, InterruptedException { * @since 1.315 */ public void zip(OutputStream os, FileFilter filter) throws IOException, InterruptedException { - archive(ArchiverFactory.ZIP,os,filter); + archive(ArchiverFactory.ZIP, os, filter); } /** @@ -439,7 +437,7 @@ public void zip(OutputStream os, FileFilter filter) throws IOException, Interrup */ @Deprecated public void createZipArchive(OutputStream os, final String glob) throws IOException, InterruptedException { - archive(ArchiverFactory.ZIP,os,glob); + archive(ArchiverFactory.ZIP, os, glob); } /** @@ -452,7 +450,7 @@ public void createZipArchive(OutputStream os, final String glob) throws IOExcept * @since 1.315 */ public void zip(OutputStream os, final String glob) throws IOException, InterruptedException { - archive(ArchiverFactory.ZIP,os,glob); + archive(ArchiverFactory.ZIP, os, glob); } /** @@ -515,7 +513,8 @@ public int archive(final ArchiverFactory factory, OutputStream os, final DirScan final OutputStream out = channel != null ? new RemoteOutputStream(os) : os; return act(new Archive(factory, out, scanner, verificationRoot, noFollowLinks)); } - private static class Archive extends SecureFileCallable { + + private static class Archive extends MasterToSlaveFileCallable { private final ArchiverFactory factory; private final OutputStream out; private final DirScanner scanner; @@ -529,11 +528,12 @@ private static class Archive extends SecureFileCallable { this.verificationRoot = verificationRoot; this.noFollowLinks = noFollowLinks; } + @Override public Integer invoke(File f, VirtualChannel channel) throws IOException { Archiver a = factory.create(out); try { - scanner.scan(f, ignoringSymlinks(reading(a), verificationRoot, noFollowLinks)); + scanner.scan(f, ignoringSymlinks(a, verificationRoot, noFollowLinks)); } finally { a.close(); } @@ -544,11 +544,11 @@ public Integer invoke(File f, VirtualChannel channel) throws IOException { } public int archive(final ArchiverFactory factory, OutputStream os, final FileFilter filter) throws IOException, InterruptedException { - return archive(factory,os,new DirScanner.Filter(filter)); + return archive(factory, os, new DirScanner.Filter(filter)); } public int archive(final ArchiverFactory factory, OutputStream os, final String glob) throws IOException, InterruptedException { - return archive(factory,os,new DirScanner.Glob(glob,null)); + return archive(factory, os, new DirScanner.Glob(glob, null)); } /** @@ -561,26 +561,31 @@ public int archive(final ArchiverFactory factory, OutputStream os, final String */ public void unzip(final FilePath target) throws IOException, InterruptedException { // TODO: post release, re-unite two branches by introducing FileStreamCallable that resolves InputStream - if (channel != target.channel) {// local -> remote or remote->local + if (channel != target.channel) { // local -> remote or remote->local final RemoteInputStream in = new RemoteInputStream(read(), Flag.GREEDY); target.act(new UnzipRemote(in)); - } else {// local -> local or remote->remote + } else { // local -> local or remote->remote target.act(new UnzipLocal(this)); } } - private static class UnzipRemote extends SecureFileCallable { + + private static class UnzipRemote extends MasterToSlaveFileCallable { private final RemoteInputStream in; + UnzipRemote(RemoteInputStream in) { this.in = in; } + @Override public Void invoke(File dir, VirtualChannel channel) throws IOException, InterruptedException { unzip(dir, in); return null; } + private static final long serialVersionUID = 1L; } - private static class UnzipLocal extends SecureFileCallable { + + private static class UnzipLocal extends MasterToSlaveFileCallable { private final FilePath filePath; @@ -593,9 +598,10 @@ public Void invoke(File dir, VirtualChannel channel) throws IOException, Interru if (this.filePath.isRemote()) { throw new IllegalStateException("Expected local path for file: " + filePath); // this.channel==target.channel above } - unzip(dir, reading(new File(this.filePath.getRemote()))); // shortcut to local file + unzip(dir, new File(this.filePath.getRemote())); // shortcut to local file return null; } + private static final long serialVersionUID = 1L; } @@ -612,30 +618,35 @@ public Void invoke(File dir, VirtualChannel channel) throws IOException, Interru public void untar(final FilePath target, final TarCompression compression) throws IOException, InterruptedException { final FilePath source = FilePath.this; // TODO: post release, re-unite two branches by introducing FileStreamCallable that resolves InputStream - if (source.channel != target.channel) {// local -> remote or remote->local + if (source.channel != target.channel) { // local -> remote or remote->local final RemoteInputStream in = new RemoteInputStream(source.read(), Flag.GREEDY); target.act(new UntarRemote(source.getName(), compression, in)); - } else {// local -> local or remote->remote + } else { // local -> local or remote->remote target.act(new UntarLocal(source, compression)); } } - private static class UntarRemote extends SecureFileCallable { + + private static class UntarRemote extends MasterToSlaveFileCallable { private final TarCompression compression; private final RemoteInputStream in; private final String name; + UntarRemote(String name, TarCompression compression, RemoteInputStream in) { this.compression = compression; this.in = in; this.name = name; } + @Override public Void invoke(File dir, VirtualChannel channel) throws IOException, InterruptedException { readFromTar(name, dir, compression.extract(in)); return null; } + private static final long serialVersionUID = 1L; } - private static class UntarLocal extends SecureFileCallable { + + private static class UntarLocal extends MasterToSlaveFileCallable { private final TarCompression compression; private final FilePath filePath; @@ -643,11 +654,13 @@ private static class UntarLocal extends SecureFileCallable { this.filePath = source; this.compression = compression; } + @Override public Void invoke(File dir, VirtualChannel channel) throws IOException, InterruptedException { readFromTar(this.filePath.getName(), dir, compression.extract(this.filePath.read())); return null; } + private static final long serialVersionUID = 1L; } @@ -663,16 +676,20 @@ public void unzipFrom(InputStream _in) throws IOException, InterruptedException final InputStream in = new RemoteInputStream(_in, Flag.GREEDY); act(new UnzipFrom(in)); } - private static class UnzipFrom extends SecureFileCallable { + + private static class UnzipFrom extends MasterToSlaveFileCallable { private final InputStream in; + UnzipFrom(InputStream in) { this.in = in; } + @Override public Void invoke(File dir, VirtualChannel channel) throws IOException { unzip(dir, in); return null; } + private static final long serialVersionUID = 1L; } @@ -681,7 +698,7 @@ private static void unzip(File dir, InputStream in) throws IOException { try { // TODO why does this not simply use ZipInputStream? IOUtils.copy(in, tmpFile); - unzip(dir,tmpFile); + unzip(dir, tmpFile); } finally { Files.delete(Util.fileToPath(tmpFile)); @@ -709,12 +726,12 @@ private static void unzip(File dir, File zipFile) throws IOException { mkdirs(p); } try (InputStream input = zip.getInputStream(e)) { - IOUtils.copy(input, writing(f)); + IOUtils.copy(input, f); } try { FilePath target = new FilePath(f); int mode = e.getUnixMode(); - if (mode!=0) // Ant returns 0 if the archive doesn't record the access mode + if (mode != 0) // Ant returns 0 if the archive doesn't record the access mode target.chmod(mode); } catch (InterruptedException ex) { LOGGER.log(Level.WARNING, "unable to set permissions", ex); @@ -733,11 +750,13 @@ private static void unzip(File dir, File zipFile) throws IOException { public FilePath absolutize() throws IOException, InterruptedException { return new FilePath(channel, act(new Absolutize())); } - private static class Absolutize extends SecureFileCallable { + + private static class Absolutize extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public String invoke(File f, VirtualChannel channel) throws IOException { - return stating(f).getAbsolutePath(); + return f.getAbsolutePath(); } } @@ -745,7 +764,8 @@ public String invoke(File f, VirtualChannel channel) throws IOException { public boolean hasSymlink(FilePath verificationRoot, boolean noFollowLinks) throws IOException, InterruptedException { return act(new HasSymlink(verificationRoot == null ? null : verificationRoot.remote, noFollowLinks)); } - private static class HasSymlink extends SecureFileCallable { + + private static class HasSymlink extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; private final String verificationRoot; private final boolean noFollowLinks; @@ -757,7 +777,7 @@ private static class HasSymlink extends SecureFileCallable { @Override public Boolean invoke(File f, VirtualChannel channel) throws IOException { - return isSymlink(stating(f), verificationRoot, noFollowLinks); + return isSymlink(f, verificationRoot, noFollowLinks); } } @@ -780,6 +800,7 @@ private static class SymlinkRetainingFileFilter implements FileFilter, Serializa public boolean accept(File file) { return isSymlink(file, verificationRoot, noFollowLinks); } + private static final long serialVersionUID = 1L; } @@ -795,21 +816,25 @@ public boolean accept(File file) { public void symlinkTo(final String target, final TaskListener listener) throws IOException, InterruptedException { act(new SymlinkTo(target, listener)); } - private static class SymlinkTo extends SecureFileCallable { + + private static class SymlinkTo extends MasterToSlaveFileCallable { private final String target; private final TaskListener listener; + SymlinkTo(String target, TaskListener listener) { this.target = target; this.listener = listener; } + private static final long serialVersionUID = 1L; + @Override public Void invoke(File f, VirtualChannel channel) throws IOException, InterruptedException { - Util.createSymlink(symlinking(f).getParentFile(), target, f.getName(), listener); + Util.createSymlink(f.getParentFile(), target, f.getName(), listener); return null; } } - + /** * Resolves symlink, if the given file is a symlink. Otherwise return null. *

@@ -820,11 +845,13 @@ public Void invoke(File f, VirtualChannel channel) throws IOException, Interrupt public String readLink() throws IOException, InterruptedException { return act(new ReadLink()); } - private static class ReadLink extends SecureFileCallable { + + private static class ReadLink extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public String invoke(File f, VirtualChannel channel) throws IOException, InterruptedException { - return Util.resolveSymlink(reading(f)); + return Util.resolveSymlink(f); } } @@ -844,7 +871,7 @@ public boolean equals(Object o) { public int hashCode() { return 31 * (channel != null ? channel.hashCode() : 0) + remote.hashCode(); } - + /** * Supported tar file compression methods. */ @@ -854,6 +881,7 @@ public enum TarCompression { public InputStream extract(InputStream in) { return new BufferedInputStream(in); } + @Override public OutputStream compress(OutputStream out) { return new BufferedOutputStream(out); @@ -862,15 +890,16 @@ public OutputStream compress(OutputStream out) { GZIP { @Override public InputStream extract(InputStream _in) throws IOException { - HeadBufferingStream in = new HeadBufferingStream(_in,SIDE_BUFFER_SIZE); + HeadBufferingStream in = new HeadBufferingStream(_in, SIDE_BUFFER_SIZE); try { return new GZIPInputStream(in, 8192, true); } catch (IOException e) { // various people reported "java.io.IOException: Not in GZIP format" here, so diagnose this problem better in.fillSide(); - throw new IOException(e.getMessage()+"\nstream="+Util.toHexString(in.getSideBuffer()),e); + throw new IOException(e.getMessage() + "\nstream=" + Util.toHexString(in.getSideBuffer()), e); } } + @Override public OutputStream compress(OutputStream out) throws IOException { return new GZIPOutputStream(new BufferedOutputStream(out)); @@ -878,6 +907,7 @@ public OutputStream compress(OutputStream out) throws IOException { }; public abstract InputStream extract(InputStream in) throws IOException; + public abstract OutputStream compress(OutputStream in) throws IOException; } @@ -898,18 +928,22 @@ public void untarFrom(InputStream _in, final TarCompression compression) throws _in.close(); } } - private static class UntarFrom extends SecureFileCallable { + + private static class UntarFrom extends MasterToSlaveFileCallable { private final TarCompression compression; private final InputStream in; + UntarFrom(TarCompression compression, InputStream in) { this.compression = compression; this.in = in; } + @Override public Void invoke(File dir, VirtualChannel channel) throws IOException { - readFromTar("input stream",dir, compression.extract(in)); // #writing etc. are called in #readFromTar + readFromTar("input stream", dir, compression.extract(in)); return null; } + private static final long serialVersionUID = 1L; } @@ -995,7 +1029,7 @@ private boolean installIfNecessaryFrom(@NonNull URL archive, @NonNull TaskListen long sourceTimestamp = con.getLastModified(); - if(this.exists()) { + if (this.exists()) { if (lastModified != 0 && sourceTimestamp == lastModified) return false; // already up to date this.deleteContents(); @@ -1020,27 +1054,29 @@ private boolean installIfNecessaryFrom(@NonNull URL archive, @NonNull TaskListen InputStream in = archive.getProtocol().startsWith("http") ? ProxyConfiguration.getInputStream(archive) : con.getInputStream(); CountingInputStream cis = new CountingInputStream(in); try { - if(archive.toExternalForm().endsWith(".zip")) + if (archive.toExternalForm().endsWith(".zip")) unzipFrom(cis); else - untarFrom(cis,GZIP); + untarFrom(cis, GZIP); } catch (IOException e) { throw new IOException(String.format("Failed to unpack %s (%d bytes read of total %d)", - archive,cis.getByteCount(),con.getContentLength()),e); + archive, cis.getByteCount(), con.getContentLength()), e); } timestamp.touch(sourceTimestamp); return true; } catch (IOException e) { - throw new IOException("Failed to install "+archive+" to "+remote,e); + throw new IOException("Failed to install " + archive + " to " + remote, e); } } // this reads from arbitrary URL private static final class Unpack extends MasterToSlaveFileCallable { private final URL archive; + Unpack(URL archive) { this.archive = archive; } + @Override public Void invoke(File dir, VirtualChannel channel) throws IOException, InterruptedException { try (InputStream in = archive.openStream()) { CountingInputStream cis = new CountingInputStream(in); @@ -1084,7 +1120,7 @@ public void copyFrom(InputStream in) throws IOException, InterruptedException { /** * Convenience method to call {@link FilePath#copyTo(FilePath)}. - * + * * @since 1.311 */ public void copyFrom(FilePath src) throws IOException, InterruptedException { @@ -1095,9 +1131,9 @@ public void copyFrom(FilePath src) throws IOException, InterruptedException { * Place the data from {@link FileItem} into the file location specified by this {@link FilePath} object. */ public void copyFrom(FileItem file) throws IOException, InterruptedException { - if(channel==null) { + if (channel == null) { try { - file.write(writing(new File(remote))); + file.write(new File(remote)); } catch (IOException e) { throw e; } catch (Exception e) { @@ -1106,7 +1142,7 @@ public void copyFrom(FileItem file) throws IOException, InterruptedException { } else { try (InputStream i = file.getInputStream(); OutputStream o = write()) { - org.apache.commons.io.IOUtils.copy(i,o); + org.apache.commons.io.IOUtils.copy(i, o); } } } @@ -1138,34 +1174,25 @@ public interface FileCallable extends Serializable, RoleSensitive { T invoke(File f, VirtualChannel channel) throws IOException, InterruptedException; } - /** - * {@link FileCallable}s that can be executed anywhere, including the controller. - * - * The code is the same as {@link SlaveToMasterFileCallable}, but used as a marker to - * designate those impls that use {@link FilePathFilter}. - */ - /*package*/ abstract static class SecureFileCallable extends SlaveToMasterFileCallable { - } - /** * Executes some program on the machine that this {@link FilePath} exists, * so that one can perform local file operations. */ public T act(final FileCallable callable) throws IOException, InterruptedException { - return act(callable,callable.getClass().getClassLoader()); + return act(callable, callable.getClass().getClassLoader()); } private T act(final FileCallable callable, ClassLoader cl) throws IOException, InterruptedException { - if(channel!=null) { + if (channel != null) { // run this on a remote system try { - DelegatingCallable wrapper = new FileCallableWrapper<>(callable, cl, this); + DelegatingCallable wrapper = new FileCallableWrapper<>(callable, cl, this); for (FileCallableWrapperFactory factory : ExtensionList.lookup(FileCallableWrapperFactory.class)) { wrapper = factory.wrap(wrapper); } return channel.call(wrapper); } catch (TunneledInterruptedException e) { - throw (InterruptedException)new InterruptedException(e.getMessage()).initCause(e); + throw (InterruptedException) new InterruptedException(e.getMessage()).initCause(e); } } else { // the file is on the local machine. @@ -1184,7 +1211,7 @@ private T act(final FileCallable callable, ClassLoader cl) throws IOExcep */ public abstract static class FileCallableWrapperFactory implements ExtensionPoint { - public abstract DelegatingCallable wrap(DelegatingCallable callable); + public abstract DelegatingCallable wrap(DelegatingCallable callable); } @@ -1235,15 +1262,15 @@ protected void after() {} */ public Future actAsync(final FileCallable callable) throws IOException, InterruptedException { try { - DelegatingCallable wrapper = new FileCallableWrapper<>(callable, this); + DelegatingCallable wrapper = new FileCallableWrapper<>(callable, this); for (FileCallableWrapperFactory factory : ExtensionList.lookup(FileCallableWrapperFactory.class)) { wrapper = factory.wrap(wrapper); } - return (channel!=null ? channel : localChannel) + return (channel != null ? channel : localChannel) .callAsync(wrapper); } catch (IOException e) { // wrap it into a new IOException so that we get the caller's stack trace as well. - throw new IOException("remote file operation failed",e); + throw new IOException("remote file operation failed", e); } } @@ -1251,8 +1278,8 @@ public Future actAsync(final FileCallable callable) throws IOException * Executes some program on the machine that this {@link FilePath} exists, * so that one can perform local file operations. */ - public V act(Callable callable) throws IOException, InterruptedException, E { - if(channel!=null) { + public V act(Callable callable) throws IOException, InterruptedException, E { + if (channel != null) { // run this on a remote system return channel.call(callable); } else { @@ -1268,20 +1295,23 @@ public V act(Callable callable) throws IOException, * * @since 1.522 */ - public Callable asCallableWith(final FileCallable task) { + public Callable asCallableWith(final FileCallable task) { return new CallableWith<>(task); } + private class CallableWith implements Callable { private final FileCallable task; + CallableWith(FileCallable task) { this.task = task; } + @Override public V call() throws IOException { try { return act(task); } catch (InterruptedException e) { - throw (IOException)new InterruptedIOException().initCause(e); + throw (IOException) new InterruptedIOException().initCause(e); } } @@ -1300,11 +1330,13 @@ public void checkRoles(RoleChecker checker) throws SecurityException { public URI toURI() throws IOException, InterruptedException { return act(new ToURI()); } - private static class ToURI extends SecureFileCallable { + + private static class ToURI extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public URI invoke(File f, VirtualChannel channel) { - return stating(f).toURI(); + return f.toURI(); } } @@ -1326,7 +1358,7 @@ public VirtualFile toVirtualFile() { Jenkins j = Jenkins.getInstanceOrNull(); if (j != null) { for (Computer c : j.getComputers()) { - if (getChannel()==c.getChannel()) { + if (getChannel() == c.getChannel()) { return c; } } @@ -1342,11 +1374,13 @@ public void mkdirs() throws IOException, InterruptedException { throw new IOException("Failed to mkdirs: " + remote); } } - private static class Mkdirs extends SecureFileCallable { + + private static class Mkdirs extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public Boolean invoke(File f, VirtualChannel channel) throws IOException, InterruptedException { - if(mkdirs(f) || f.exists()) + if (mkdirs(f) || f.exists()) return true; // OK // following Ant task to avoid possible race condition. @@ -1355,7 +1389,7 @@ public Boolean invoke(File f, VirtualChannel channel) throws IOException, Interr return mkdirs(f) || f.exists(); } } - + /** * Deletes all suffixes recursively. * @throws IOException if it exists but could not be successfully deleted @@ -1368,17 +1402,17 @@ public void deleteSuffixesRecursive() throws IOException, InterruptedException { /** * Deletes all suffixed directories that are separated by {@link WorkspaceList#COMBINATOR}, including all its contents recursively. */ - private static class DeleteSuffixesRecursive extends SecureFileCallable { + private static class DeleteSuffixesRecursive extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; @Override public Void invoke(File f, VirtualChannel channel) throws IOException { for (File file : listParentFiles(f)) { if (file.getName().startsWith(f.getName() + WorkspaceList.COMBINATOR)) { - Util.deleteRecursive(file.toPath(), path -> deleting(path.toFile())); + Util.deleteRecursive(file.toPath(), path -> path.toFile()); } } - + return null; } } @@ -1400,11 +1434,13 @@ private static File[] listParentFiles(File f) { public void deleteRecursive() throws IOException, InterruptedException { act(new DeleteRecursive()); } - private static class DeleteRecursive extends SecureFileCallable { + + private static class DeleteRecursive extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public Void invoke(File f, VirtualChannel channel) throws IOException { - Util.deleteRecursive(fileToPath(f), path -> deleting(path.toFile())); + Util.deleteRecursive(fileToPath(f), path -> path.toFile()); return null; } } @@ -1415,11 +1451,13 @@ public Void invoke(File f, VirtualChannel channel) throws IOException { public void deleteContents() throws IOException, InterruptedException { act(new DeleteContents()); } - private static class DeleteContents extends SecureFileCallable { + + private static class DeleteContents extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public Void invoke(File f, VirtualChannel channel) throws IOException { - Util.deleteContentsRecursive(fileToPath(f), path -> deleting(path.toFile())); + Util.deleteContentsRecursive(fileToPath(f), path -> path.toFile()); return null; } } @@ -1432,28 +1470,29 @@ public Void invoke(File f, VirtualChannel channel) throws IOException { public String getBaseName() { String n = getName(); int idx = n.lastIndexOf('.'); - if (idx<0) return n; - return n.substring(0,idx); + if (idx < 0) return n; + return n.substring(0, idx); } /** * Gets just the file name portion without directories. * * For example, "foo.txt" for "../abc/foo.txt" */ + public String getName() { String r = remote; - if(r.endsWith("\\") || r.endsWith("/")) - r = r.substring(0,r.length()-1); + if (r.endsWith("\\") || r.endsWith("/")) + r = r.substring(0, r.length() - 1); - int len = r.length()-1; - while(len>=0) { + int len = r.length() - 1; + while (len >= 0) { char ch = r.charAt(len); - if(ch=='\\' || ch=='/') + if (ch == '\\' || ch == '/') break; len--; } - return r.substring(len+1); + return r.substring(len + 1); } /** @@ -1470,7 +1509,7 @@ public FilePath sibling(String rel) { * Returns a {@link FilePath} by adding the given suffix to this path name. */ public FilePath withSuffix(String suffix) { - return new FilePath(channel,remote+suffix); + return new FilePath(channel, remote + suffix); } /** @@ -1479,7 +1518,7 @@ public FilePath withSuffix(String suffix) { * @return a file on the same channel */ public @NonNull FilePath child(String relOrAbsolute) { - return new FilePath(this,relOrAbsolute); + return new FilePath(this, relOrAbsolute); } /** @@ -1491,11 +1530,11 @@ public FilePath getParent() { int i = remote.length() - 2; for (; i >= 0; i--) { char ch = remote.charAt(i); - if(ch=='\\' || ch=='/') + if (ch == '\\' || ch == '/') break; } - return i >= 0 ? new FilePath( channel, remote.substring(0,i+1) ) : null; + return i >= 0 ? new FilePath(channel, remote.substring(0, i + 1)) : null; } /** @@ -1515,21 +1554,24 @@ public FilePath createTempFile(final String prefix, final String suffix) throws try { return new FilePath(this, act(new CreateTempFile(prefix, suffix))); } catch (IOException e) { - throw new IOException("Failed to create a temp file on "+remote,e); + throw new IOException("Failed to create a temp file on " + remote, e); } } - private static class CreateTempFile extends SecureFileCallable { + + private static class CreateTempFile extends MasterToSlaveFileCallable { private final String prefix; private final String suffix; + CreateTempFile(String prefix, String suffix) { this.prefix = prefix; this.suffix = suffix; } + private static final long serialVersionUID = 1L; + @Override public String invoke(File dir, VirtualChannel channel) throws IOException { - creating(new File(dir, prefix + "-security-check-dummy-" + suffix)); // use fake file to check access before creation - File f = creating(File.createTempFile(prefix, suffix, dir)); + File f = File.createTempFile(prefix, suffix, dir); return f.getName(); } } @@ -1551,7 +1593,7 @@ public String invoke(File dir, VirtualChannel channel) throws IOException { * @see File#createTempFile(String, String) */ public FilePath createTextTempFile(final String prefix, final String suffix, final String contents) throws IOException, InterruptedException { - return createTextTempFile(prefix,suffix,contents,true); + return createTextTempFile(prefix, suffix, contents, true); } /** @@ -1580,37 +1622,39 @@ public FilePath createTextTempFile(final String prefix, final String suffix, fin try { return new FilePath(channel, act(new CreateTextTempFile(inThisDirectory, prefix, suffix, contents))); } catch (IOException e) { - throw new IOException("Failed to create a temp file on "+remote,e); + throw new IOException("Failed to create a temp file on " + remote, e); } } - private static class CreateTextTempFile extends SecureFileCallable { + + private static class CreateTextTempFile extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; private final boolean inThisDirectory; private final String prefix; private final String suffix; private final String contents; + CreateTextTempFile(boolean inThisDirectory, String prefix, String suffix, String contents) { this.inThisDirectory = inThisDirectory; this.prefix = prefix; this.suffix = suffix; this.contents = contents; } + @Override public String invoke(File dir, VirtualChannel channel) throws IOException { - if(!inThisDirectory) + if (!inThisDirectory) dir = new File(System.getProperty("java.io.tmpdir")); else mkdirs(dir); File f; try { - creating(new File(dir, prefix + "-security-check-dummy-" + suffix)); // use fake file to check access before creation - f = creating(File.createTempFile(prefix, suffix, dir)); + f = File.createTempFile(prefix, suffix, dir); } catch (IOException e) { - throw new IOException("Failed to create a temporary directory in "+dir,e); + throw new IOException("Failed to create a temporary directory in " + dir, e); } - try (Writer w = new FileWriter(writing(f))) { + try (Writer w = Files.newBufferedWriter(Util.fileToPath(f), Charset.defaultCharset())) { w.write(contents); } @@ -1643,18 +1687,21 @@ public FilePath createTempDir(final String prefix, final String suffix) throws I String name = String.join(".", s); return new FilePath(this, act(new CreateTempDir(name))); } catch (IOException e) { - throw new IOException("Failed to create a temp directory on "+remote,e); + throw new IOException("Failed to create a temp directory on " + remote, e); } } - private static class CreateTempDir extends SecureFileCallable { + + private static class CreateTempDir extends MasterToSlaveFileCallable { private final String name; + CreateTempDir(String name) { this.name = name; } + private static final long serialVersionUID = 1L; + @Override public String invoke(File dir, VirtualChannel channel) throws IOException { - mkdirsing(new File(dir, name + "-security-test")); // ensure access Path tempPath; final boolean isPosix = FileSystems.getDefault().supportedFileAttributeViews().contains("posix"); @@ -1666,7 +1713,7 @@ public String invoke(File dir, VirtualChannel channel) throws IOException { tempPath = Files.createTempDirectory(Util.fileToPath(dir), name); } - if (mkdirsing(tempPath.toFile()) == null) { + if (tempPath.toFile() == null) { throw new IOException("Failed to obtain file from path " + dir); } return tempPath.toFile().getName(); @@ -1682,11 +1729,13 @@ public boolean delete() throws IOException, InterruptedException { act(new Delete()); return true; } - private static class Delete extends SecureFileCallable { + + private static class Delete extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public Void invoke(File f, VirtualChannel channel) throws IOException { - Util.deleteFile(deleting(f)); + Util.deleteFile(f); return null; } } @@ -1697,11 +1746,13 @@ public Void invoke(File f, VirtualChannel channel) throws IOException { public boolean exists() throws IOException, InterruptedException { return act(new Exists()); } - private static class Exists extends SecureFileCallable { + + private static class Exists extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public Boolean invoke(File f, VirtualChannel channel) throws IOException { - return stating(f).exists(); + return f.exists(); } } @@ -1715,11 +1766,13 @@ public Boolean invoke(File f, VirtualChannel channel) throws IOException { public long lastModified() throws IOException, InterruptedException { return act(new LastModified()); } - private static class LastModified extends SecureFileCallable { + + private static class LastModified extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public Long invoke(File f, VirtualChannel channel) throws IOException { - return stating(f).lastModified(); + return f.lastModified(); } } @@ -1731,45 +1784,53 @@ public Long invoke(File f, VirtualChannel channel) throws IOException { public void touch(final long timestamp) throws IOException, InterruptedException { act(new Touch(timestamp)); } - private static class Touch extends SecureFileCallable { + + private static class Touch extends MasterToSlaveFileCallable { private final long timestamp; + Touch(long timestamp) { this.timestamp = timestamp; } + private static final long serialVersionUID = -5094638816500738429L; + @Override public Void invoke(File f, VirtualChannel channel) throws IOException { - if(!f.exists()) { - Files.newOutputStream(fileToPath(creating(f))).close(); + if (!f.exists()) { + Files.newOutputStream(fileToPath(f)).close(); } - if(!stating(f).setLastModified(timestamp)) - throw new IOException("Failed to set the timestamp of "+f+" to "+timestamp); + if (!f.setLastModified(timestamp)) + throw new IOException("Failed to set the timestamp of " + f + " to " + timestamp); return null; } } - + private void setLastModifiedIfPossible(final long timestamp) throws IOException, InterruptedException { String message = act(new SetLastModified(timestamp)); - if (message!=null) { + if (message != null) { LOGGER.warning(message); } } - private static class SetLastModified extends SecureFileCallable { + + private static class SetLastModified extends MasterToSlaveFileCallable { private final long timestamp; + SetLastModified(long timestamp) { this.timestamp = timestamp; } + private static final long serialVersionUID = -828220335793641630L; + @Override public String invoke(File f, VirtualChannel channel) throws IOException { - if(!writing(f).setLastModified(timestamp)) { + if (!f.setLastModified(timestamp)) { if (Functions.isWindows()) { // On Windows this seems to fail often. See JENKINS-11073 // Therefore don't fail, but just log a warning - return "Failed to set the timestamp of "+f+" to "+timestamp; + return "Failed to set the timestamp of " + f + " to " + timestamp; } else { - throw new IOException("Failed to set the timestamp of "+f+" to "+timestamp); + throw new IOException("Failed to set the timestamp of " + f + " to " + timestamp); } } return null; @@ -1782,14 +1843,16 @@ public String invoke(File f, VirtualChannel channel) throws IOException { public boolean isDirectory() throws IOException, InterruptedException { return act(new IsDirectory()); } - private static class IsDirectory extends SecureFileCallable { + + private static class IsDirectory extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public Boolean invoke(File f, VirtualChannel channel) throws IOException { - return stating(f).isDirectory(); + return f.isDirectory(); } } - + /** * Returns the file size in bytes. * @@ -1798,11 +1861,13 @@ public Boolean invoke(File f, VirtualChannel channel) throws IOException { public long length() throws IOException, InterruptedException { return act(new Length()); } - private static class Length extends SecureFileCallable { + + private static class Length extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public Long invoke(File f, VirtualChannel channel) throws IOException { - return stating(f).length(); + return f.length(); } } @@ -1813,8 +1878,10 @@ public Long invoke(File f, VirtualChannel channel) throws IOException { public long getFreeDiskSpace() throws IOException, InterruptedException { return act(new GetFreeDiskSpace()); } + private static class GetFreeDiskSpace extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public Long invoke(File f, VirtualChannel channel) throws IOException { return f.getFreeSpace(); @@ -1828,8 +1895,10 @@ public Long invoke(File f, VirtualChannel channel) throws IOException { public long getTotalDiskSpace() throws IOException, InterruptedException { return act(new GetTotalDiskSpace()); } + private static class GetTotalDiskSpace extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public Long invoke(File f, VirtualChannel channel) throws IOException { return f.getTotalSpace(); @@ -1843,8 +1912,10 @@ public Long invoke(File f, VirtualChannel channel) throws IOException { public long getUsableDiskSpace() throws IOException, InterruptedException { return act(new GetUsableDiskSpace()); } + private static class GetUsableDiskSpace extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public Long invoke(File f, VirtualChannel channel) throws IOException { return f.getUsableSpace(); @@ -1872,18 +1943,21 @@ public Long invoke(File f, VirtualChannel channel) throws IOException { * @see #mode() */ public void chmod(final int mask) throws IOException, InterruptedException { - if(!isUnix() || mask==-1) return; + if (!isUnix() || mask == -1) return; act(new Chmod(mask)); } - private static class Chmod extends SecureFileCallable { + + private static class Chmod extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; private final int mask; + Chmod(int mask) { this.mask = mask; } + @Override public Void invoke(File f, VirtualChannel channel) throws IOException { - _chmod(writing(f), mask); + _chmod(f, mask); return null; } @@ -1895,7 +1969,7 @@ public Void invoke(File f, VirtualChannel channel) throws IOException { private static void _chmod(File f, int mask) throws IOException { // TODO WindowsPosix actually does something here (WindowsLibC._wchmod); should we let it? // Anyway the existing calls already skip this method if on Windows. - if (File.pathSeparatorChar==';') return; // noop + if (File.pathSeparatorChar == ';') return; // noop Files.setPosixFilePermissions(fileToPath(f), Util.modeToPermissions(mask)); } @@ -1910,15 +1984,17 @@ private static void _chmod(File f, int mask) throws IOException { * @since 1.311 * @see #chmod(int) */ - public int mode() throws IOException, InterruptedException, PosixException { - if(!isUnix()) return -1; + public int mode() throws IOException, InterruptedException { + if (!isUnix()) return -1; return act(new Mode()); } - private static class Mode extends SecureFileCallable { + + private static class Mode extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public Integer invoke(File f, VirtualChannel channel) throws IOException { - return IOUtils.mode(stating(f)); + return IOUtils.mode(f); } } @@ -1930,7 +2006,7 @@ public Integer invoke(File f, VirtualChannel channel) throws IOException { */ @NonNull public List list() throws IOException, InterruptedException { - return list((FileFilter)null); + return list((FileFilter) null); } /** @@ -1965,6 +2041,7 @@ private static final class DirectoryFilter implements FileFilter, Serializable { public boolean accept(File f) { return f.isDirectory(); } + private static final long serialVersionUID = 1L; } @@ -1984,15 +2061,19 @@ public List list(final FileFilter filter) throws IOException, Interrup } return act(new ListFilter(filter), (filter != null ? filter : this).getClass().getClassLoader()); } - private static class ListFilter extends SecureFileCallable> { + + private static class ListFilter extends MasterToSlaveFileCallable> { private final FileFilter filter; + ListFilter(FileFilter filter) { this.filter = filter; } + private static final long serialVersionUID = 1L; + @Override public List invoke(File f, VirtualChannel channel) throws IOException { - File[] children = reading(f).listFiles(filter); + File[] children = f.listFiles(filter); if (children == null) { return Collections.emptyList(); } @@ -2050,23 +2131,27 @@ public FilePath[] list(final String includes, final String excludes) throws IOEx public FilePath[] list(final String includes, final String excludes, final boolean defaultExcludes) throws IOException, InterruptedException { return act(new ListGlob(includes, excludes, defaultExcludes)); } - private static class ListGlob extends SecureFileCallable { + + private static class ListGlob extends MasterToSlaveFileCallable { private final String includes; private final String excludes; private final boolean defaultExcludes; + ListGlob(String includes, String excludes, boolean defaultExcludes) { this.includes = includes; this.excludes = excludes; this.defaultExcludes = defaultExcludes; } + private static final long serialVersionUID = 1L; + @Override public FilePath[] invoke(File f, VirtualChannel channel) throws IOException { - String[] files = glob(reading(f), includes, excludes, defaultExcludes); + String[] files = glob(f, includes, excludes, defaultExcludes); FilePath[] r = new FilePath[files.length]; - for( int i=0; i { + private static class Read extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; private final Pipe p; private String verificationRoot; @@ -2200,9 +2285,10 @@ private static class Read extends SecureFileCallable { this.verificationRoot = verificationRoot; this.noFollowLinks = noFollowLinks; } + @Override public Void invoke(File f, VirtualChannel channel) throws IOException, InterruptedException { - try (InputStream fis = newInputStreamDenyingSymlinkAsNeeded(reading(f), verificationRoot, noFollowLinks); OutputStream out = p.getOut()) { + try (InputStream fis = newInputStreamDenyingSymlinkAsNeeded(f, verificationRoot, noFollowLinks); OutputStream out = p.getOut()) { org.apache.commons.io.IOUtils.copy(fis, out); } catch (Exception x) { p.error(x); @@ -2216,7 +2302,7 @@ public Void invoke(File f, VirtualChannel channel) throws IOException, Interrupt * @since 1.586 */ public InputStream readFromOffset(final long offset) throws IOException, InterruptedException { - if(channel ==null) { + if (channel == null) { final RandomAccessFile raf = new RandomAccessFile(new File(remote), "r"); try { raf.seek(offset); @@ -2255,23 +2341,23 @@ public int read(byte[] b) throws IOException { actAsync(new OffsetPipeSecureFileCallable(p, offset)); return new java.util.zip.GZIPInputStream(p.getIn()); } - - private static class OffsetPipeSecureFileCallable extends SecureFileCallable { + + private static class OffsetPipeSecureFileCallable extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; - + private Pipe p; private long offset; - + private OffsetPipeSecureFileCallable(Pipe p, long offset) { this.p = p; this.offset = offset; } - + @Override public Void invoke(File f, VirtualChannel channel) throws IOException { try (OutputStream os = p.getOut(); OutputStream out = new java.util.zip.GZIPOutputStream(os, 8192); - RandomAccessFile raf = new RandomAccessFile(reading(f), "r")) { + RandomAccessFile raf = new RandomAccessFile(f, "r")) { raf.seek(offset); byte[] buf = new byte[8192]; int len; @@ -2288,12 +2374,14 @@ public Void invoke(File f, VirtualChannel channel) throws IOException { */ public String readToString() throws IOException, InterruptedException { return act(new ReadToString()); - } - private static class ReadToString extends SecureFileCallable { - private static final long serialVersionUID = 1L; + } + + private static class ReadToString extends MasterToSlaveFileCallable { + private static final long serialVersionUID = 1L; + @Override public String invoke(File f, VirtualChannel channel) throws IOException, InterruptedException { - return new String(Files.readAllBytes(fileToPath(reading(f)))); + return new String(Files.readAllBytes(fileToPath(f)), Charset.defaultCharset()); } } @@ -2310,21 +2398,23 @@ public String invoke(File f, VirtualChannel channel) throws IOException, Interru * file, it might not be fully written yet. */ public OutputStream write() throws IOException, InterruptedException { - if(channel==null) { + if (channel == null) { File f = new File(remote).getAbsoluteFile(); mkdirs(f.getParentFile()); - return Files.newOutputStream(fileToPath(writing(f))); // TODO #writing seems unnecessary on a local file + return Files.newOutputStream(fileToPath(f)); } return act(new WritePipe()); } - private static class WritePipe extends SecureFileCallable { + + private static class WritePipe extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public OutputStream invoke(File f, VirtualChannel channel) throws IOException, InterruptedException { f = f.getAbsoluteFile(); mkdirs(f.getParentFile()); - return new RemoteOutputStream(Files.newOutputStream(fileToPath(writing(f)))); + return new RemoteOutputStream(Files.newOutputStream(fileToPath(f))); } } @@ -2338,19 +2428,22 @@ public OutputStream invoke(File f, VirtualChannel channel) throws IOException, I public void write(final String content, final String encoding) throws IOException, InterruptedException { act(new Write(encoding, content)); } - private static class Write extends SecureFileCallable { + + private static class Write extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; private final String encoding; private final String content; + Write(String encoding, String content) { this.encoding = encoding; this.content = content; } + @Override public Void invoke(File f, VirtualChannel channel) throws IOException { mkdirs(f.getParentFile()); - try (OutputStream fos = Files.newOutputStream(fileToPath(writing(f))); - Writer w = encoding != null ? new OutputStreamWriter(fos, encoding) : new OutputStreamWriter(fos)) { + try (OutputStream fos = Files.newOutputStream(fileToPath(f)); + Writer w = encoding != null ? new OutputStreamWriter(fos, encoding) : new OutputStreamWriter(fos, Charset.defaultCharset())) { w.write(content); } return null; @@ -2364,11 +2457,13 @@ public Void invoke(File f, VirtualChannel channel) throws IOException { public String digest() throws IOException, InterruptedException { return act(new Digest()); } - private static class Digest extends SecureFileCallable { + + private static class Digest extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; + @Override public String invoke(File f, VirtualChannel channel) throws IOException { - return Util.getDigestOf(reading(f)); + return Util.getDigestOf(f); } } @@ -2377,20 +2472,24 @@ public String invoke(File f, VirtualChannel channel) throws IOException { * be on the some host */ public void renameTo(final FilePath target) throws IOException, InterruptedException { - if(this.channel != target.channel) { - throw new IOException("renameTo target must be on the same host"); - } + if (this.channel != target.channel) { + throw new IOException("renameTo target must be on the same host"); + } act(new RenameTo(target)); } - private static class RenameTo extends SecureFileCallable { + + private static class RenameTo extends MasterToSlaveFileCallable { private final FilePath target; + RenameTo(FilePath target) { this.target = target; } + private static final long serialVersionUID = 1L; + @Override public Void invoke(File f, VirtualChannel channel) throws IOException { - Files.move(fileToPath(deleting(reading(f))), fileToPath(writing(creating(new File(target.remote)))), LinkOption.NOFOLLOW_LINKS); + Files.move(fileToPath(f), fileToPath(new File(target.remote)), LinkOption.NOFOLLOW_LINKS); return null; } } @@ -2401,33 +2500,37 @@ public Void invoke(File f, VirtualChannel channel) throws IOException { * @since 1.308. */ public void moveAllChildrenTo(final FilePath target) throws IOException, InterruptedException { - if(this.channel != target.channel) { + if (this.channel != target.channel) { throw new IOException("pullUpTo target must be on the same host"); } act(new MoveAllChildrenTo(target)); } - private static class MoveAllChildrenTo extends SecureFileCallable { + + private static class MoveAllChildrenTo extends MasterToSlaveFileCallable { private final FilePath target; + MoveAllChildrenTo(FilePath target) { this.target = target; } + private static final long serialVersionUID = 1L; + @Override public Void invoke(File f, VirtualChannel channel) throws IOException { // JENKINS-16846: if f.getName() is the same as one of the files/directories in f, // then the rename op will fail - File tmp = new File(f.getAbsolutePath()+".__rename"); - if (!deleting(f).renameTo(creating(tmp))) - throw new IOException("Failed to rename "+f+" to "+tmp); + File tmp = new File(f.getAbsolutePath() + ".__rename"); + if (!f.renameTo(tmp)) + throw new IOException("Failed to rename " + f + " to " + tmp); File t = new File(target.getRemote()); - for(File child : reading(tmp).listFiles()) { + for (File child : tmp.listFiles()) { File target = new File(t, child.getName()); - if(!deleting(reading(child)).renameTo(writing(creating(target)))) - throw new IOException("Failed to rename "+child+" to "+target); + if (!child.renameTo(target)) + throw new IOException("Failed to rename " + child + " to " + target); } - Files.deleteIfExists(Util.fileToPath(deleting(tmp))); + Files.deleteIfExists(Util.fileToPath(tmp)); return null; } } @@ -2441,7 +2544,7 @@ public void copyTo(FilePath target) throws IOException, InterruptedException { copyTo(out); } } catch (IOException e) { - throw new IOException("Failed to copy "+this+" to "+target,e); + throw new IOException("Failed to copy " + this + " to " + target, e); } } @@ -2461,18 +2564,20 @@ public void copyToWithPermission(FilePath target) throws IOException, Interrupte target.chmod(mode()); target.setLastModifiedIfPossible(lastModified()); } - private static class CopyToWithPermission extends SecureFileCallable { + + private static class CopyToWithPermission extends MasterToSlaveFileCallable { private final FilePath target; + CopyToWithPermission(FilePath target) { this.target = target; } + @Override public Void invoke(File f, VirtualChannel channel) throws IOException { File targetFile = new File(target.remote); File targetDir = targetFile.getParentFile(); - filterNonNull().mkdirs(targetDir); Files.createDirectories(fileToPath(targetDir)); - Files.copy(fileToPath(reading(f)), fileToPath(writing(targetFile)), StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); + Files.copy(fileToPath(f), fileToPath(targetFile), StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); return null; } } @@ -2489,15 +2594,18 @@ public void copyTo(OutputStream os) throws IOException, InterruptedException { // this is needed because I/O operation is asynchronous syncIO(); } - private static class CopyTo extends SecureFileCallable { + + private static class CopyTo extends MasterToSlaveFileCallable { private static final long serialVersionUID = 4088559042349254141L; private final OutputStream out; + CopyTo(OutputStream out) { this.out = out; } + @Override public Void invoke(File f, VirtualChannel channel) throws IOException { - try (InputStream fis = Files.newInputStream(fileToPath(reading(f)))) { + try (InputStream fis = Files.newInputStream(fileToPath(f))) { org.apache.commons.io.IOUtils.copy(fis, out); return null; } finally { @@ -2513,12 +2621,12 @@ public Void invoke(File f, VirtualChannel channel) throws IOException { */ private void syncIO() throws InterruptedException { try { - if (channel!=null) + if (channel != null) channel.syncLocalIO(); } catch (AbstractMethodError e) { // legacy agent.jar. Handle this gracefully try { - LOGGER.log(Level.WARNING,"Looks like an old agent.jar. Please update "+ Which.jarFile(Channel.class)+" to the new version",e); + LOGGER.log(Level.WARNING, "Looks like an old agent.jar. Please update " + Which.jarFile(Channel.class) + " to the new version", e); } catch (IOException ignored) { // really ignore this time } @@ -2544,19 +2652,21 @@ interface RemoteCopier { * relative path name to the output file. Path separator must be '/'. */ void open(String fileName) throws IOException; + void write(byte[] buf, int len) throws IOException; + void close() throws IOException; } /** * Copies the contents of this directory recursively into the specified target directory. - * + * * @return * the number of files copied. - * @since 1.312 + * @since 1.312 */ public int copyRecursiveTo(FilePath target) throws IOException, InterruptedException { - return copyRecursiveTo("**/*",target); + return copyRecursiveTo("**/*", target); } /** @@ -2571,7 +2681,7 @@ public int copyRecursiveTo(FilePath target) throws IOException, InterruptedExcep * the number of files copied. */ public int copyRecursiveTo(String fileMask, FilePath target) throws IOException, InterruptedException { - return copyRecursiveTo(fileMask,null,target); + return copyRecursiveTo(fileMask, null, target); } /** @@ -2613,11 +2723,11 @@ public int copyRecursiveTo(final DirScanner scanner, final FilePath target, fina * @since 2.196 */ public int copyRecursiveTo(final DirScanner scanner, final FilePath target, final String description, @NonNull TarCompression compression) throws IOException, InterruptedException { - if(this.channel==target.channel) { + if (this.channel == target.channel) { // local to local copy. return act(new CopyRecursiveLocal(target, scanner)); } else - if(this.channel==null) { + if (this.channel == null) { // local -> remote copy final Pipe pipe = Pipe.createLocalToRemote(); @@ -2636,10 +2746,10 @@ public int copyRecursiveTo(final DirScanner scanner, final FilePath target, fina Future future = actAsync(new CopyRecursiveRemoteToLocal(pipe, scanner, compression)); try { - readFromTar(remote + '/' + description,new File(target.remote),compression.extract(pipe.getIn())); - } catch (IOException e) {// BuildException or IOException + readFromTar(remote + '/' + description, new File(target.remote), compression.extract(pipe.getIn())); + } catch (IOException e) { // BuildException or IOException try { - future.get(3,TimeUnit.SECONDS); + future.get(3, TimeUnit.SECONDS); throw e; // the remote side completed successfully, so the error must be local } catch (ExecutionException x) { // report both errors @@ -2667,14 +2777,17 @@ private IOException ioWithCause(ExecutionException e) { ; } - private static class CopyRecursiveLocal extends SecureFileCallable { + private static class CopyRecursiveLocal extends MasterToSlaveFileCallable { private final FilePath target; private final DirScanner scanner; + CopyRecursiveLocal(FilePath target, DirScanner scanner) { this.target = target; this.scanner = scanner; } + private static final long serialVersionUID = 1L; + @Override public Integer invoke(File base, VirtualChannel channel) throws IOException { if (!base.exists()) { @@ -2685,7 +2798,7 @@ public Integer invoke(File base, VirtualChannel channel) throws IOException { } final File dest = new File(target.remote); final AtomicInteger count = new AtomicInteger(); - scanner.scan(base, reading(new FileVisitor() { + scanner.scan(base, new FileVisitor() { private boolean exceptionEncountered; private boolean logMessageShown; @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "TODO needs triage") @@ -2694,13 +2807,13 @@ public void visit(File f, String relativePath) throws IOException { if (f.isFile()) { File target = new File(dest, relativePath); mkdirsE(target.getParentFile()); - Path targetPath = fileToPath(writing(target)); + Path targetPath = fileToPath(target); exceptionEncountered = exceptionEncountered || !tryCopyWithAttributes(f, targetPath); if (exceptionEncountered) { Files.copy(fileToPath(f), targetPath, StandardCopyOption.REPLACE_EXISTING); if (!logMessageShown) { - LOGGER.log(Level.INFO, - "JENKINS-52325: Jenkins failed to retain attributes when copying to {0}, so proceeding without attributes.", + LOGGER.log(Level.INFO, + "JENKINS-52325: Jenkins failed to retain attributes when copying to {0}, so proceeding without attributes.", dest.getAbsolutePath()); logMessageShown = true; } @@ -2708,37 +2821,40 @@ public void visit(File f, String relativePath) throws IOException { count.incrementAndGet(); } } + private boolean tryCopyWithAttributes(File f, Path targetPath) { - try { + try { Files.copy(fileToPath(f), targetPath, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { LOGGER.log(Level.FINE, "Unable to copy: {0}", e.getMessage()); return false; } - return true; + return true; } + @Override public boolean understandsSymlink() { return true; } + @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "TODO needs triage") @Override public void visitSymlink(File link, String target, String relativePath) throws IOException { try { mkdirsE(new File(dest, relativePath).getParentFile()); - writing(new File(dest, target)); Util.createSymlink(dest, target, relativePath, TaskListener.NULL); } catch (InterruptedException x) { throw new IOException(x); } count.incrementAndGet(); } - })); + }); return count.get(); } } - private static class ReadFromTar extends SecureFileCallable { + + private static class ReadFromTar extends MasterToSlaveFileCallable { private final Pipe pipe; private final String description; private final TarCompression compression; @@ -2750,7 +2866,9 @@ private static class ReadFromTar extends SecureFileCallable { this.description = description; this.compression = compression; } + private static final long serialVersionUID = 1L; + @Override public Void invoke(File f, VirtualChannel channel) throws IOException { try (InputStream in = pipe.getIn()) { @@ -2759,35 +2877,42 @@ public Void invoke(File f, VirtualChannel channel) throws IOException { } } } - private static class WriteToTar extends SecureFileCallable { + + private static class WriteToTar extends MasterToSlaveFileCallable { private final DirScanner scanner; private final Pipe pipe; private final TarCompression compression; + WriteToTar(DirScanner scanner, Pipe pipe, @NonNull TarCompression compression) { this.scanner = scanner; this.pipe = pipe; this.compression = compression; } + private static final long serialVersionUID = 1L; + @Override public Integer invoke(File f, VirtualChannel channel) throws IOException, InterruptedException { - return writeToTar(reading(f), scanner, compression.compress(pipe.getOut())); + return writeToTar(f, scanner, compression.compress(pipe.getOut())); } } - private static class CopyRecursiveRemoteToLocal extends SecureFileCallable { + + private static class CopyRecursiveRemoteToLocal extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; private final Pipe pipe; private final DirScanner scanner; private final TarCompression compression; + CopyRecursiveRemoteToLocal(Pipe pipe, DirScanner scanner, @NonNull TarCompression compression) { this.pipe = pipe; this.scanner = scanner; this.compression = compression; } + @Override public Integer invoke(File f, VirtualChannel channel) throws IOException { try (OutputStream out = pipe.getOut()) { - return writeToTar(reading(f), scanner, compression.compress(out)); + return writeToTar(f, scanner, compression.compress(out)); } } } @@ -2822,7 +2947,7 @@ public int tar(OutputStream out, DirScanner scanner) throws IOException, Interru private static Integer writeToTar(File baseDir, DirScanner scanner, OutputStream out) throws IOException { Archiver tw = ArchiverFactory.TAR.create(out); try { - scanner.scan(baseDir,reading(tw)); + scanner.scan(baseDir, tw); } finally { tw.close(); } @@ -2851,9 +2976,9 @@ private static void readFromTar(String name, File baseDir, InputStream in) throw if (parent != null) mkdirs(parent); if (te.isSymbolicLink()) { - new FilePath(symlinking(f)).symlinkTo(te.getLinkName(), TaskListener.NULL); + new FilePath(f).symlinkTo(te.getLinkName(), TaskListener.NULL); } else { - IOUtils.copy(t, writing(f)); + IOUtils.copy(t, f); Files.setLastModifiedTime(Util.fileToPath(f), FileTime.from(te.getModTime().toInstant())); int mode = te.getMode() & 0777; @@ -2876,18 +3001,19 @@ private static void readFromTar(String name, File baseDir, InputStream in) throw * @since 1.89 */ public Launcher createLauncher(TaskListener listener) throws IOException, InterruptedException { - if(channel==null) + if (channel == null) return new LocalLauncher(listener); else - return new RemoteLauncher(listener,channel,channel.call(new IsUnix())); + return new RemoteLauncher(listener, channel, channel.call(new IsUnix())); } - private static final class IsUnix extends MasterToSlaveCallable { + private static final class IsUnix extends MasterToSlaveCallable { @Override @NonNull public Boolean call() throws IOException { - return File.pathSeparatorChar==':'; + return File.pathSeparatorChar == ':'; } + private static final long serialVersionUID = 1L; } @@ -2915,7 +3041,7 @@ public String validateAntFileMask(final String fileMasks, final int bound) throw /** * Same as {@link #validateAntFileMask(String, int, boolean)} with the default number of operations. * @see #VALIDATE_ANT_FILE_MASK_BOUND - * @since TODO + * @since 2.325 */ public String validateAntFileMask(final String fileMasks, final boolean caseSensitive) throws IOException, InterruptedException { return validateAntFileMask(fileMasks, VALIDATE_ANT_FILE_MASK_BOUND, caseSensitive); @@ -2952,28 +3078,32 @@ public String validateAntFileMask(final String fileMasks, final boolean caseSens public @CheckForNull String validateAntFileMask(final String fileMasks, final int bound, final boolean caseSensitive) throws IOException, InterruptedException { return act(new ValidateAntFileMask(fileMasks, caseSensitive, bound)); } + private static class ValidateAntFileMask extends MasterToSlaveFileCallable { private final String fileMasks; private final boolean caseSensitive; private final int bound; + ValidateAntFileMask(String fileMasks, boolean caseSensitive, int bound) { this.fileMasks = fileMasks; this.caseSensitive = caseSensitive; this.bound = bound; } + private static final long serialVersionUID = 1; + @Override public String invoke(File dir, VirtualChannel channel) throws IOException, InterruptedException { - if(fileMasks.startsWith("~")) + if (fileMasks.startsWith("~")) return Messages.FilePath_TildaDoesntWork(); - StringTokenizer tokens = new StringTokenizer(fileMasks,","); + StringTokenizer tokens = new StringTokenizer(fileMasks, ","); - while(tokens.hasMoreTokens()) { + while (tokens.hasMoreTokens()) { final String fileMask = tokens.nextToken().trim(); - if(hasMatch(dir,fileMask,caseSensitive)) + if (hasMatch(dir, fileMask, caseSensitive)) continue; // no error on this portion - + // JENKINS-5253 - if we can get some match in case insensitive mode // and user requested case sensitive match, notify the user if (caseSensitive && hasMatch(dir, fileMask, false)) { @@ -2982,11 +3112,11 @@ public String invoke(File dir, VirtualChannel channel) throws IOException, Inter // in 1.172 we introduced an incompatible change to stop using ' ' as the separator // so see if we can match by using ' ' as the separator - if(fileMask.contains(" ")) { + if (fileMask.contains(" ")) { boolean matched = true; for (String token : Util.tokenize(fileMask)) - matched &= hasMatch(dir,token,caseSensitive); - if(matched) + matched &= hasMatch(dir, token, caseSensitive); + if (matched) return Messages.FilePath_validateAntFileMask_whitespaceSeparator(); } @@ -2994,28 +3124,28 @@ public String invoke(File dir, VirtualChannel channel) throws IOException, Inter // to this: (1) the user gave us aa/bb/cc/dd where cc/dd was correct // and (2) the user gave us cc/dd where aa/bb/cc/dd was correct. - {// check the (1) above first - String f=fileMask; - while(true) { + { // check the (1) above first + String f = fileMask; + while (true) { int idx = findSeparator(f); - if(idx==-1) break; - f=f.substring(idx+1); + if (idx == -1) break; + f = f.substring(idx + 1); - if(hasMatch(dir,f,caseSensitive)) - return Messages.FilePath_validateAntFileMask_doesntMatchAndSuggest(fileMask,f); + if (hasMatch(dir, f, caseSensitive)) + return Messages.FilePath_validateAntFileMask_doesntMatchAndSuggest(fileMask, f); } } - {// check the (2) above next as this is more expensive. + { // check the (2) above next as this is more expensive. // Try prepending "**/" to see if that results in a match - FileSet fs = Util.createFileSet(reading(dir),"**/"+fileMask); + FileSet fs = Util.createFileSet(dir, "**/" + fileMask); fs.setCaseSensitive(caseSensitive); DirectoryScanner ds = fs.getDirectoryScanner(new Project()); - if(ds.getIncludedFilesCount()!=0) { + if (ds.getIncludedFilesCount() != 0) { // try shorter name first so that the suggestion results in least amount of changes String[] names = ds.getIncludedFiles(); - Arrays.sort(names,SHORTER_STRING_FIRST); - for( String f : names) { + Arrays.sort(names, SHORTER_STRING_FIRST); + for (String f : names) { // now we want to decompose f to the leading portion that matched "**" // and the trailing portion that matched the file mask, so that // we can suggest the user error. @@ -3023,43 +3153,43 @@ public String invoke(File dir, VirtualChannel channel) throws IOException, Inter // this is not a very efficient/clever way to do it, but it's relatively simple StringBuilder prefix = new StringBuilder(); - while(true) { + while (true) { int idx = findSeparator(f); - if(idx==-1) break; + if (idx == -1) break; prefix.append(f, 0, idx).append('/'); - f=f.substring(idx+1); - if(hasMatch(dir,prefix+fileMask,caseSensitive)) - return Messages.FilePath_validateAntFileMask_doesntMatchAndSuggest(fileMask, prefix+fileMask); + f = f.substring(idx + 1); + if (hasMatch(dir, prefix + fileMask, caseSensitive)) + return Messages.FilePath_validateAntFileMask_doesntMatchAndSuggest(fileMask, prefix + fileMask); } } } } - {// finally, see if we can identify any sub portion that's valid. Otherwise bail out + { // finally, see if we can identify any sub portion that's valid. Otherwise bail out String previous = null; String pattern = fileMask; - while(true) { - if(hasMatch(dir,pattern,caseSensitive)) { + while (true) { + if (hasMatch(dir, pattern, caseSensitive)) { // found a match - if(previous==null) - return Messages.FilePath_validateAntFileMask_portionMatchAndSuggest(fileMask,pattern); + if (previous == null) + return Messages.FilePath_validateAntFileMask_portionMatchAndSuggest(fileMask, pattern); else - return Messages.FilePath_validateAntFileMask_portionMatchButPreviousNotMatchAndSuggest(fileMask,pattern,previous); + return Messages.FilePath_validateAntFileMask_portionMatchButPreviousNotMatchAndSuggest(fileMask, pattern, previous); } int idx = findSeparator(pattern); - if(idx<0) {// no more path component left to go back - if(pattern.equals(fileMask)) + if (idx < 0) { // no more path component left to go back + if (pattern.equals(fileMask)) return Messages.FilePath_validateAntFileMask_doesntMatchAnything(fileMask); else - return Messages.FilePath_validateAntFileMask_doesntMatchAnythingAndSuggest(fileMask,pattern); + return Messages.FilePath_validateAntFileMask_doesntMatchAnythingAndSuggest(fileMask, pattern); } // cut off the trailing component and try again previous = pattern; - pattern = pattern.substring(0,idx); + pattern = pattern.substring(0, idx); } } } @@ -3069,6 +3199,7 @@ public String invoke(File dir, VirtualChannel channel) throws IOException, Inter private boolean hasMatch(File dir, String pattern, boolean bCaseSensitive) throws InterruptedException { class Cancel extends RuntimeException {} + DirectoryScanner ds = bound == Integer.MAX_VALUE ? new DirectoryScanner() : new DirectoryScanner() { int ticks; long start = System.currentTimeMillis(); @@ -3083,19 +3214,19 @@ class Cancel extends RuntimeException {} return super.isCaseSensitive(); } }; - ds.setBasedir(reading(dir)); + ds.setBasedir(dir); ds.setIncludes(new String[] {pattern}); ds.setCaseSensitive(bCaseSensitive); try { ds.scan(); } catch (Cancel c) { - if (ds.getIncludedFilesCount()!=0 || ds.getIncludedDirsCount()!=0) { + if (ds.getIncludedFilesCount() != 0 || ds.getIncludedDirsCount() != 0) { return true; } else { - throw (InterruptedException)new InterruptedException("no matches found within " + bound).initCause(c); + throw (InterruptedException) new InterruptedException("no matches found within " + bound).initCause(c); } } - return ds.getIncludedFilesCount()!=0 || ds.getIncludedDirsCount()!=0; + return ds.getIncludedFilesCount() != 0 || ds.getIncludedDirsCount() != 0; } /** @@ -3104,9 +3235,9 @@ class Cancel extends RuntimeException {} private int findSeparator(String pattern) { int idx1 = pattern.indexOf('\\'); int idx2 = pattern.indexOf('/'); - if(idx1==-1) return idx2; - if(idx2==-1) return idx1; - return Math.min(idx1,idx2); + if (idx1 == -1) return idx2; + if (idx2 == -1) return idx1; + return Math.min(idx1, idx2); } } @@ -3141,24 +3272,24 @@ private UrlFactory getUrlFactory() { public static FormValidation validateFileMask(@CheckForNull FilePath path, String value) throws IOException { return FilePath.validateFileMask(path, value, true); } - + /** * Shortcut for {@link #validateFileMask(String,boolean,boolean)} with {@code errorIfNotExist} true, as the left-hand side can be null. */ public static FormValidation validateFileMask(@CheckForNull FilePath path, String value, boolean caseSensitive) throws IOException { - if(path==null) return FormValidation.ok(); + if (path == null) return FormValidation.ok(); return path.validateFileMask(value, true, caseSensitive); } /** - * Short for {@code validateFileMask(value, true, true)} + * Short for {@code validateFileMask(value, true, true)} */ public FormValidation validateFileMask(String value) throws IOException { return validateFileMask(value, true, true); } - + /** - * Short for {@code validateFileMask(value, errorIfNotExist, true)} + * Short for {@code validateFileMask(value, errorIfNotExist, true)} */ public FormValidation validateFileMask(String value, boolean errorIfNotExist) throws IOException { return validateFileMask(value, errorIfNotExist, true); @@ -3179,15 +3310,15 @@ public FormValidation validateFileMask(String value, boolean errorIfNotExist, bo checkPermissionForValidate(); value = fixEmpty(value); - if(value==null) + if (value == null) return FormValidation.ok(); try { - if(!exists()) // no workspace. can't check + if (!exists()) // no workspace. can't check return FormValidation.ok(); String msg = validateAntFileMask(value, VALIDATE_ANT_FILE_MASK_BOUND, caseSensitive); - if(errorIfNotExist) return FormValidation.error(msg); + if (errorIfNotExist) return FormValidation.error(msg); else return FormValidation.warning(msg); } catch (InterruptedException e) { return FormValidation.ok(Messages.FilePath_did_not_manage_to_validate_may_be_too_sl(value)); @@ -3217,33 +3348,33 @@ public FormValidation validateRelativePath(String value, boolean errorIfNotExist value = fixEmpty(value); // none entered yet, or something is seriously wrong - if(value==null) return FormValidation.ok(); + if (value == null) return FormValidation.ok(); // a common mistake is to use wildcard - if(value.contains("*")) return FormValidation.error(Messages.FilePath_validateRelativePath_wildcardNotAllowed()); + if (value.contains("*")) return FormValidation.error(Messages.FilePath_validateRelativePath_wildcardNotAllowed()); try { - if(!exists()) // no base directory. can't check + if (!exists()) // no base directory. can't check return FormValidation.ok(); FilePath path = child(value); - if(path.exists()) { + if (path.exists()) { if (expectingFile) { - if(!path.isDirectory()) + if (!path.isDirectory()) return FormValidation.ok(); else return FormValidation.error(Messages.FilePath_validateRelativePath_notFile(value)); } else { - if(path.isDirectory()) + if (path.isDirectory()) return FormValidation.ok(); else return FormValidation.error(Messages.FilePath_validateRelativePath_notDirectory(value)); } } - String msg = expectingFile ? Messages.FilePath_validateRelativePath_noSuchFile(value) : + String msg = expectingFile ? Messages.FilePath_validateRelativePath_noSuchFile(value) : Messages.FilePath_validateRelativePath_noSuchDirectory(value); - if(errorIfNotExist) return FormValidation.error(msg); + if (errorIfNotExist) return FormValidation.error(msg); else return FormValidation.warning(msg); } catch (InterruptedException e) { return FormValidation.ok(); @@ -3262,11 +3393,11 @@ private static void checkPermissionForValidate() { * A convenience method over {@link #validateRelativePath(String, boolean, boolean)}. */ public FormValidation validateRelativeDirectory(String value, boolean errorIfNotExist) throws IOException { - return validateRelativePath(value,errorIfNotExist,false); + return validateRelativePath(value, errorIfNotExist, false); } public FormValidation validateRelativeDirectory(String value) throws IOException { - return validateRelativeDirectory(value,true); + return validateRelativeDirectory(value, true); } @Deprecated @Override @@ -3276,15 +3407,15 @@ public String toString() { } public VirtualChannel getChannel() { - if(channel!=null) return channel; + if (channel != null) return channel; else return localChannel; } /** - * Returns true if this {@link FilePath} represents a remote file. + * Returns true if this {@link FilePath} represents a remote file. */ public boolean isRemote() { - return channel!=null; + return channel != null; } private void writeObject(ObjectOutputStream oos) throws IOException { @@ -3294,7 +3425,7 @@ private void writeObject(ObjectOutputStream oos) throws IOException { } oos.defaultWriteObject(); - oos.writeBoolean(channel==null); + oos.writeBoolean(channel == null); } private Channel _getChannelForSerialization() { @@ -3310,7 +3441,7 @@ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFound Channel channel = _getChannelForSerialization(); ois.defaultReadObject(); - if(ois.readBoolean()) { + if (ois.readBoolean()) { this.channel = channel; } else { this.channel = null; @@ -3323,15 +3454,16 @@ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFound private static final long serialVersionUID = 1L; - @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "TODO needs triage") - public static int SIDE_BUFFER_SIZE = 1024; + @Restricted(NoExternalUse.class) + @RestrictedSince("TODO") + public static final int SIDE_BUFFER_SIZE = 1024; private static final Logger LOGGER = Logger.getLogger(FilePath.class.getName()); /** * Adapts {@link FileCallable} to {@link Callable}. */ - private static class FileCallableWrapper implements DelegatingCallable { + private static class FileCallableWrapper implements DelegatingCallable { private final FileCallable callable; private transient ClassLoader classLoader; private final FilePath filePath; @@ -3385,6 +3517,7 @@ private static class TunneledInterruptedException extends IOException { private TunneledInterruptedException(InterruptedException cause) { super(cause); } + private static final long serialVersionUID = 1L; } @@ -3397,6 +3530,7 @@ private TunneledInterruptedException(InterruptedException cause) { public static FilePath getHomeDirectory(VirtualChannel ch) throws InterruptedException, IOException { return ch.call(new GetHomeDirectory()); } + private static class GetHomeDirectory extends MasterToSlaveCallable { @Override public FilePath call() throws IOException { @@ -3412,18 +3546,18 @@ public static final class ExplicitlySpecifiedDirScanner extends DirScanner { private static final long serialVersionUID = 1; - private final Map files; + private final Map files; /** * Create a “scanner” (it actually does no scanning). * @param files a map from logical relative paths as per {@link FileVisitor#visit}, to actual relative paths within the scanned directory */ - public ExplicitlySpecifiedDirScanner(Map files) { + public ExplicitlySpecifiedDirScanner(Map files) { this.files = files; } @Override public void scan(File dir, FileVisitor visitor) throws IOException { - for (Map.Entry entry : files.entrySet()) { + for (Map.Entry entry : files.entrySet()) { String archivedPath = entry.getKey(); assert archivedPath.indexOf('\\') == -1; String workspacePath = entry.getValue(); @@ -3439,45 +3573,13 @@ public ExplicitlySpecifiedDirScanner(Map files) { new NamingThreadFactory(new DaemonThreadFactory(), "FilePath.localPool")) )); - + /** * Channel to the current instance. */ @NonNull public static final LocalChannel localChannel = new LocalChannel(threadPoolForRemoting); - private static @NonNull SoloFilePathFilter filterNonNull() { - final SoloFilePathFilter filter = SoloFilePathFilter.wrap(FilePathFilter.current()); - return filter != null ? filter : UNRESTRICTED; - } - - /** - * Wraps {@link FileVisitor} to notify read access to {@link FilePathFilter}. - */ - private static FileVisitor reading(final FileVisitor v) { - final FilePathFilter filter = SoloFilePathFilter.wrap(FilePathFilter.current()); - if (filter==null) return v; - - return new FileVisitor() { - @Override - public void visit(File f, String relativePath) throws IOException { - filter.read(f); - v.visit(f,relativePath); - } - - @Override - public void visitSymlink(File link, String target, String relativePath) throws IOException { - filter.read(link); - v.visitSymlink(link, target, relativePath); - } - - @Override - public boolean understandsSymlink() { - return v.understandsSymlink(); - } - }; - } - /** * Wraps {@link FileVisitor} to ignore symlinks. */ @@ -3501,76 +3603,8 @@ public boolean understandsSymlink() { return v; } - /** - * Pass through 'f' after ensuring that we can read that file. - */ - private static File reading(File f) { - filterNonNull().read(f); - return f; - } - - /** - * Pass through 'f' after ensuring that we can access the file attributes. - */ - private static File stating(File f) { - filterNonNull().stat(f); - return f; - } - - /** - * Pass through 'f' after ensuring that we can create that file/dir. - */ - private static File creating(File f) { - filterNonNull().create(f); - return f; - } - - /** - * Pass through 'f' after ensuring that we can write to that file. - */ - private static File writing(File f) { - FilePathFilter filter = filterNonNull(); - if (!f.exists()) - filter.create(f); - filter.write(f); - return f; - } - - /** - * Pass through 'f' after ensuring that we can create that symlink. - */ - private static File symlinking(File f) { - FilePathFilter filter = filterNonNull(); - if (!f.exists()) - filter.create(f); - filter.symlink(f); - return f; - } - - /** - * Pass through 'f' after ensuring that we can delete that file. - */ - private static File deleting(File f) { - filterNonNull().delete(f); - return f; - } - - /** - * Pass through 'f' after ensuring that we can mkdirs that directory. - */ - private static File mkdirsing(File f) { - filterNonNull().mkdirs(f); - return f; - } - private static boolean mkdirs(File dir) throws IOException { if (dir.exists()) return false; - - File reference = dir; - while (reference != null && !reference.exists()) { - filterNonNull().mkdirs(reference); - reference = reference.getParentFile(); - } Files.createDirectories(fileToPath(dir)); return true; } @@ -3579,11 +3613,6 @@ private static File mkdirsE(File dir) throws IOException { if (dir.exists()) { return dir; } - File reference = dir; - while (reference != null && !reference.exists()) { - filterNonNull().mkdirs(reference); - reference = reference.getParentFile(); - } return IOUtils.mkdirs(dir); } @@ -3597,11 +3626,11 @@ public boolean isDescendant(@NonNull String potentialChildRelativePath) throws I return act(new IsDescendant(potentialChildRelativePath)); } - private static class IsDescendant extends SecureFileCallable { + private static class IsDescendant extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; private String potentialChildRelativePath; - private IsDescendant(@NonNull String potentialChildRelativePath){ + private IsDescendant(@NonNull String potentialChildRelativePath) { this.potentialChildRelativePath = potentialChildRelativePath; } @@ -3610,8 +3639,8 @@ public Boolean invoke(@NonNull File parentFile, @NonNull VirtualChannel channel) if (new File(potentialChildRelativePath).isAbsolute()) { throw new IllegalArgumentException("Only a relative path is supported, the given path is absolute: " + potentialChildRelativePath); } - - Path parentAbsolutePath = Util.fileToPath(stating(parentFile).getAbsoluteFile()); + + Path parentAbsolutePath = Util.fileToPath(parentFile.getAbsoluteFile()); Path parentRealPath; try { if (Functions.isWindows()) { @@ -3650,7 +3679,7 @@ public Boolean invoke(@NonNull File parentFile, @NonNull VirtualChannel channel) } Path currentFileAbsolutePath = currentFilePath.toAbsolutePath(); - try{ + try { Path child = currentFileAbsolutePath.toRealPath(); if (!child.startsWith(parentRealPath)) { LOGGER.log(Level.FINE, "Child [{0}] does not start with parent [{1}] => not descendant", new Object[]{ child, parentRealPath }); @@ -3658,13 +3687,13 @@ public Boolean invoke(@NonNull File parentFile, @NonNull VirtualChannel channel) } } catch (NoSuchFileException e) { // nonexistent file / Windows Server 2016 + MSFT docker - // in case this folder / file will be copied somewhere else, + // in case this folder / file will be copied somewhere else, // it becomes the responsibility of that system to check the isDescendant with the existing links // we are not taking the parentRealPath to avoid possible problem Path child = currentFileAbsolutePath.normalize(); Path parent = parentAbsolutePath.normalize(); return child.startsWith(parent); - } catch(FileSystemException e) { + } catch (FileSystemException e) { LOGGER.log(Level.WARNING, String.format("Problem during call to the method toRealPath on %s", currentFileAbsolutePath), e); return false; } @@ -3673,14 +3702,14 @@ public Boolean invoke(@NonNull File parentFile, @NonNull VirtualChannel channel) return true; } - private @CheckForNull Path getDirectChild(Path parentPath, String childPath){ + private @CheckForNull Path getDirectChild(Path parentPath, String childPath) { Path current = parentPath.resolve(childPath); while (current != null && !parentPath.equals(current.getParent())) { current = current.getParent(); } return current; } - + private @NonNull Path windowsToRealPath(@NonNull Path path) throws IOException { try { return path.toRealPath(); @@ -3716,8 +3745,6 @@ private static Path getRealPath(Path path) throws IOException { return path.toRealPath(LinkOption.NOFOLLOW_LINKS); } - private static final SoloFilePathFilter UNRESTRICTED = SoloFilePathFilter.wrap(FilePathFilter.UNRESTRICTED); - private static class SymlinkDiscardingFileFilter implements FileFilter, Serializable { private final String verificationRoot; @@ -3732,7 +3759,7 @@ private static class SymlinkDiscardingFileFilter implements FileFilter, Serializ public boolean accept(File file) { return !isSymlink(file, verificationRoot, noFollowLinks); } + private static final long serialVersionUID = 1L; } - } diff --git a/core/src/main/java/hudson/FileSystemProvisioner.java b/core/src/main/java/hudson/FileSystemProvisioner.java index e2dbb4480ff85..d93f2c8e8b76e 100644 --- a/core/src/main/java/hudson/FileSystemProvisioner.java +++ b/core/src/main/java/hudson/FileSystemProvisioner.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import hudson.model.AbstractBuild; @@ -36,11 +37,11 @@ */ @Deprecated public abstract class FileSystemProvisioner implements Describable { - public abstract void prepareWorkspace(AbstractBuild build, FilePath ws, TaskListener listener) throws IOException, InterruptedException; + public abstract void prepareWorkspace(AbstractBuild build, FilePath ws, TaskListener listener) throws IOException, InterruptedException; public abstract void discardWorkspace(AbstractProject project, FilePath ws) throws IOException, InterruptedException; - public abstract WorkspaceSnapshot snapshot(AbstractBuild build, FilePath ws, String glob, TaskListener listener) throws IOException, InterruptedException; + public abstract WorkspaceSnapshot snapshot(AbstractBuild build, FilePath ws, String glob, TaskListener listener) throws IOException, InterruptedException; @Override public Descriptor getDescriptor() { diff --git a/core/src/main/java/hudson/Functions.java b/core/src/main/java/hudson/Functions.java index 2d54d3358f923..d0f0b5c84f597 100644 --- a/core/src/main/java/hudson/Functions.java +++ b/core/src/main/java/hudson/Functions.java @@ -1,20 +1,20 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, * Yahoo! Inc., Stephen Connolly, Tom Huybrechts, Alan Harder, Manufacture * Francaise des Pneumatiques Michelin, Romain Seguy - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,6 +23,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -160,6 +161,7 @@ import org.apache.commons.jexl.parser.ASTSizeFunction; import org.apache.commons.jexl.util.Introspector; import org.apache.commons.lang.StringUtils; +import org.jenkins.ui.icon.Icon; import org.jenkins.ui.icon.IconSet; import org.jvnet.tiger_types.Types; import org.kohsuke.accmod.Restricted; @@ -211,7 +213,7 @@ public static boolean isModelWithContextMenu(Object o) { public static boolean isModelWithChildren(Object o) { return o instanceof ModelObjectWithChildren; } - + @Deprecated public static boolean isMatrixProject(Object o) { return o != null && o.getClass().getName().equals("hudson.matrix.MatrixProject"); @@ -293,8 +295,8 @@ public static void initPageVariables(JellyContext context) { see https://wiki.jenkins-ci.org/display/JENKINS/Hyperlinks+in+HTML */ - context.setVariable("resURL",rootURL+getResourcePath()); - context.setVariable("imagesURL",rootURL+getResourcePath()+"/images"); + context.setVariable("resURL", rootURL + getResourcePath()); + context.setVariable("imagesURL", rootURL + getResourcePath() + "/images"); context.setVariable("divBasedFormLayout", true); context.setVariable("userAgent", currentRequest.getHeader("User-Agent")); IconSet.initPageVariables(context); @@ -312,12 +314,12 @@ public static void initPageVariables(JellyContext context) { * if c' is not parameterized. */ public static Class getTypeParameter(Class c, Class base, int n) { - Type parameterization = Types.getBaseClass(c,base); + Type parameterization = Types.getBaseClass(c, base); if (parameterization instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) parameterization; - return Types.erasure(Types.getTypeArgument(pt,n)); + return Types.erasure(Types.getTypeArgument(pt, n)); } else { - throw new AssertionError(c+" doesn't properly parameterize "+base); + throw new AssertionError(c + " doesn't properly parameterize " + base); } } @@ -330,9 +332,9 @@ public JDK.DescriptorImpl getJDKDescriptor() { * like "-5", "+/-0", "+3". */ public static String getDiffString(int i) { - if(i==0) return "±0"; + if (i == 0) return "±0"; String s = Integer.toString(i); - if(i>0) return "+"+s; + if (i > 0) return "+" + s; else return s; } @@ -340,9 +342,9 @@ public static String getDiffString(int i) { * {@link #getDiffString(int)} that doesn't show anything for +/-0 */ public static String getDiffString2(int i) { - if(i==0) return ""; + if (i == 0) return ""; String s = Integer.toString(i); - if(i>0) return "+"+s; + if (i > 0) return "+" + s; else return s; } @@ -351,10 +353,10 @@ public static String getDiffString2(int i) { * if there's something to print */ public static String getDiffString2(String prefix, int i, String suffix) { - if(i==0) return ""; + if (i == 0) return ""; String s = Integer.toString(i); - if(i>0) return prefix+"+"+s+suffix; - else return prefix+s+suffix; + if (i > 0) return prefix + "+" + s + suffix; + else return prefix + s + suffix; } /** @@ -363,7 +365,7 @@ public static String getDiffString2(String prefix, int i, String suffix) { public static String addSuffix(int n, String singular, String plural) { StringBuilder buf = new StringBuilder(); buf.append(n).append(' '); - if(n==1) + if (n == 1) buf.append(singular); else buf.append(plural); @@ -374,16 +376,16 @@ public static RunUrl decompose(StaplerRequest req) { List ancestors = req.getAncestors(); // find the first and last Run instances - Ancestor f=null,l=null; + Ancestor f = null, l = null; for (Ancestor anc : ancestors) { - if(anc.getObject() instanceof Run) { - if(f==null) f=anc; - l=anc; + if (anc.getObject() instanceof Run) { + if (f == null) f = anc; + l = anc; } } - if(l==null) return null; // there was no Run object + if (l == null) return null; // there was no Run object - String head = f.getPrev().getUrl()+'/'; + String head = f.getPrev().getUrl() + '/'; String base = l.getUrl(); String reqUri = req.getOriginalRequestURI(); @@ -400,7 +402,7 @@ public static RunUrl decompose(StaplerRequest req) { // Remove that many from request URL, ignoring extra slashes String rest = reqUri.replaceFirst("(?:/+[^/]*){" + slashCount + "}", ""); - return new RunUrl( (Run) f.getObject(), head, base, rest); + return new RunUrl((Run) f.getObject(), head, base, rest); } /** @@ -408,8 +410,8 @@ public static RunUrl decompose(StaplerRequest req) { * @since 1.213 */ public static Area getScreenResolution() { - Cookie res = Functions.getCookie(Stapler.getCurrentRequest(),"screenResolution"); - if(res!=null) + Cookie res = Functions.getCookie(Stapler.getCurrentRequest(), "screenResolution"); + if (res != null) return Area.parse(res.getValue()); return null; } @@ -474,10 +476,10 @@ public String getPreviousBuildUrl() { } private String getUrl(Run n) { - if(n ==null) + if (n == null) return null; else { - return head+n.getNumber()+rest; + return head + n.getNumber() + rest; } } } @@ -510,7 +512,7 @@ public static Map getSystemProperties() { /** * Gets the system property indicated by the specified key. - * + * * Delegates to {@link SystemProperties#getString(String)}. */ @Restricted(DoNotUse.class) @@ -533,14 +535,14 @@ public static Map getEnvVars() { } public static boolean isWindows() { - return File.pathSeparatorChar==';'; + return File.pathSeparatorChar == ';'; } - + public static boolean isGlibcSupported() { try { GNUCLibrary.LIBC.getpid(); return true; - } catch(Throwable t) { + } catch (Throwable t) { return false; } } @@ -568,10 +570,11 @@ public static String[] printLogRecordHtml(LogRecord r, LogRecord prior) { * @return date, source, level, message+thrown * @see SimpleFormatter#format(LogRecord) */ + private static String[] logRecordPreformat(LogRecord r) { String source; if (r.getSourceClassName() == null) { - source = r.getLoggerName(); + source = r.getLoggerName() == null ? "" : r.getLoggerName(); } else { if (r.getSourceMethodName() == null) { source = r.getSourceClassName(); @@ -599,11 +602,11 @@ public static Iterable reverse(Collection collection) { return list; } - public static Cookie getCookie(HttpServletRequest req,String name) { + public static Cookie getCookie(HttpServletRequest req, String name) { Cookie[] cookies = req.getCookies(); - if(cookies!=null) { + if (cookies != null) { for (Cookie cookie : cookies) { - if(cookie.getName().equals(name)) { + if (cookie.getName().equals(name)) { return cookie; } } @@ -611,13 +614,14 @@ public static Cookie getCookie(HttpServletRequest req,String name) { return null; } - public static String getCookie(HttpServletRequest req,String name, String defaultValue) { + public static String getCookie(HttpServletRequest req, String name, String defaultValue) { Cookie c = getCookie(req, name); - if(c==null || c.getValue()==null) return defaultValue; + if (c == null || c.getValue() == null) return defaultValue; return c.getValue(); } private static final Pattern ICON_SIZE = Pattern.compile("\\d+x\\d+"); + @Restricted(NoExternalUse.class) public static String validateIconSize(String iconSize) throws SecurityException { if (!ICON_SIZE.matcher(iconSize).matches()) { @@ -642,28 +646,28 @@ public static String getYuiSuffix() { /** * Creates a sub map by using the given range (both ends inclusive). */ - public static SortedMap filter(SortedMap map, String from, String to) { - if(from==null && to==null) return map; - if(to==null) - return map.headMap(Integer.parseInt(from)-1); - if(from==null) + public static SortedMap filter(SortedMap map, String from, String to) { + if (from == null && to == null) return map; + if (to == null) + return map.headMap(Integer.parseInt(from) - 1); + if (from == null) return map.tailMap(Integer.parseInt(to)); - return map.subMap(Integer.parseInt(to),Integer.parseInt(from)-1); + return map.subMap(Integer.parseInt(to), Integer.parseInt(from) - 1); } /** * Creates a sub map by using the given range (upper end inclusive). */ @Restricted(NoExternalUse.class) - public static SortedMap filterExcludingFrom(SortedMap map, String from, String to) { - if(from==null && to==null) return map; - if(to==null) + public static SortedMap filterExcludingFrom(SortedMap map, String from, String to) { + if (from == null && to == null) return map; + if (to == null) return map.headMap(Integer.parseInt(from)); - if(from==null) + if (from == null) return map.tailMap(Integer.parseInt(to)); - return map.subMap(Integer.parseInt(to),Integer.parseInt(from)); + return map.subMap(Integer.parseInt(to), Integer.parseInt(from)); } private static final SimpleFormatter formatter = new SimpleFormatter(); @@ -684,7 +688,7 @@ public static boolean isAutoRefresh(HttpServletRequest request) { } public static boolean isCollapsed(String paneId) { - return PaneStatusProperties.forCurrentUser().isCollapsed(paneId); + return PaneStatusProperties.forCurrentUser().isCollapsed(paneId); } @Restricted(NoExternalUse.class) @@ -713,11 +717,11 @@ public static String getUserTimeZonePostfix() { * This is used to determine the "current" URL assigned to the given object, * so that one can compute relative URLs from it. */ - public static String getNearestAncestorUrl(StaplerRequest req,Object it) { + public static String getNearestAncestorUrl(StaplerRequest req, Object it) { List list = req.getAncestors(); - for( int i=list.size()-1; i>=0; i-- ) { + for (int i = list.size() - 1; i >= 0; i--) { Ancestor anc = (Ancestor) list.get(i); - if(anc.getObject()==it) + if (anc.getObject() == it) return anc.getUrl(); } return null; @@ -728,17 +732,17 @@ public static String getNearestAncestorUrl(StaplerRequest req,Object it) { */ public static String getSearchURL() { List list = Stapler.getCurrentRequest().getAncestors(); - for( int i=list.size()-1; i>=0; i-- ) { + for (int i = list.size() - 1; i >= 0; i--) { Ancestor anc = (Ancestor) list.get(i); - if(anc.getObject() instanceof SearchableModelObject) - return anc.getUrl()+"/search/"; + if (anc.getObject() instanceof SearchableModelObject) + return anc.getUrl() + "/search/"; } return null; } public static String appendSpaceIfNotNull(String n) { - if(n==null) return null; - else return n+' '; + if (n == null) return null; + else return n + ' '; } /** @@ -759,8 +763,8 @@ public static String getWin32ErrorMessage(IOException e) { } public static boolean isMultiline(String s) { - if(s==null) return false; - return s.indexOf('\r')>=0 || s.indexOf('\n')>=0; + if (s == null) return false; + return s.indexOf('\r') >= 0 || s.indexOf('\n') >= 0; } public static String encode(String s) { @@ -794,26 +798,26 @@ public static String xmlEscape(String s) { } public static String xmlUnescape(String s) { - return s.replace("<","<").replace(">",">").replace("&","&"); + return s.replace("<", "<").replace(">", ">").replace("&", "&"); } public static String htmlAttributeEscape(String text) { - StringBuilder buf = new StringBuilder(text.length()+64); - for( int i=0; i') + if (ch == '>') buf.append(">"); else - if(ch=='&') + if (ch == '&') buf.append("&"); else - if(ch=='"') + if (ch == '"') buf.append("""); else - if(ch=='\'') + if (ch == '\'') buf.append("'"); else buf.append(ch); @@ -822,7 +826,7 @@ public static String htmlAttributeEscape(String text) { } public static void checkPermission(Permission permission) throws IOException, ServletException { - checkPermission(Jenkins.get(),permission); + checkPermission(Jenkins.get(), permission); } public static void checkPermission(AccessControlled object, Permission permission) throws IOException, ServletException { @@ -839,19 +843,19 @@ public static void checkPermission(AccessControlled object, Permission permissio public static void checkPermission(Object object, Permission permission) throws IOException, ServletException { if (permission == null) return; - + if (object instanceof AccessControlled) - checkPermission((AccessControlled) object,permission); + checkPermission((AccessControlled) object, permission); else { List ancs = Stapler.getCurrentRequest().getAncestors(); - for(Ancestor anc : Iterators.reverse(ancs)) { + for (Ancestor anc : Iterators.reverse(ancs)) { Object o = anc.getObject(); if (o instanceof AccessControlled) { - checkPermission((AccessControlled) o,permission); + checkPermission((AccessControlled) o, permission); return; } } - checkPermission(Jenkins.get(),permission); + checkPermission(Jenkins.get(), permission); } } @@ -862,7 +866,7 @@ public static void checkPermission(Object object, Permission permission) throws * If null, returns true. This defaulting is convenient in making the use of this method terse. */ public static boolean hasPermission(Permission permission) throws IOException, ServletException { - return hasPermission(Jenkins.get(),permission); + return hasPermission(Jenkins.get(), permission); } /** @@ -873,13 +877,13 @@ public static boolean hasPermission(Object object, Permission permission) throws if (permission == null) return true; if (object instanceof AccessControlled) - return ((AccessControlled)object).hasPermission(permission); + return ((AccessControlled) object).hasPermission(permission); else { List ancs = Stapler.getCurrentRequest().getAncestors(); - for(Ancestor anc : Iterators.reverse(ancs)) { + for (Ancestor anc : Iterators.reverse(ancs)) { Object o = anc.getObject(); if (o instanceof AccessControlled) { - return ((AccessControlled)o).hasPermission(permission); + return ((AccessControlled) o).hasPermission(permission); } } return Jenkins.get().hasPermission(permission); @@ -889,7 +893,7 @@ public static boolean hasPermission(Object object, Permission permission) throws public static void adminCheck(StaplerRequest req, StaplerResponse rsp, Object required, Permission permission) throws IOException, ServletException { // this is legacy --- all views should be eventually converted to // the permission based model. - if(required!=null && !Hudson.adminCheck(req, rsp)) { + if (required != null && !Hudson.adminCheck(req, rsp)) { // check failed. commit the FORBIDDEN response, then abort. rsp.setStatus(HttpServletResponse.SC_FORBIDDEN); rsp.getOutputStream().close(); @@ -897,7 +901,7 @@ public static void adminCheck(StaplerRequest req, StaplerResponse rsp, Object re } // make sure the user owns the necessary permission to access this page. - if(permission!=null) + if (permission != null) checkPermission(permission); } @@ -906,13 +910,13 @@ public static void adminCheck(StaplerRequest req, StaplerResponse rsp, Object re */ public static String inferHudsonURL(StaplerRequest req) { String rootUrl = Jenkins.get().getRootUrl(); - if(rootUrl !=null) + if (rootUrl != null) // prefer the one explicitly configured, to work with load-balancer, frontend, etc. return rootUrl; StringBuilder buf = new StringBuilder(); buf.append(req.getScheme()).append("://"); buf.append(req.getServerName()); - if(! (req.getScheme().equals("http") && req.getLocalPort()==80 || req.getScheme().equals("https") && req.getLocalPort()==443)) + if (! (req.getScheme().equals("http") && req.getLocalPort() == 80 || req.getScheme().equals("https") && req.getLocalPort() == 443)) buf.append(':').append(req.getLocalPort()); buf.append(req.getContextPath()).append('/'); return buf.toString(); @@ -922,14 +926,15 @@ public static String inferHudsonURL(StaplerRequest req) { * Returns the link to be displayed in the footer of the UI. */ public static String getFooterURL() { - if(footerURL == null) { + if (footerURL == null) { footerURL = SystemProperties.getString("hudson.footerURL"); - if(StringUtils.isBlank(footerURL)) { + if (StringUtils.isBlank(footerURL)) { footerURL = "https://www.jenkins.io/"; } } return footerURL; } + private static String footerURL = null; public static List getJobPropertyDescriptors(Class clazz) { @@ -940,7 +945,7 @@ public static List getJobPropertyDescriptors(Job job) { return DescriptorVisibilityFilter.apply(job, JobPropertyDescriptor.getPropertyDescriptors(job.getClass())); } - public static List> getBuildWrapperDescriptors(AbstractProject project) { + public static List> getBuildWrapperDescriptors(AbstractProject project) { return BuildWrappers.getFor(project); } @@ -952,15 +957,15 @@ public static List> getAuthorizationStrategyDe return AuthorizationStrategy.all(); } - public static List> getBuilderDescriptors(AbstractProject project) { + public static List> getBuilderDescriptors(AbstractProject project) { return BuildStepDescriptor.filter(Builder.all(), project.getClass()); } - public static List> getPublisherDescriptors(AbstractProject project) { + public static List> getPublisherDescriptors(AbstractProject project) { return BuildStepDescriptor.filter(Publisher.all(), project.getClass()); } - public static List> getSCMDescriptors(AbstractProject project) { + public static List> getSCMDescriptors(AbstractProject project) { return SCM._for((Job) project); } @@ -1062,7 +1067,7 @@ public static Collection getSortedDescriptorsForGlobalConfig(com.goo for (ExtensionComponent c : exts.getComponents()) { Descriptor d = c.getInstance(); - if (d.getGlobalConfigPage()==null) continue; + if (d.getGlobalConfigPage() == null) continue; if (!Jenkins.get().hasPermission(d.getRequiredGlobalConfigPagePermission())) { continue; @@ -1077,7 +1082,7 @@ public static Collection getSortedDescriptorsForGlobalConfig(com.goo List answer = new ArrayList<>(r.size()); for (Tag d : r) answer.add(d.d); - return DescriptorVisibilityFilter.apply(Jenkins.get(),answer); + return DescriptorVisibilityFilter.apply(Jenkins.get(), answer); } /** @@ -1103,7 +1108,7 @@ public static Collection getSortedDescriptorsForGlobalConfigByDescri for (ExtensionComponent c : exts.getComponents()) { Descriptor d = c.getInstance(); - if (d.getGlobalConfigPage()==null) continue; + if (d.getGlobalConfigPage() == null) continue; if (predicate.test(d)) { r.add(new Tag(c.ordinal(), d)); @@ -1114,7 +1119,7 @@ public static Collection getSortedDescriptorsForGlobalConfigByDescri List answer = new ArrayList<>(r.size()); for (Tag d : r) answer.add(d.d); - return DescriptorVisibilityFilter.apply(Jenkins.get(),answer); + return DescriptorVisibilityFilter.apply(Jenkins.get(), answer); } /** @@ -1184,7 +1189,7 @@ public static boolean hasAnyPermission(Object object, Permission[] permissions) if (ac != null) { return hasAnyPermission(ac, permissions); } - + return hasAnyPermission(Jenkins.get(), permissions); } } @@ -1219,7 +1224,7 @@ public static void checkAnyPermission(Object object, Permission[] permissions) t checkAnyPermission((AccessControlled) object, permissions); else { List ancs = Stapler.getCurrentRequest().getAncestors(); - for(Ancestor anc : Iterators.reverse(ancs)) { + for (Ancestor anc : Iterators.reverse(ancs)) { Object o = anc.getObject(); if (o instanceof AccessControlled) { checkAnyPermission((AccessControlled) o, permissions); @@ -1243,14 +1248,14 @@ private static class Tag implements Comparable { private StringBuilder buildSuperclassHierarchy(Class c, StringBuilder buf) { Class sc = c.getSuperclass(); - if (sc!=null) buildSuperclassHierarchy(sc,buf).append(':'); + if (sc != null) buildSuperclassHierarchy(sc, buf).append(':'); return buf.append(c.getName()); } @Override public int compareTo(Tag that) { int r = Double.compare(that.ordinal, this.ordinal); - if (r!=0) return r; // descending for ordinal by reversing the order for compare + if (r != 0) return r; // descending for ordinal by reversing the order for compare return this.hierarchy.compareTo(that.hierarchy); } } @@ -1258,13 +1263,19 @@ public int compareTo(Tag that) { * Computes the path to the icon of the given action * from the context path. */ + public static String getIconFilePath(Action a) { String name = a.getIconFileName(); - if (name==null) return null; + if (name == null) { + return null; + } + if (name.startsWith("symbol-")) { + return name; + } if (name.startsWith("/")) return name.substring(1); else - return "images/24x24/"+name; + return "images/24x24/" + name; } /** @@ -1272,70 +1283,70 @@ public static String getIconFilePath(Action a) { * but handle null gracefully. */ public static int size2(Object o) throws Exception { - if(o==null) return 0; - return ASTSizeFunction.sizeOf(o,Introspector.getUberspect()); + if (o == null) return 0; + return ASTSizeFunction.sizeOf(o, Introspector.getUberspect()); } /** * Computes the relative path from the current page to the given item. */ public static String getRelativeLinkTo(Item p) { - Map ancestors = new HashMap<>(); - View view=null; + Map ancestors = new HashMap<>(); + View view = null; StaplerRequest request = Stapler.getCurrentRequest(); - for( Ancestor a : request.getAncestors() ) { - ancestors.put(a.getObject(),a.getRelativePath()); - if(a.getObject() instanceof View) + for (Ancestor a : request.getAncestors()) { + ancestors.put(a.getObject(), a.getRelativePath()); + if (a.getObject() instanceof View) view = (View) a.getObject(); } String path = ancestors.get(p); - if(path!=null) { + if (path != null) { return normalizeURI(path + '/'); } - Item i=p; + Item i = p; String url = ""; - while(true) { + while (true) { ItemGroup ig = i.getParent(); - url = i.getShortUrl()+url; + url = i.getShortUrl() + url; - if(ig== Jenkins.get() || (view != null && ig == view.getOwner().getItemGroup())) { + if (ig == Jenkins.get() || (view != null && ig == view.getOwner().getItemGroup())) { assert i instanceof TopLevelItem; if (view != null) { // assume p and the current page belong to the same view, so return a relative path // (even if they did not, View.getItem does not by default verify ownership) - return normalizeURI(ancestors.get(view)+'/'+url); + return normalizeURI(ancestors.get(view) + '/' + url); } else { // otherwise return a path from the root Hudson - return normalizeURI(request.getContextPath()+'/'+p.getUrl()); + return normalizeURI(request.getContextPath() + '/' + p.getUrl()); } } path = ancestors.get(ig); - if(path!=null) { - return normalizeURI(path+'/'+url); + if (path != null) { + return normalizeURI(path + '/' + url); } assert ig instanceof Item; // if not, ig must have been the Hudson instance i = (Item) ig; } } - + private static String normalizeURI(String uri) { return URI.create(uri).normalize().toString(); } - + /** * Gets all the {@link TopLevelItem}s recursively in the {@link ItemGroup} tree. - * + * * @since 1.512 */ public static List getAllTopLevelItems(ItemGroup root) { return root.getAllItems(TopLevelItem.class); } - + /** * Gets the relative name or display name to the given item from the specified group. * @@ -1354,41 +1365,41 @@ public static String getRelativeNameFrom(@CheckForNull Item p, @CheckForNull Ite if (p == null) return null; if (g == null) return useDisplayName ? p.getFullDisplayName() : p.getFullName(); String separationString = useDisplayName ? " » " : "/"; - + // first list up all the parents - Map parents = new HashMap<>(); - int depth=0; - while (g!=null) { + Map parents = new HashMap<>(); + int depth = 0; + while (g != null) { parents.put(g, depth++); if (g instanceof Item) - g = ((Item)g).getParent(); + g = ((Item) g).getParent(); else g = null; } StringBuilder buf = new StringBuilder(); - Item i=p; + Item i = p; while (true) { - if (buf.length()>0) buf.insert(0,separationString); - buf.insert(0,useDisplayName ? i.getDisplayName() : i.getName()); + if (buf.length() > 0) buf.insert(0, separationString); + buf.insert(0, useDisplayName ? i.getDisplayName() : i.getName()); ItemGroup gr = i.getParent(); Integer d = parents.get(gr); - if (d!=null) { - for (int j=d; j>0; j--) { - buf.insert(0,separationString); - buf.insert(0,".."); + if (d != null) { + for (int j = d; j > 0; j--) { + buf.insert(0, separationString); + buf.insert(0, ".."); } return buf.toString(); } if (gr instanceof Item) - i = (Item)gr; + i = (Item) gr; else // Parent is a group, but not an item return null; } } - + /** * Gets the name to the given item relative to given group. * @@ -1403,9 +1414,9 @@ public static String getRelativeNameFrom(@CheckForNull Item p, @CheckForNull Ite @Nullable public static String getRelativeNameFrom(@CheckForNull Item p, @CheckForNull ItemGroup g) { return getRelativeNameFrom(p, g, false); - } - - + } + + /** * Gets the relative display name to the given item from the specified group. * @@ -1422,15 +1433,15 @@ public static String getRelativeDisplayNameFrom(@CheckForNull Item p, @CheckForN return getRelativeNameFrom(p, g, true); } - public static Map dumpAllThreads() { - Map sorted = new TreeMap<>(new ThreadSorter()); + public static Map dumpAllThreads() { + Map sorted = new TreeMap<>(new ThreadSorter()); sorted.putAll(Thread.getAllStackTraces()); return sorted; } public static ThreadInfo[] getThreadInfos() { ThreadMXBean mbean = ManagementFactory.getThreadMXBean(); - return mbean.dumpAllThreads(mbean.isObjectMonitorUsageSupported(),mbean.isSynchronizerUsageSupported()); + return mbean.dumpAllThreads(mbean.isObjectMonitorUsageSupported(), mbean.isSynchronizerUsageSupported()); } public static ThreadGroupMap sortThreadsAndGetGroupMap(ThreadInfo[] list) { @@ -1441,12 +1452,12 @@ public static ThreadGroupMap sortThreadsAndGetGroupMap(ThreadInfo[] list) { // Common code for sorting Threads/ThreadInfos by ThreadGroup private static class ThreadSorterBase { - protected Map map = new HashMap<>(); + protected Map map = new HashMap<>(); ThreadSorterBase() { ThreadGroup tg = Thread.currentThread().getThreadGroup(); while (tg.getParent() != null) tg = tg.getParent(); - Thread[] threads = new Thread[tg.activeCount()*2]; + Thread[] threads = new Thread[tg.activeCount() * 2]; int threadsLen = tg.enumerate(threads, true); for (int i = 0; i < threadsLen; i++) { ThreadGroup group = threads[i].getThreadGroup(); @@ -1456,8 +1467,8 @@ private static class ThreadSorterBase { protected int compare(long idA, long idB) { String tga = map.get(idA), tgb = map.get(idB); - int result = (tga!=null?-1:0) + (tgb!=null?1:0); // Will be non-zero if only one is null - if (result==0 && tga!=null) + int result = (tga != null ? -1 : 0) + (tgb != null ? 1 : 0); // Will be non-zero if only one is null + if (result == 0 && tga != null) result = tga.compareToIgnoreCase(tgb); return result; } @@ -1526,7 +1537,7 @@ public static String dumpThreadInfo(ThreadInfo ti, ThreadGroupMap map) { } sb.append('\n'); StackTraceElement[] stackTrace = ti.getStackTrace(); - for (int i=0; i < stackTrace.length; i++) { + for (int i = 0; i < stackTrace.length; i++) { StackTraceElement ste = stackTrace[i]; sb.append("\tat ").append(ste); sb.append('\n'); @@ -1574,9 +1585,9 @@ public static Collection emptyList() { public static String jsStringEscape(String s) { if (s == null) return null; StringBuilder buf = new StringBuilder(); - for( int i=0; i T defaulted(T value, T defaultValue) { - return value!=null ? value : defaultValue; + return value != null ? value : defaultValue; } /** @@ -1669,6 +1680,7 @@ public static T defaulted(T value, T defaultValue) { doPrintStackTrace(s, t, null, "", new HashSet<>()); return s.toString(); } + private static void doPrintStackTrace(@NonNull StringBuilder s, @NonNull Throwable t, @CheckForNull Throwable higher, @NonNull String prefix, @NonNull Set encountered) { if (!encountered.add(t)) { s.append("\n"); @@ -1741,8 +1753,8 @@ public static void printStackTrace(@CheckForNull Throwable t, @NonNull PrintStre * Minimum 5 rows. */ public static int determineRows(String s) { - if(s==null) return 5; - return Math.max(5,LINE_END.split(s).length); + if (s == null) return 5; + return Math.max(5, LINE_END.split(s).length); } /** @@ -1776,7 +1788,7 @@ public static boolean isAnonymous() { */ public static JellyContext getCurrentJellyContext() { JellyContext context = ExpressionFactory2.CURRENT_CONTEXT.get(); - assert context!=null; + assert context != null; return context; } @@ -1796,8 +1808,8 @@ public static String runScript(Script script) throws JellyTagException { * Warning: do not call this with a {@link RunList}, or you will break lazy loading! */ public static List subList(List base, int maxSize) { - if(maxSize List subList(List base, int maxSize) { public static String joinPath(String... components) { StringBuilder buf = new StringBuilder(); for (String s : components) { - if (s.length()==0) continue; + if (s.length() == 0) continue; - if (buf.length()>0) { - if (buf.charAt(buf.length()-1)!='/') + if (buf.length() > 0) { + if (buf.charAt(buf.length() - 1) != '/') buf.append('/'); - if (s.charAt(0)=='/') s=s.substring(1); + if (s.charAt(0) == '/') s = s.substring(1); } buf.append(s); } @@ -1826,9 +1838,9 @@ public static String joinPath(String... components) { * * @return null in case the action should not be presented to the user. */ - public static @CheckForNull String getActionUrl(String itUrl,Action action) { + public static @CheckForNull String getActionUrl(String itUrl, Action action) { String urlName = action.getUrlName(); - if(urlName==null) return null; // Should not be displayed + if (urlName == null) return null; // Should not be displayed try { if (new URI(urlName).isAbsolute()) { return urlName; @@ -1837,11 +1849,11 @@ public static String joinPath(String... components) { Logger.getLogger(Functions.class.getName()).log(Level.WARNING, "Failed to parse URL for {0}: {1}", new Object[] {action, x}); return null; } - if(urlName.startsWith("/")) - return joinPath(Stapler.getCurrentRequest().getContextPath(),urlName); + if (urlName.startsWith("/")) + return joinPath(Stapler.getCurrentRequest().getContextPath(), urlName); else // relative URL name - return joinPath(Stapler.getCurrentRequest().getContextPath()+'/'+itUrl,urlName); + return joinPath(Stapler.getCurrentRequest().getContextPath() + '/' + itUrl, urlName); } /** @@ -1852,12 +1864,12 @@ public static String joinPath(String... components) { public static String toEmailSafeString(String projectName) { // TODO: escape non-ASCII characters StringBuilder buf = new StringBuilder(projectName.length()); - for( int i=0; i=0) + if (('a' <= ch && ch <= 'z') + || ('A' <= ch && ch <= 'Z') + || ('0' <= ch && ch <= '9') + || "-_.".indexOf(ch) >= 0) buf.append(ch); else buf.append('_'); // escape @@ -1876,9 +1888,9 @@ public String getServerName() { // This makes it work correctly when Hudson runs behind a reverse proxy. String url = Jenkins.get().getRootUrl(); try { - if(url!=null) { + if (url != null) { String host = new URL(url).getHost(); - if(host!=null) + if (host != null) return host; } } catch (MalformedURLException e) { @@ -1895,7 +1907,7 @@ public String getServerName() { */ @Deprecated public String getCheckUrl(String userDefined, Object descriptor, String field) { - if(userDefined!=null || field==null) return userDefined; + if (userDefined != null || field == null) return userDefined; if (descriptor instanceof Descriptor) { Descriptor d = (Descriptor) descriptor; return d.getCheckUrl(field); @@ -1908,13 +1920,13 @@ public String getCheckUrl(String userDefined, Object descriptor, String field) { * @since 1.528 */ public void calcCheckUrl(Map attributes, String userDefined, Object descriptor, String field) { - if(userDefined!=null || field==null) return; + if (userDefined != null || field == null) return; if (descriptor instanceof Descriptor) { Descriptor d = (Descriptor) descriptor; CheckMethod m = d.getCheckMethod(field); - attributes.put("checkUrl",m.toStemUrl()); - attributes.put("checkDependsOn",m.getDependsOn()); + attributes.put("checkUrl", m.toStemUrl()); + attributes.put("checkDependsOn", m.getDependsOn()); } } @@ -1926,8 +1938,8 @@ public void calcCheckUrl(Map attributes, String userDefined, Object descriptor, public boolean hyperlinkMatchesCurrentPage(String href) throws UnsupportedEncodingException { String url = Stapler.getCurrentRequest().getRequestURL().toString(); if (href == null || href.length() <= 1) return ".".equals(href) && url.endsWith("/"); - url = URLDecoder.decode(url,"UTF-8"); - href = URLDecoder.decode(href,"UTF-8"); + url = URLDecoder.decode(url, "UTF-8"); + href = URLDecoder.decode(href, "UTF-8"); if (url.endsWith("/")) url = url.substring(0, url.length() - 1); if (href.endsWith("/")) href = href.substring(0, href.length() - 1); @@ -1943,13 +1955,14 @@ public List singletonList(T t) { */ public static List getPageDecorators() { // this method may be called to render start up errors, at which point Hudson doesn't exist yet. see JENKINS-3608 - if(Jenkins.getInstanceOrNull()==null) return Collections.emptyList(); + if (Jenkins.getInstanceOrNull() == null) return Collections.emptyList(); return PageDecorator.all(); } /** * Gets only one {@link SimplePageDecorator}. * @since 2.128 */ + public static SimplePageDecorator getSimplePageDecorator() { return SimplePageDecorator.first(); } @@ -1966,8 +1979,8 @@ public static List> getCloudDescriptors() { * Prepend a prefix only when there's the specified body. */ public String prepend(String prefix, String body) { - if(body!=null && body.length()>0) - return prefix+body; + if (body != null && body.length() > 0) + return prefix + body; return body; } @@ -1992,11 +2005,11 @@ public static Date getCurrentTime() { } public static Locale getCurrentLocale() { - Locale locale=null; + Locale locale = null; StaplerRequest req = Stapler.getCurrentRequest(); - if(req!=null) + if (req != null) locale = req.getLocale(); - if(locale==null) + if (locale == null) locale = Locale.getDefault(); return locale; } @@ -2016,7 +2029,7 @@ public static String generateConsoleAnnotationScriptAndStylesheet() { buf.append(""); } for (ConsoleAnnotationDescriptor d : ConsoleAnnotationDescriptor.all()) { - String path = cp+"/descriptor/"+d.clazz.getName(); + String path = cp + "/descriptor/" + d.clazz.getName(); if (d.hasScript()) buf.append(""); if (d.hasStylesheet()) @@ -2113,9 +2126,9 @@ private String getJellyViewsInformationForCurrentRequest() { } public List filterDescriptors(Object context, Iterable descriptors) { - return DescriptorVisibilityFilter.apply(context,descriptors); + return DescriptorVisibilityFilter.apply(context, descriptors); } - + /** * Returns true if we are running unit tests. */ @@ -2154,13 +2167,13 @@ public static boolean isWipeOutPermissionEnabled() { } public static String createRenderOnDemandProxy(JellyContext context, String attributesToCapture) { - return Stapler.getCurrentRequest().createJavaScriptProxy(new RenderOnDemandClosure(context,attributesToCapture)); + return Stapler.getCurrentRequest().createJavaScriptProxy(new RenderOnDemandClosure(context, attributesToCapture)); } public static String getCurrentDescriptorByNameUrl() { return Descriptor.getCurrentDescriptorByNameUrl(); } - + public static String setCurrentDescriptorByNameUrl(String value) { String o = getCurrentDescriptorByNameUrl(); Stapler.getCurrentRequest().setAttribute("currentDescriptorByNameUrl", value); @@ -2185,7 +2198,7 @@ public static List getRequestHeaders(String name) { * Used for arguments to internationalized expressions to avoid escape */ public static Object rawHtml(Object o) { - return o==null ? null : new RawHtmlArgument(o); + return o == null ? null : new RawHtmlArgument(o); } public static ArrayList getCLICommands() { @@ -2211,30 +2224,30 @@ public static String getAvatar(User user, String avatarSize) { */ @Deprecated public String getUserAvatar(User user, String avatarSize) { - return getAvatar(user,avatarSize); + return getAvatar(user, avatarSize); } - - + + /** * Returns human readable information about file size - * + * * @param size file size in bytes * @return file size in appropriate unit */ - public static String humanReadableByteSize(long size){ + public static String humanReadableByteSize(long size) { String measure = "B"; - if(size < 1024){ + if (size < 1024) { return size + " " + measure; } double number = size; - if(number>=1024){ - number = number/1024; + if (number >= 1024) { + number = number / 1024; measure = "KB"; - if(number>=1024){ - number = number/1024; + if (number >= 1024) { + number = number / 1024; measure = "MB"; - if(number>=1024){ - number=number/1024; + if (number >= 1024) { + number = number / 1024; measure = "GB"; } } @@ -2267,8 +2280,8 @@ public static String breakableString(final String plain) { */ public static void advertiseHeaders(HttpServletResponse rsp) { Jenkins j = Jenkins.getInstanceOrNull(); - if (j!=null) { - rsp.setHeader("X-Hudson","1.395"); + if (j != null) { + rsp.setHeader("X-Hudson", "1.395"); rsp.setHeader("X-Jenkins", Jenkins.VERSION); rsp.setHeader("X-Jenkins-Session", Jenkins.SESSION_HASH); } @@ -2282,4 +2295,72 @@ public static boolean isContextMenuVisible(Action a) { return true; } } + + @Restricted(NoExternalUse.class) + public static Icon tryGetIcon(String iconGuess) { + // Jenkins Symbols don't have metadata so return null + if (iconGuess == null || iconGuess.startsWith("symbol-")) { + return null; + } + + StaplerRequest currentRequest = Stapler.getCurrentRequest(); + currentRequest.getWebApp().getDispatchValidator().allowDispatch(currentRequest, Stapler.getCurrentResponse()); + Icon iconMetadata = IconSet.icons.getIconByClassSpec(iconGuess); + + if (iconMetadata == null) { + // Icon could be provided as a simple iconFileName e.g. "settings.png" + iconMetadata = IconSet.icons.getIconByClassSpec(IconSet.toNormalizedIconNameClass(iconGuess) + " icon-md"); + } + + if (iconMetadata == null) { + // Icon could be provided as an absolute iconFileName e.g. "/plugin/foo/abc.png" + iconMetadata = IconSet.icons.getIconByUrl(iconGuess); + } + + return iconMetadata; + } + + @Restricted(NoExternalUse.class) + public static String tryGetIconPath(String iconGuess, JellyContext context) { + if (iconGuess == null) { + return null; + } + + if (iconGuess.startsWith("symbol-")) { + return iconGuess; + } + + StaplerRequest currentRequest = Stapler.getCurrentRequest(); + currentRequest.getWebApp().getDispatchValidator().allowDispatch(currentRequest, Stapler.getCurrentResponse()); + String rootURL = currentRequest.getContextPath(); + Icon iconMetadata = tryGetIcon(iconGuess); + String iconSource = null; + + if (iconMetadata != null) { + iconSource = iconMetadata.getQualifiedUrl(context); + } + + if (iconMetadata == null) { + if (!iconGuess.startsWith("/") && !iconGuess.startsWith("http")) { + iconGuess = "/" + iconGuess; + } + + iconSource = rootURL + (iconGuess.startsWith("/images/") || iconGuess.startsWith("/plugin/") ? getResourcePath() : "") + iconGuess; + } + + if (iconMetadata != null && iconMetadata.getClassSpec() != null) { + String translatedIcon = IconSet.tryTranslateTangoIconToSymbol(iconMetadata.getClassSpec()); + if (translatedIcon != null) { + return translatedIcon; + } + } + + return iconSource; + } + + @SuppressFBWarnings(value = "PREDICTABLE_RANDOM", justification = "True randomness isn't necessary for form item IDs") + @Restricted(NoExternalUse.class) + public static String generateItemId() { + return String.valueOf(Math.floor(Math.random() * 3000)); + } } diff --git a/core/src/main/java/hudson/Indenter.java b/core/src/main/java/hudson/Indenter.java index aa4348b57a9bb..90a1d403e2259 100644 --- a/core/src/main/java/hudson/Indenter.java +++ b/core/src/main/java/hudson/Indenter.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import hudson.model.Job; @@ -34,12 +35,12 @@ public abstract class Indenter { protected abstract int getNestLevel(J job); public final String getCss(J job) { - return "padding-left: "+getNestLevel(job)*2+"em"; + return "padding-left: " + getNestLevel(job) * 2 + "em"; } public final String getRelativeShift(J job) { int i = getNestLevel(job); - if(i==0) return null; - return "position:relative; left: "+ i *2+"em"; + if (i == 0) return null; + return "position:relative; left: " + i * 2 + "em"; } } diff --git a/core/src/main/java/hudson/Launcher.java b/core/src/main/java/hudson/Launcher.java index 57de28f89d5eb..6ea7375ff5a95 100644 --- a/core/src/main/java/hudson/Launcher.java +++ b/core/src/main/java/hudson/Launcher.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Stephen Connolly, CloudBees, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import static org.apache.commons.io.output.NullOutputStream.NULL_OUTPUT_STREAM; @@ -85,7 +86,7 @@ * * * @author Kohsuke Kawaguchi - * @see FilePath#createLauncher(TaskListener) + * @see FilePath#createLauncher(TaskListener) */ public abstract class Launcher { @@ -119,7 +120,7 @@ protected Launcher(@NonNull Launcher launcher) { * @since 2.246 */ @Restricted(Beta.class) - public void prepareFilterRules(@CheckForNull Run run, @NonNull EnvVarsFilterableBuilder builder){ + public void prepareFilterRules(@CheckForNull Run run, @NonNull EnvVarsFilterableBuilder builder) { List specificRuleList = builder.buildEnvVarsFilterRules(); EnvVarsFilterRuleWrapper ruleWrapper = EnvVarsFilterRuleWrapper.createRuleWrapper(run, builder, this, specificRuleList); this.setEnvVarsFilterRuleWrapper(ruleWrapper); @@ -146,7 +147,7 @@ public VirtualChannel getChannel() { /** * Gets the {@link TaskListener} that this launcher uses to * report the commands that it's executing. - * + * * @return Task listener */ @NonNull @@ -173,8 +174,8 @@ public TaskListener getListener() { @Deprecated @CheckForNull public Computer getComputer() { - for( Computer c : Jenkins.get().getComputers() ) - if(c.getChannel()==channel) + for (Computer c : Jenkins.get().getComputers()) + if (c.getChannel() == channel) return c; return null; } @@ -289,7 +290,7 @@ public boolean quiet() { /** * Sets the current directory. - * + * * @param workDir Work directory to be used. * If {@code null}, the default/current directory will be used by the process starter * @return {@code this} @@ -314,8 +315,8 @@ public FilePath pwd() { /** * Sets STDOUT destination. - * - * @param out Output stream. + * + * @param out Output stream. * Use {@code null} to send STDOUT to {@code /dev/null}. * @return {@code this} */ @@ -327,7 +328,7 @@ public ProcStarter stdout(@CheckForNull OutputStream out) { /** * Sends the stdout to the given {@link TaskListener}. - * + * * @param out Task listener (must be safely remotable) * @return {@code this} */ @@ -339,7 +340,7 @@ public ProcStarter stdout(@NonNull TaskListener out) { /** * Gets current STDOUT destination. - * + * * @return STDOUT output stream. {@code null} if STDOUT is suppressed or undefined. */ @CheckForNull @@ -358,7 +359,7 @@ public ProcStarter stderr(@CheckForNull OutputStream err) { /** * Gets current STDERR destination. - * + * * @return STDERR output stream. {@code null} if suppressed or undefined. */ @CheckForNull @@ -369,7 +370,7 @@ public OutputStream stderr() { /** * Controls where the stdin of the process comes from. * By default, {@code /dev/null}. - * + * * @return {@code this} */ @NonNull @@ -380,7 +381,7 @@ public ProcStarter stdin(@CheckForNull InputStream in) { /** * Gets current STDIN destination. - * + * * @return STDIN output stream. {@code null} if suppressed or undefined. */ @CheckForNull @@ -395,7 +396,7 @@ public InputStream stdin() { * In addition to what the current process * is inherited (if this is going to be launched from a agent agent, that * becomes the "current" process), these variables will be also set. - * + * * @param overrides Environment variables to be overridden * @return {@code this} */ @@ -407,7 +408,7 @@ public ProcStarter envs(@NonNull Map overrides) { /** * @param overrides * List of "VAR=VALUE". See {@link #envs(Map)} for the semantics. - * + * * @return {@code this} */ public ProcStarter envs(@CheckForNull String... overrides) { @@ -425,7 +426,7 @@ public ProcStarter envs(@CheckForNull String... overrides) { /** * Gets a list of environment variables to be set. * Returns an empty array if envs field has not been initialized. - * + * * @return If initialized, returns a copy of internal envs array. Otherwise - a new empty array. */ @NonNull @@ -470,7 +471,7 @@ public ProcStarter readStderr() { * Indicates that the caller will directly write to the child process {@link #stdin()} via {@link Proc#getStdin()}. * (Whereas by default you call {@link #stdin(InputStream)} * and let Jenkins pump your {@link InputStream} of choosing to stdin.) - * + * * @return {@code this} * @since 1.399 */ @@ -486,7 +487,7 @@ public ProcStarter writeStdin() { * @since 2.246 */ @Restricted(Beta.class) - public ProcStarter buildStep(EnvVarsFilterableBuilder envVarsFilterableBuilder){ + public ProcStarter buildStep(EnvVarsFilterableBuilder envVarsFilterableBuilder) { this.envVarsFilterableBuilder = envVarsFilterableBuilder; return this; } @@ -518,7 +519,7 @@ public int join() throws IOException, InterruptedException { // The logging around procHolderForJoin prevents the preliminary object deallocation we saw in JENKINS-23271 final Proc procHolderForJoin = start(); LOGGER.log(Level.FINER, "Started the process {0}", procHolderForJoin); - + if (procHolderForJoin instanceof ProcWithJenkins23271Patch) { return procHolderForJoin.join(); } else { @@ -571,8 +572,8 @@ public final ProcStarter launch() { * Use {@link #launch()} and its associated builder pattern */ @Deprecated - public final Proc launch(String cmd, Map env, OutputStream out, FilePath workDir) throws IOException { - return launch(cmd,Util.mapToEnv(env),out,workDir); + public final Proc launch(String cmd, Map env, OutputStream out, FilePath workDir) throws IOException { + return launch(cmd, Util.mapToEnv(env), out, workDir); } /** @@ -642,8 +643,8 @@ public final Proc launch(String[] cmd, boolean[] mask, Map env, * Use {@link #launch()} and its associated builder pattern */ @Deprecated - public final Proc launch(String cmd,String[] env,OutputStream out, FilePath workDir) throws IOException { - return launch(Util.tokenize(cmd),env,out,workDir); + public final Proc launch(String cmd, String[] env, OutputStream out, FilePath workDir) throws IOException { + return launch(Util.tokenize(cmd), env, out, workDir); } /** @@ -762,7 +763,7 @@ public Proc launch(String[] cmd, boolean[] mask, String[] env, InputStream in, O *

* When the returned channel is terminated, the process will be killed. * - * @param cmd + * @param cmd * The commands. * @param out * Where the stderr from the launched process will be sent. @@ -774,20 +775,20 @@ public Proc launch(String[] cmd, boolean[] mask, String[] env, InputStream in, O * is inherited (if this is going to be launched from an agent, that * becomes the "current" process), these variables will be also set. */ - public abstract Channel launchChannel(@NonNull String[] cmd, @NonNull OutputStream out, - @CheckForNull FilePath workDir, @NonNull Map envVars) throws IOException, InterruptedException; + public abstract Channel launchChannel(@NonNull String[] cmd, @NonNull OutputStream out, + @CheckForNull FilePath workDir, @NonNull Map envVars) throws IOException, InterruptedException; /** * Returns true if this {@link Launcher} is going to launch on Unix. */ public boolean isUnix() { - return File.pathSeparatorChar==':'; + return File.pathSeparatorChar == ':'; } /** * Calls {@link ProcessTree#killAll(Map)} to kill processes. */ - public abstract void kill(Map modelEnvVars) throws IOException, InterruptedException; + public abstract void kill(Map modelEnvVars) throws IOException, InterruptedException; /** * Prints out the command line to the listener so that users know what we are doing. @@ -796,7 +797,7 @@ protected final void printCommandLine(@NonNull String[] cmd, @CheckForNull FileP StringBuilder buf = new StringBuilder(); if (workDir != null) { buf.append('['); - if(showFullPath) + if (showFullPath) buf.append(workDir.getRemote()); else buf.append(workDir.getRemote().replaceFirst("^.+[/\\\\]", "")); @@ -805,8 +806,8 @@ protected final void printCommandLine(@NonNull String[] cmd, @CheckForNull FileP buf.append('$'); for (String c : cmd) { buf.append(' '); - if(c.indexOf(' ')>=0) { - if(c.indexOf('"')>=0) + if (c.indexOf(' ') >= 0) { + if (c.indexOf('"') >= 0) buf.append('\'').append(c).append('\''); else buf.append('"').append(c).append('"'); @@ -827,11 +828,11 @@ protected final void printCommandLine(@NonNull String[] cmd, @CheckForNull FileP * @param workDir The work dir. */ protected final void maskedPrintCommandLine(@NonNull List cmd, @CheckForNull boolean[] mask, @CheckForNull FilePath workDir) { - if(mask==null) { - printCommandLine(cmd.toArray(new String[0]),workDir); + if (mask == null) { + printCommandLine(cmd.toArray(new String[0]), workDir); return; } - + assert mask.length == cmd.size(); final String[] masked = new String[cmd.size()]; for (int i = 0; i < cmd.size(); i++) { @@ -843,14 +844,14 @@ protected final void maskedPrintCommandLine(@NonNull List cmd, @CheckFor } printCommandLine(masked, workDir); } - + protected final void maskedPrintCommandLine(@NonNull String[] cmd, @NonNull boolean[] mask, @CheckForNull FilePath workDir) { - maskedPrintCommandLine(Arrays.asList(cmd),mask,workDir); + maskedPrintCommandLine(Arrays.asList(cmd), mask, workDir); } /** * Returns a decorated {@link Launcher} for the given node. - * + * * @param node Node for which this launcher is created. * @return Decorated instance of the Launcher. */ @@ -858,7 +859,7 @@ protected final void maskedPrintCommandLine(@NonNull String[] cmd, @NonNull bool public final Launcher decorateFor(@NonNull Node node) { Launcher l = this; for (LauncherDecorator d : LauncherDecorator.all()) - l = d.decorate(l,node); + l = d.decorate(l, node); return l; } @@ -877,10 +878,10 @@ public final Launcher decorateByPrefix(final String... prefix) { public boolean isUnix() { return outer.isUnix(); } - + @Override public Proc launch(ProcStarter starter) throws IOException { - starter.commands.addAll(0,Arrays.asList(prefix)); + starter.commands.addAll(0, Arrays.asList(prefix)); boolean[] masks = starter.masks; if (masks != null) { starter.masks = prefix(masks); @@ -890,7 +891,7 @@ public Proc launch(ProcStarter starter) throws IOException { @Override public Channel launchChannel(String[] cmd, OutputStream out, FilePath workDir, Map envVars) throws IOException, InterruptedException { - return outer.launchChannel(prefix(cmd),out,workDir,envVars); + return outer.launchChannel(prefix(cmd), out, workDir, envVars); } @Override @@ -899,15 +900,15 @@ public void kill(Map modelEnvVars) throws IOException, Interrupt } private String[] prefix(@NonNull String[] args) { - String[] newArgs = new String[args.length+prefix.length]; - System.arraycopy(prefix,0,newArgs,0,prefix.length); - System.arraycopy(args,0,newArgs,prefix.length,args.length); + String[] newArgs = new String[args.length + prefix.length]; + System.arraycopy(prefix, 0, newArgs, 0, prefix.length); + System.arraycopy(args, 0, newArgs, prefix.length, args.length); return newArgs; } private boolean[] prefix(@NonNull boolean[] args) { - boolean[] newArgs = new boolean[args.length+prefix.length]; - System.arraycopy(args,0,newArgs,prefix.length,args.length); + boolean[] newArgs = new boolean[args.length + prefix.length]; + System.arraycopy(args, 0, newArgs, prefix.length, args.length); return newArgs; } }; @@ -935,7 +936,7 @@ public boolean isUnix() { @Override public Proc launch(ProcStarter starter) throws IOException { EnvVars e = new EnvVars(env); - if (starter.envs!=null) { + if (starter.envs != null) { for (String env : starter.envs) { e.addLine(env); } @@ -948,7 +949,7 @@ public Proc launch(ProcStarter starter) throws IOException { public Channel launchChannel(String[] cmd, OutputStream out, FilePath workDir, Map envVars) throws IOException, InterruptedException { EnvVars e = new EnvVars(env); e.putAll(envVars); - return outer.launchChannel(cmd,out,workDir,e); + return outer.launchChannel(cmd, out, workDir, e); } @Override @@ -986,27 +987,27 @@ public Proc launch(ProcStarter ps) throws IOException { // replace variables in command line String[] jobCmd = new String[ps.commands.size()]; - for ( int idx = 0 ; idx < jobCmd.length; idx++ ) - jobCmd[idx] = jobEnv.expand(ps.commands.get(idx)); + for (int idx = 0; idx < jobCmd.length; idx++) + jobCmd[idx] = jobEnv.expand(ps.commands.get(idx)); return new LocalProc(jobCmd, Util.mapToEnv(jobEnv), - ps.reverseStdin ?LocalProc.SELFPUMP_INPUT:ps.stdin, - ps.reverseStdout?LocalProc.SELFPUMP_OUTPUT:ps.stdout, - ps.reverseStderr?LocalProc.SELFPUMP_OUTPUT:ps.stderr, + ps.reverseStdin ? LocalProc.SELFPUMP_INPUT : ps.stdin, + ps.reverseStdout ? LocalProc.SELFPUMP_OUTPUT : ps.stdout, + ps.reverseStderr ? LocalProc.SELFPUMP_OUTPUT : ps.stderr, toFile(ps.pwd)); } private File toFile(FilePath f) { - return f==null ? null : new File(f.getRemote()); + return f == null ? null : new File(f.getRemote()); } @Override - public Channel launchChannel(String[] cmd, OutputStream out, FilePath workDir, Map envVars) throws IOException { + public Channel launchChannel(String[] cmd, OutputStream out, FilePath workDir, Map envVars) throws IOException { printCommandLine(cmd, workDir); ProcessBuilder pb = new ProcessBuilder(cmd); pb.directory(toFile(workDir)); - if (envVars!=null) pb.environment().putAll(envVars); + if (envVars != null) pb.environment().putAll(envVars); return launchChannel(out, pb); } @@ -1026,10 +1027,10 @@ public Channel launchChannel(OutputStream out, ProcessBuilder pb) throws IOExcep final Process proc = pb.start(); - final Thread t2 = new StreamCopyThread(pb.command()+": stderr copier", proc.getErrorStream(), out); + final Thread t2 = new StreamCopyThread(pb.command() + ": stderr copier", proc.getErrorStream(), out); t2.start(); - return new Channel("locally launched channel on "+ pb.command(), + return new Channel("locally launched channel on " + pb.command(), Computer.threadPoolForRemoting, proc.getInputStream(), proc.getOutputStream(), out) { /** @@ -1040,7 +1041,7 @@ public synchronized void terminate(IOException e) { super.terminate(e); ProcessTree pt = ProcessTree.get(); try { - pt.killAll(proc,cookie); + pt.killAll(proc, cookie); } catch (InterruptedException x) { LOGGER.log(Level.INFO, "Interrupted", x); } @@ -1109,11 +1110,11 @@ public VirtualChannel getChannel() { @Override public Proc launch(ProcStarter ps) throws IOException { final OutputStream out = ps.stdout == null || ps.stdoutListener != null ? null : new RemoteOutputStream(new CloseProofOutputStream(ps.stdout)); - final OutputStream err = ps.stderr==null ? null : new RemoteOutputStream(new CloseProofOutputStream(ps.stderr)); + final OutputStream err = ps.stderr == null ? null : new RemoteOutputStream(new CloseProofOutputStream(ps.stderr)); final InputStream in = ps.stdin == null || ps.stdin == NULL_INPUT_STREAM ? null : new RemoteInputStream(ps.stdin, false); - + final FilePath psPwd = ps.pwd; - final String workDir = psPwd==null ? null : psPwd.getRemote(); + final String workDir = psPwd == null ? null : psPwd.getRemote(); try { RemoteLaunchCallable remote = new RemoteLaunchCallable(ps.commands, ps.masks, ps.envs, in, ps.reverseStdin, out, ps.reverseStdout, err, ps.reverseStderr, ps.quiet, workDir, listener, ps.stdoutListener); @@ -1122,20 +1123,20 @@ public Proc launch(ProcStarter ps) throws IOException { envVarsFilterRuleWrapper = null; return new ProcImpl(getChannel().call(remote)); } catch (InterruptedException e) { - throw (IOException)new InterruptedIOException().initCause(e); + throw (IOException) new InterruptedIOException().initCause(e); } } @Override - public Channel launchChannel(String[] cmd, OutputStream err, FilePath _workDir, Map envOverrides) throws IOException, InterruptedException { + public Channel launchChannel(String[] cmd, OutputStream err, FilePath _workDir, Map envOverrides) throws IOException, InterruptedException { printCommandLine(cmd, _workDir); Pipe out = Pipe.createRemoteToLocal(); - final String workDir = _workDir==null ? null : _workDir.getRemote(); + final String workDir = _workDir == null ? null : _workDir.getRemote(); OutputStream os = getChannel().call(new RemoteChannelLaunchCallable(cmd, out, err, workDir, envOverrides)); - return new Channel("remotely launched channel on "+channel, + return new Channel("remotely launched channel on " + channel, Computer.threadPoolForRemoting, out.getIn(), new BufferedOutputStream(os)); } @@ -1145,7 +1146,7 @@ public boolean isUnix() { } @Override - public void kill(final Map modelEnvVars) throws IOException, InterruptedException { + public void kill(final Map modelEnvVars) throws IOException, InterruptedException { getChannel().call(new KillTask(modelEnvVars)); } @@ -1154,7 +1155,7 @@ public String toString() { return "RemoteLauncher[" + getChannel() + "]"; } - private static final class KillTask extends MasterToSlaveCallable { + private static final class KillTask extends MasterToSlaveCallable { private final Map modelEnvVars; KillTask(Map modelEnvVars) { @@ -1230,14 +1231,14 @@ public OutputStream getStdin() { } } } - + /** - * A launcher which delegates to a provided inner launcher. + * A launcher which delegates to a provided inner launcher. * Allows subclasses to only implement methods they want to override. - * Originally, this launcher has been implemented in + * Originally, this launcher has been implemented in * * Custom Tools Plugin. - * + * * @author rcampbell * @author Oleg Nenashev, Synopsys Inc. * @since 1.568 @@ -1301,9 +1302,9 @@ public VirtualChannel getChannel() { @Override public Proc launch(String[] cmd, String[] env, InputStream in, OutputStream out, FilePath workDir) throws IOException { - return inner.launch(cmd, env, in, out, workDir); + return inner.launch(cmd, env, in, out, workDir); } - + /** * Gets nested launcher. * @return Inner launcher @@ -1311,12 +1312,12 @@ public Proc launch(String[] cmd, String[] env, InputStream in, OutputStream out, @NonNull public Launcher getInner() { return inner; - } + } } public static class IOTriplet implements Serializable { @CheckForNull - InputStream stdout,stderr; + InputStream stdout, stderr; @CheckForNull OutputStream stdin; private static final long serialVersionUID = 1L; @@ -1324,16 +1325,19 @@ public static class IOTriplet implements Serializable { /** * Remoting interface of a remote process */ + public interface RemoteProcess { int join() throws InterruptedException, IOException; + void kill() throws IOException, InterruptedException; + boolean isAlive() throws IOException, InterruptedException; - + @NonNull IOTriplet getIOtriplet(); } - private static class RemoteLaunchCallable extends MasterToSlaveCallable { + private static class RemoteLaunchCallable extends MasterToSlaveCallable { private final @NonNull List cmd; private final @CheckForNull boolean[] masks; private final @CheckForNull String[] env; @@ -1350,8 +1354,8 @@ private static class RemoteLaunchCallable extends MasterToSlaveCallable cmd, @CheckForNull boolean[] masks, @CheckForNull String[] env, @CheckForNull InputStream in, boolean reverseStdin, - @CheckForNull OutputStream out, boolean reverseStdout, - @CheckForNull OutputStream err, boolean reverseStderr, + @CheckForNull OutputStream out, boolean reverseStdout, + @CheckForNull OutputStream err, boolean reverseStderr, boolean quiet, @CheckForNull String workDir, @NonNull TaskListener listener, @CheckForNull TaskListener stdoutListener) { this.cmd = new ArrayList<>(cmd); this.masks = masks; @@ -1386,14 +1390,14 @@ public RemoteProcess call() throws IOException { } else { ps.stdout(out); } - if(workDir!=null) ps.pwd(workDir); + if (workDir != null) ps.pwd(workDir); if (reverseStdin) ps.writeStdin(); if (reverseStdout) ps.readStdout(); if (reverseStderr) ps.readStderr(); final Proc p = ps.start(); - return channel.export(RemoteProcess.class,new RemoteProcess() { + return channel.export(RemoteProcess.class, new RemoteProcess() { @Override public int join() throws InterruptedException, IOException { try { @@ -1436,7 +1440,7 @@ public IOTriplet getIOtriplet() { private static final long serialVersionUID = 1L; } - private static class RemoteChannelLaunchCallable extends MasterToSlaveCallable { + private static class RemoteChannelLaunchCallable extends MasterToSlaveCallable { @NonNull private final String[] cmd; @NonNull @@ -1446,10 +1450,10 @@ private static class RemoteChannelLaunchCallable extends MasterToSlaveCallable envOverrides; + private final Map envOverrides; - RemoteChannelLaunchCallable(@NonNull String[] cmd, @NonNull Pipe out, @NonNull OutputStream err, - @CheckForNull String workDir, @NonNull Map envOverrides) { + RemoteChannelLaunchCallable(@NonNull String[] cmd, @NonNull Pipe out, @NonNull OutputStream err, + @CheckForNull String workDir, @NonNull Map envOverrides) { this.cmd = cmd; this.out = out; this.err = new RemoteOutputStream(err); @@ -1464,9 +1468,9 @@ public OutputStream call() throws IOException { workDir == null ? null : new File(workDir)); List cmdLines = Arrays.asList(cmd); - new StreamCopyThread("stdin copier for remote agent on "+cmdLines, + new StreamCopyThread("stdin copier for remote agent on " + cmdLines, p.getInputStream(), out.getOut()).start(); - new StreamCopyThread("stderr copier for remote agent on "+cmdLines, + new StreamCopyThread("stderr copier for remote agent on " + cmdLines, p.getErrorStream(), err).start(); // TODO: don't we need to join? @@ -1483,10 +1487,10 @@ public OutputStream call() throws IOException { private static EnvVars inherit(@CheckForNull String[] env) { // convert String[] to Map first EnvVars m = new EnvVars(); - if(env!=null) { + if (env != null) { for (String e : env) { int index = e.indexOf('='); - m.put(e.substring(0,index), e.substring(index+1)); + m.put(e.substring(0, index), e.substring(index + 1)); } } // then do the inheritance @@ -1496,12 +1500,12 @@ private static EnvVars inherit(@CheckForNull String[] env) { /** * Expands the list of environment variables by inheriting current env variables. */ - private static EnvVars inherit(@NonNull Map overrides) { + private static EnvVars inherit(@NonNull Map overrides) { EnvVars m = new EnvVars(EnvVars.masterEnvVars); m.overrideExpandingAll(overrides); return m; } - + /** * Debug option to display full current path instead of just the last token. */ diff --git a/core/src/main/java/hudson/LocalPluginManager.java b/core/src/main/java/hudson/LocalPluginManager.java index ede9554f5f488..d1fcfd678e3ad 100644 --- a/core/src/main/java/hudson/LocalPluginManager.java +++ b/core/src/main/java/hudson/LocalPluginManager.java @@ -46,7 +46,7 @@ public class LocalPluginManager extends PluginManager { * @param rootDir Jenkins home directory. */ public LocalPluginManager(@CheckForNull ServletContext context, @NonNull File rootDir) { - super(context, new File(rootDir,"plugins")); + super(context, new File(rootDir, "plugins")); } /** diff --git a/core/src/main/java/hudson/Lookup.java b/core/src/main/java/hudson/Lookup.java index b0b40ba89151d..ba051f72a633c 100644 --- a/core/src/main/java/hudson/Lookup.java +++ b/core/src/main/java/hudson/Lookup.java @@ -32,14 +32,14 @@ * @author Kohsuke Kawaguchi */ public class Lookup { - private final ConcurrentHashMap data = new ConcurrentHashMap<>(); + private final ConcurrentHashMap data = new ConcurrentHashMap<>(); public T get(Class type) { return type.cast(data.get(type)); } public T set(Class type, T instance) { - return type.cast(data.put(type,instance)); + return type.cast(data.put(type, instance)); } /** @@ -51,7 +51,7 @@ public T set(Class type, T instance) { */ public T setIfNull(Class type, T instance) { Object o = data.putIfAbsent(type, instance); - if (o!=null) return type.cast(o); + if (o != null) return type.cast(o); return instance; } } diff --git a/core/src/main/java/hudson/Main.java b/core/src/main/java/hudson/Main.java index 8ae8dfcd76ed1..625fef0c52ee8 100644 --- a/core/src/main/java/hudson/Main.java +++ b/core/src/main/java/hudson/Main.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import com.thoughtworks.xstream.core.util.Base64Encoder; @@ -69,7 +70,7 @@ public static void main(String[] args) { /** @see #remotePost */ public static int run(String[] args) throws Exception { String home = getHudsonHome(); - if (home==null) { + if (home == null) { System.err.println("JENKINS_HOME is not set."); return -1; } @@ -83,7 +84,7 @@ public static int run(String[] args) throws Exception { private static String getHudsonHome() { String home = EnvVars.masterEnvVars.get("JENKINS_HOME"); - if (home!=null) return home; + if (home != null) return home; return EnvVars.masterEnvVars.get("HUDSON_HOME"); } @@ -95,30 +96,30 @@ public static int remotePost(String[] args) throws Exception { String projectName = args[0]; String home = getHudsonHome(); - if(!home.endsWith("/")) home = home + '/'; // make sure it ends with '/' + if (!home.endsWith("/")) home = home + '/'; // make sure it ends with '/' // check for authentication info String auth = new URL(home).getUserInfo(); - if(auth != null) auth = "Basic " + new Base64Encoder().encode(auth.getBytes(StandardCharsets.UTF_8)); + if (auth != null) auth = "Basic " + new Base64Encoder().encode(auth.getBytes(StandardCharsets.UTF_8)); - {// check if the home is set correctly + { // check if the home is set correctly HttpURLConnection con = open(new URL(home)); if (auth != null) con.setRequestProperty("Authorization", auth); con.connect(); - if(con.getResponseCode()!=200 - || con.getHeaderField("X-Hudson")==null) { - System.err.println(home+" is not Hudson ("+con.getResponseMessage()+")"); + if (con.getResponseCode() != 200 + || con.getHeaderField("X-Hudson") == null) { + System.err.println(home + " is not Hudson (" + con.getResponseMessage() + ")"); return -1; } } URL jobURL = new URL(home + "job/" + Util.encode(projectName).replace("/", "/job/") + "/"); - {// check if the job name is correct + { // check if the job name is correct HttpURLConnection con = open(new URL(jobURL, "acceptBuildResult")); if (auth != null) con.setRequestProperty("Authorization", auth); con.connect(); - if(con.getResponseCode()!=200) { + if (con.getResponseCode() != 200) { System.err.println(jobURL + " is not a valid external job (" + con.getResponseCode() + " " + con.getResponseMessage() + ")"); return -1; } @@ -130,7 +131,7 @@ public static int remotePost(String[] args) throws Exception { HttpURLConnection con = open(new URL(home + "crumbIssuer/api/xml?xpath=concat(//crumbRequestField,\":\",//crumb)'")); if (auth != null) con.setRequestProperty("Authorization", auth); - String line = IOUtils.readFirstLine(con.getInputStream(),"UTF-8"); + String line = IOUtils.readFirstLine(con.getInputStream(), "UTF-8"); String[] components = line.split(":"); if (components.length == 2) { crumbField = components[0]; @@ -141,31 +142,31 @@ public static int remotePost(String[] args) throws Exception { } // write the output to a temporary file first. - File tmpFile = File.createTempFile("jenkins","log"); + File tmpFile = File.createTempFile("jenkins", "log"); try { int ret; try (OutputStream os = Files.newOutputStream(tmpFile.toPath()); Writer w = new OutputStreamWriter(os, StandardCharsets.UTF_8)) { w.write(""); - w.write(""); + w.write(""); w.flush(); // run the command long start = System.currentTimeMillis(); List cmd = new ArrayList<>(Arrays.asList(args).subList(1, args.length)); - Proc proc = new Proc.LocalProc(cmd.toArray(new String[0]),(String[])null,System.in, - new DualOutputStream(System.out,new EncodingStream(os))); + Proc proc = new Proc.LocalProc(cmd.toArray(new String[0]), (String[]) null, System.in, + new DualOutputStream(System.out, new EncodingStream(os))); ret = proc.join(); - w.write(""+ret+""+(System.currentTimeMillis()-start)+""); + w.write("" + ret + "" + (System.currentTimeMillis() - start) + ""); } catch (InvalidPathException e) { throw new IOException(e); } URL location = new URL(jobURL, "postBuildResult"); - while(true) { + while (true) { try { // start a remote connection HttpURLConnection con = open(location); @@ -175,7 +176,7 @@ public static int remotePost(String[] args) throws Exception { } con.setDoOutput(true); // this tells HttpURLConnection not to buffer the whole thing - con.setFixedLengthStreamingMode((int)tmpFile.length()); + con.setFixedLengthStreamingMode((int) tmpFile.length()); con.connect(); // send the data try (InputStream in = Files.newInputStream(tmpFile.toPath())) { @@ -184,13 +185,13 @@ public static int remotePost(String[] args) throws Exception { throw new IOException(e); } - if(con.getResponseCode()!=200) { + if (con.getResponseCode() != 200) { org.apache.commons.io.IOUtils.copy(con.getErrorStream(), System.err); } return ret; } catch (HttpRetryException e) { - if(e.getLocation()!=null) { + if (e.getLocation() != null) { // retry with the new location location = new URL(e.getLocation()); continue; @@ -208,7 +209,7 @@ public static int remotePost(String[] args) throws Exception { * Connects to the given HTTP URL and configure time out, to avoid infinite hang. */ private static HttpURLConnection open(URL url) throws IOException { - HttpURLConnection c = (HttpURLConnection)url.openConnection(); + HttpURLConnection c = (HttpURLConnection) url.openConnection(); c.setReadTimeout(TIMEOUT); c.setConnectTimeout(TIMEOUT); return c; @@ -225,10 +226,10 @@ private static HttpURLConnection open(URL url) throws IOException { * This is also set if running inside {@code mvn hpi:run} since plugins parent POM 2.30. */ @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "for debugging") - public static boolean isDevelopmentMode = SystemProperties.getBoolean(Main.class.getName()+".development"); + public static boolean isDevelopmentMode = SystemProperties.getBoolean(Main.class.getName() + ".development"); /** * Time out for socket connection to Hudson. */ - public static final int TIMEOUT = SystemProperties.getInteger(Main.class.getName()+".timeout",15000); + public static final int TIMEOUT = SystemProperties.getInteger(Main.class.getName() + ".timeout", 15000); } diff --git a/core/src/main/java/hudson/MarkupText.java b/core/src/main/java/hudson/MarkupText.java index 0317a7e1b0164..182565205ecfa 100644 --- a/core/src/main/java/hudson/MarkupText.java +++ b/core/src/main/java/hudson/MarkupText.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import java.util.ArrayList; @@ -66,7 +67,7 @@ private static final class Tag implements Comparable { @Override public int compareTo(Tag that) { - return this.pos-that.pos; + return this.pos - that.pos; } } @@ -74,7 +75,7 @@ public int compareTo(Tag that) { * Represents a substring of a {@link MarkupText}. */ public final class SubText extends AbstractMarkupText { - private final int start,end; + private final int start, end; private final int[] groups; public SubText(Matcher m, int textOffset) { @@ -82,10 +83,10 @@ public SubText(Matcher m, int textOffset) { end = m.end() + textOffset; int cnt = m.groupCount(); - groups = new int[cnt*2]; - for( int i=0; i…}. */ public void href(String url) { - addHyperlink(0,length(),url); + addHyperlink(0, length(), url); } /** @@ -146,8 +147,8 @@ public void href(String url) { * groups captured by '(...)' in the regexp. */ public int start(int groupIndex) { - if(groupIndex==0) return start; - return groups[groupIndex*2-2]; + if (groupIndex == 0) return start; + return groups[groupIndex * 2 - 2]; } /** @@ -161,8 +162,8 @@ public int start() { * Gets the end index of the captured group within {@link MarkupText#getText()}. */ public int end(int groupIndex) { - if(groupIndex==0) return end; - return groups[groupIndex*2-1]; + if (groupIndex == 0) return end; + return groups[groupIndex * 2 - 1]; } /** @@ -176,9 +177,9 @@ public int end() { * Gets the text that represents the captured group. */ public String group(int groupIndex) { - if(start(groupIndex)==-1) + if (start(groupIndex) == -1) return null; - return text.substring(start(groupIndex),end(groupIndex)); + return text.substring(start(groupIndex), end(groupIndex)); } /** @@ -195,24 +196,24 @@ public int groupCount() { public String replace(String s) { StringBuilder buf = new StringBuilder(s.length() + 10); - for( int i=0; i 9) { - buf.append('$').append(ch); + buf.append('$').append(ch); } else { - // add the group text - String group = group(groupId); - if (group != null) - buf.append(group); + // add the group text + String group = group(groupId); + if (group != null) + buf.append(group); } } else { @@ -226,7 +227,7 @@ public String replace(String s) { @Override protected SubText createSubText(Matcher m) { - return new SubText(m,start); + return new SubText(m, start); } } @@ -252,29 +253,29 @@ public String getText() { */ @Override public SubText subText(int start, int end) { - return new SubText(start, end<0 ? text.length()+1+end : end); + return new SubText(start, end < 0 ? text.length() + 1 + end : end); } @Override - public void addMarkup( int startPos, int endPos, String startTag, String endTag ) { + public void addMarkup(int startPos, int endPos, String startTag, String endTag) { rangeCheck(startPos); rangeCheck(endPos); - if(startPos>endPos) throw new IndexOutOfBoundsException(); + if (startPos > endPos) throw new IndexOutOfBoundsException(); // when multiple tags are added to the same range, we want them to show up like // abc, not abc. Also, we'd like abcdef, // not abcdef. Do this by inserting them to different places. tags.add(new Tag(startPos, startTag)); - tags.add(0,new Tag(endPos,endTag)); + tags.add(0, new Tag(endPos, endTag)); } public void addMarkup(int pos, String tag) { rangeCheck(pos); - tags.add(new Tag(pos,tag)); + tags.add(new Tag(pos, tag)); } private void rangeCheck(int pos) { - if(pos<0 || pos>text.length()) + if (pos < 0 || pos > text.length()) throw new IndexOutOfBoundsException(); } @@ -298,8 +299,8 @@ public String toString() { * If false, the escape is for the normal HTML, thus SP becomes &nbsp; and CR/LF becomes {@code
} */ public String toString(boolean preEscape) { - if(tags.isEmpty()) - return preEscape? Util.xmlEscape(text) : Util.escape(text); // the most common case + if (tags.isEmpty()) + return preEscape ? Util.xmlEscape(text) : Util.escape(text); // the most common case Collections.sort(tags); @@ -307,14 +308,14 @@ public String toString(boolean preEscape) { int copied = 0; // # of chars already copied from text to buf for (Tag tag : tags) { - if (copied findTokens(Pattern pattern) { @Override protected SubText createSubText(Matcher m) { - return new SubText(m,0); + return new SubText(m, 0); } } diff --git a/core/src/main/java/hudson/PermalinkList.java b/core/src/main/java/hudson/PermalinkList.java index 4b165d66747f1..6c97c54a00b2c 100644 --- a/core/src/main/java/hudson/PermalinkList.java +++ b/core/src/main/java/hudson/PermalinkList.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import hudson.model.PermalinkProjectAction.Permalink; @@ -50,7 +51,7 @@ public PermalinkList() { */ public Permalink get(String id) { for (Permalink p : this) - if(p.getId().equals(id)) + if (p.getId().equals(id)) return p; return null; } @@ -63,7 +64,7 @@ public Permalink findNearest(String id) { for (Permalink p : this) ids.add(p.getId()); String nearest = EditDistance.findNearest(id, ids); - if(nearest==null) return null; + if (nearest == null) return null; return get(nearest); } } diff --git a/core/src/main/java/hudson/Platform.java b/core/src/main/java/hudson/Platform.java index 2195f571aceec..23ab0caa6653a 100644 --- a/core/src/main/java/hudson/Platform.java +++ b/core/src/main/java/hudson/Platform.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import hudson.util.VersionNumber; @@ -36,10 +37,10 @@ * @author Kohsuke Kawaguchi */ public enum Platform { - WINDOWS(';'),UNIX(':'); + WINDOWS(';'), UNIX(':'); /** - * The character that separates paths in environment variables like PATH and CLASSPATH. + * The character that separates paths in environment variables like PATH and CLASSPATH. * On Windows ';' and on Unix ':'. * * @see File#pathSeparator @@ -51,7 +52,7 @@ public enum Platform { } public static Platform current() { - if(File.pathSeparatorChar==':') return UNIX; + if (File.pathSeparatorChar == ':') return UNIX; return WINDOWS; } @@ -65,7 +66,7 @@ public static boolean isDarwin() { */ public static boolean isSnowLeopardOrLater() { try { - return isDarwin() && new VersionNumber(System.getProperty("os.version")).compareTo(new VersionNumber("10.6"))>=0; + return isDarwin() && new VersionNumber(System.getProperty("os.version")).compareTo(new VersionNumber("10.6")) >= 0; } catch (IllegalArgumentException e) { // failed to parse the version return false; diff --git a/core/src/main/java/hudson/Plugin.java b/core/src/main/java/hudson/Plugin.java index 0942db8fd90d7..41eafeabf5455 100644 --- a/core/src/main/java/hudson/Plugin.java +++ b/core/src/main/java/hudson/Plugin.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import com.thoughtworks.xstream.XStream; @@ -266,7 +267,7 @@ public void doDynamic(StaplerRequest req, StaplerResponse rsp) throws IOExceptio */ protected void load() throws IOException { XmlFile xml = getConfigXml(); - if(xml.exists()) + if (xml.exists()) xml.unmarshal(this); } @@ -277,7 +278,7 @@ protected void load() throws IOException { */ @Override public void save() throws IOException { - if(BulkChange.contains(this)) return; + if (BulkChange.contains(this)) return; XmlFile config = getConfigXml(); config.write(this); SaveableListener.fireOnChange(this, config); @@ -294,7 +295,7 @@ public void save() throws IOException { */ protected XmlFile getConfigXml() { return new XmlFile(Jenkins.XSTREAM, - new File(Jenkins.get().getRootDir(),wrapper.getShortName()+".xml")); + new File(Jenkins.get().getRootDir(), wrapper.getShortName() + ".xml")); } @Override diff --git a/core/src/main/java/hudson/PluginFirstClassLoader.java b/core/src/main/java/hudson/PluginFirstClassLoader.java index 8aee057e7b39c..a990ea329e5a5 100644 --- a/core/src/main/java/hudson/PluginFirstClassLoader.java +++ b/core/src/main/java/hudson/PluginFirstClassLoader.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Olivier Lamy - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import java.io.File; @@ -49,47 +50,47 @@ public PluginFirstClassLoader() { private List urls = new CopyOnWriteArrayList<>(); @Override - public void addPathFiles( Collection paths ) + public void addPathFiles(Collection paths) throws IOException { - for ( File f : paths ) + for (File f : paths) { - urls.add( f.toURI().toURL() ); - addPathFile( f ); + urls.add(f.toURI().toURL()); + addPathFile(f); } } /** * @return List of jar used by the plugin /WEB-INF/lib/*.jar and classes directory /WEB-INF/classes */ - public List getURLs() + public List getURLs() { return urls; } @Override - protected Enumeration findResources( String name, boolean skipParent ) + protected Enumeration findResources(String name, boolean skipParent) throws IOException { - return super.findResources( name, skipParent ); + return super.findResources(name, skipParent); } @Override - public Enumeration findResources( String name ) + public Enumeration findResources(String name) throws IOException { - return super.findResources( name ); + return super.findResources(name); } @Override - public URL getResource( String name ) + public URL getResource(String name) { - return super.getResource( name ); + return super.getResource(name); } @Override - public InputStream getResourceAsStream( String name ) + public InputStream getResourceAsStream(String name) { - return super.getResourceAsStream( name ); + return super.getResourceAsStream(name); } } diff --git a/core/src/main/java/hudson/PluginManager.java b/core/src/main/java/hudson/PluginManager.java index 02b31686b30cc..c898a899f051a 100644 --- a/core/src/main/java/hudson/PluginManager.java +++ b/core/src/main/java/hudson/PluginManager.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import static hudson.init.InitMilestone.COMPLETED; @@ -210,7 +211,7 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas // Secure initialization CHECK_UPDATE_SLEEP_TIME_MILLIS = SystemProperties.getInteger(PluginManager.class.getName() + ".checkUpdateSleepTimeMillis", 1000); CHECK_UPDATE_ATTEMPTS = SystemProperties.getInteger(PluginManager.class.getName() + ".checkUpdateAttempts", 1); - } catch(RuntimeException e) { + } catch (RuntimeException e) { LOGGER.warning(String.format("There was an error initializing the PluginManager. Exception: %s", e)); } finally { CHECK_UPDATE_ATTEMPTS = CHECK_UPDATE_ATTEMPTS > 0 ? CHECK_UPDATE_ATTEMPTS : 1; @@ -222,7 +223,7 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas private enum PMConstructor { JENKINS { @Override - @NonNull + @NonNull PluginManager doCreate(@NonNull Class klass, @NonNull Jenkins jenkins) throws ReflectiveOperationException { return klass.getConstructor(Jenkins.class).newInstance(jenkins); @@ -247,7 +248,7 @@ PluginManager doCreate(@NonNull Class klass, @NonNull Jenkins jenkins) throws ReflectiveOperationException { try { return doCreate(klass, jenkins); - } catch(NoSuchMethodException e) { + } catch (NoSuchMethodException e) { // Constructor not found. Will try the remaining ones. return null; } @@ -278,9 +279,9 @@ PluginManager doCreate(@NonNull Class klass, } } LOGGER.log(WARNING, String.format("Provided custom plugin manager [%s] does not provide any of the suitable constructors. Using default.", pmClassName)); - } catch(ClassCastException e) { + } catch (ClassCastException e) { LOGGER.log(WARNING, String.format("Provided class [%s] does not extend PluginManager. Using default.", pmClassName)); - } catch(Exception e) { + } catch (Exception e) { LOGGER.log(WARNING, String.format("Unable to instantiate custom plugin manager [%s]. Using default.", pmClassName), e); } } @@ -359,11 +360,11 @@ protected PluginManager(ServletContext context, File rootDir) { this.rootDir = rootDir; try { - Files.createDirectories(rootDir.toPath()); + Util.createDirectories(rootDir.toPath()); } catch (IOException e) { throw new UncheckedIOException(e); } - String workDir = SystemProperties.getString(PluginManager.class.getName()+".workDir"); + String workDir = SystemProperties.getString(PluginManager.class.getName() + ".workDir"); this.workDir = StringUtils.isBlank(workDir) ? null : new File(workDir); strategy = createPluginStrategy(); @@ -420,15 +421,15 @@ public void run(Reactor session) throws Exception { } }); - requires(listUpPlugins).attains(PLUGINS_LISTED).add("Preparing plugins",new Executable() { + requires(listUpPlugins).attains(PLUGINS_LISTED).add("Preparing plugins", new Executable() { @Override public void run(Reactor session) throws Exception { // once we've listed plugins, we can fill in the reactor with plugin-specific initialization tasks TaskGraphBuilder g = new TaskGraphBuilder(); - final Map inspectedShortNames = new HashMap<>(); + final Map inspectedShortNames = new HashMap<>(); - for( final File arc : archives ) { + for (final File arc : archives) { g.followedBy().notFatal().attains(PLUGINS_LISTED).add("Inspecting plugin " + arc, new Executable() { @Override public void run(Reactor session1) throws Exception { @@ -439,7 +440,7 @@ public void run(Reactor session1) throws Exception { p.isBundled = containsHpiJpi(bundledPlugins, arc.getName()); plugins.add(p); } catch (IOException e) { - failedPlugins.add(new FailedPlugin(arc.getName(),e)); + failedPlugins.add(new FailedPlugin(arc.getName(), e)); throw e; } } @@ -451,11 +452,11 @@ public void run(Reactor session1) throws Exception { private boolean isDuplicate(PluginWrapper p) { String shortName = p.getShortName(); if (inspectedShortNames.containsKey(shortName)) { - LOGGER.info("Ignoring "+arc+" because "+inspectedShortNames.get(shortName)+" is already loaded"); + LOGGER.info("Ignoring " + arc + " because " + inspectedShortNames.get(shortName) + " is already loaded"); return true; } - inspectedShortNames.put(shortName,arc); + inspectedShortNames.put(shortName, arc); return false; } }); @@ -500,7 +501,7 @@ protected void reactOnCycle(PluginWrapper q, List cycle) { // obtain topologically sorted list and overwrite the list for (PluginWrapper p : cgd.getSorted()) { - if(p.isActive()) + if (p.isActive()) activePlugins.add(p); } } catch (CycleDetectedException e) { // TODO this should be impossible, since we override reactOnCycle to not throw the exception @@ -640,9 +641,9 @@ void considerDetachedPlugin(String shortName) { Set copiedPlugins = new HashSet<>(); Set dependencies = new HashSet<>(); - for( String pluginPath : plugins) { - String fileName = pluginPath.substring(pluginPath.lastIndexOf('/')+1); - if(fileName.length()==0) { + for (String pluginPath : plugins) { + String fileName = pluginPath.substring(pluginPath.lastIndexOf('/') + 1); + if (fileName.length() == 0) { // see http://www.nabble.com/404-Not-Found-error-when-clicking-on-help-td24508544.html // I suspect some containers are returning directory names. continue; @@ -664,7 +665,7 @@ void considerDetachedPlugin(String shortName) { LOGGER.log(Level.SEVERE, "Failed to resolve dependencies for the bundled plugin " + fileName, e); } } catch (IOException e) { - LOGGER.log(Level.SEVERE, "Failed to extract the bundled plugin "+fileName,e); + LOGGER.log(Level.SEVERE, "Failed to extract the bundled plugin " + fileName, e); } } @@ -857,8 +858,8 @@ private String normalisePluginName(@NonNull String name) { * this is necessary since the bundled plugins are still called *.hpi */ private boolean containsHpiJpi(Collection bundledPlugins, String name) { - return bundledPlugins.contains(name.replaceAll("\\.hpi",".jpi")) - || bundledPlugins.contains(name.replaceAll("\\.jpi",".hpi")); + return bundledPlugins.contains(name.replaceAll("\\.hpi", ".jpi")) + || bundledPlugins.contains(name.replaceAll("\\.jpi", ".hpi")); } /** @@ -894,11 +895,11 @@ public void dynamicLoad(File arc, boolean removeExisting, @CheckForNull List i = plugins.iterator(); i.hasNext();) { pw = i.next(); - if(sn.equals(pw.getShortName())) { + if (sn.equals(pw.getShortName())) { i.remove(); break; } @@ -910,7 +911,7 @@ public void dynamicLoad(File arc, boolean removeExisting, @CheckForNull List plugins) throws Exception { Map pluginsByName = plugins.stream().collect(Collectors.toMap(PluginWrapper::getShortName, p -> p)); // recalculate dependencies of plugins optionally depending the newly deployed ones. - for (PluginWrapper depender: this.plugins) { + for (PluginWrapper depender : this.plugins) { if (plugins.contains(depender)) { // skip itself. continue; } - for (Dependency d: depender.getOptionalDependencies()) { + for (Dependency d : depender.getOptionalDependencies()) { PluginWrapper dependee = pluginsByName.get(d.shortName); if (dependee != null) { // this plugin depends on the newly loaded one! @@ -1003,7 +1004,7 @@ public synchronized void resolveDependentPlugins() { Set dependents = new HashSet<>(); for (PluginWrapper possibleDependent : plugins) { // No need to check if plugin is dependent of itself - if(possibleDependent.getShortName().equals(plugin.getShortName())) { + if (possibleDependent.getShortName().equals(plugin.getShortName())) { continue; } @@ -1052,13 +1053,13 @@ public synchronized void resolveDependentPlugins() { */ protected void copyBundledPlugin(URL src, String fileName) throws IOException { LOGGER.log(FINE, "Copying {0}", src); - fileName = fileName.replace(".hpi",".jpi"); // normalize fileNames to have the correct suffix - String legacyName = fileName.replace(".jpi",".hpi"); + fileName = fileName.replace(".hpi", ".jpi"); // normalize fileNames to have the correct suffix + String legacyName = fileName.replace(".jpi", ".hpi"); long lastModified = getModificationDate(src); File file = new File(rootDir, fileName); // normalization first, if the old file exists. - rename(new File(rootDir,legacyName),file); + rename(new File(rootDir, legacyName), file); // update file if: // - no file exists today @@ -1077,11 +1078,11 @@ protected void copyBundledPlugin(URL src, String fileName) throws IOException { } /*package*/ static @CheckForNull Manifest parsePluginManifest(URL bundledJpi) { - try (URLClassLoader cl = new URLClassLoader(new URL[]{bundledJpi})){ - InputStream in=null; + try (URLClassLoader cl = new URLClassLoader(new URL[]{bundledJpi})) { + InputStream in = null; try { URL res = cl.findResource(PluginWrapper.MANIFEST_FILENAME); - if (res!=null) { + if (res != null) { in = getBundledJpiManifestStream(res); return new Manifest(in); } @@ -1089,11 +1090,11 @@ protected void copyBundledPlugin(URL src, String fileName) throws IOException { Util.closeAndLogFailures(in, LOGGER, PluginWrapper.MANIFEST_FILENAME, bundledJpi.toString()); } } catch (IOException e) { - LOGGER.log(WARNING, "Failed to parse manifest of "+bundledJpi, e); + LOGGER.log(WARNING, "Failed to parse manifest of " + bundledJpi, e); } return null; } - + /** * Retrieves input stream for the Manifest url. * The method intelligently handles the case of {@link JarURLConnection} pointing to files within JAR. @@ -1106,15 +1107,15 @@ protected void copyBundledPlugin(URL src, String fileName) throws IOException { URLConnection uc = url.openConnection(); InputStream in = null; // Magic, which allows to avoid using stream generated for JarURLConnection. - // It prevents getting into JENKINS-37332 due to the file descriptor leak + // It prevents getting into JENKINS-37332 due to the file descriptor leak if (uc instanceof JarURLConnection) { final JarURLConnection jarURLConnection = (JarURLConnection) uc; final String entryName = jarURLConnection.getEntryName(); - - try(JarFile jarFile = jarURLConnection.getJarFile()) { + + try (JarFile jarFile = jarURLConnection.getJarFile()) { final JarEntry entry = entryName != null && jarFile != null ? jarFile.getJarEntry(entryName) : null; if (entry != null) { - try(InputStream i = jarFile.getInputStream(entry)) { + try (InputStream i = jarFile.getInputStream(entry)) { byte[] manifestBytes = IOUtils.toByteArray(i); in = new ByteArrayInputStream(manifestBytes); } @@ -1124,16 +1125,16 @@ protected void copyBundledPlugin(URL src, String fileName) throws IOException { url); } } - } + } // If input stream is undefined, use the default implementation if (in == null) { in = url.openStream(); } - + return in; } - + /** * Retrieves modification date of the specified file. * The method intelligently handles the case of {@link JarURLConnection} pointing to files within JAR. @@ -1144,7 +1145,7 @@ protected void copyBundledPlugin(URL src, String fileName) throws IOException { @NonNull /*package*/ static long getModificationDate(@NonNull URL url) throws IOException { URLConnection uc = url.openConnection(); - + // It prevents file descriptor leak if the URL references a file within JAR // See JENKINS-37332 for more info // The code idea is taken from https://github.com/jknack/handlebars.java/pull/394 @@ -1163,7 +1164,7 @@ protected void copyBundledPlugin(URL src, String fileName) throws IOException { } } } - + // Fallbak to the default implementation return uc.getLastModified(); } @@ -1186,31 +1187,31 @@ private void rename(File legacyFile, File newFile) throws IOException { * Creates a hudson.PluginStrategy, looking at the corresponding system property. */ protected PluginStrategy createPluginStrategy() { - String strategyName = SystemProperties.getString(PluginStrategy.class.getName()); - if (strategyName != null) { - try { - Class klazz = getClass().getClassLoader().loadClass(strategyName); - Object strategy = klazz.getConstructor(PluginManager.class) - .newInstance(this); - if (strategy instanceof PluginStrategy) { - LOGGER.info("Plugin strategy: " + strategyName); - return (PluginStrategy) strategy; - } else { - LOGGER.warning("Plugin strategy (" + strategyName + - ") is not an instance of hudson.PluginStrategy"); - } - } catch (ClassNotFoundException e) { - LOGGER.warning("Plugin strategy class not found: " - + strategyName); - } catch (Exception e) { - LOGGER.log(WARNING, "Could not instantiate plugin strategy: " - + strategyName + ". Falling back to ClassicPluginStrategy", e); - } - LOGGER.info("Falling back to ClassicPluginStrategy"); - } - - // default and fallback - return new ClassicPluginStrategy(this); + String strategyName = SystemProperties.getString(PluginStrategy.class.getName()); + if (strategyName != null) { + try { + Class klazz = getClass().getClassLoader().loadClass(strategyName); + Object strategy = klazz.getConstructor(PluginManager.class) + .newInstance(this); + if (strategy instanceof PluginStrategy) { + LOGGER.info("Plugin strategy: " + strategyName); + return (PluginStrategy) strategy; + } else { + LOGGER.warning("Plugin strategy (" + strategyName + + ") is not an instance of hudson.PluginStrategy"); + } + } catch (ClassNotFoundException e) { + LOGGER.warning("Plugin strategy class not found: " + + strategyName); + } catch (Exception e) { + LOGGER.log(WARNING, "Could not instantiate plugin strategy: " + + strategyName + ". Falling back to ClassicPluginStrategy", e); + } + LOGGER.info("Falling back to ClassicPluginStrategy"); + } + + // default and fallback + return new ClassicPluginStrategy(this); } public PluginStrategy getPluginStrategy() { @@ -1246,7 +1247,7 @@ public List getFailedPlugins() { @CheckForNull public PluginWrapper getPlugin(String shortName) { for (PluginWrapper p : getPlugins()) { - if(p.getShortName().equals(shortName)) + if (p.getShortName().equals(shortName)) return p; } return null; @@ -1263,7 +1264,7 @@ public PluginWrapper getPlugin(String shortName) { @CheckForNull public PluginWrapper getPlugin(Class pluginClazz) { for (PluginWrapper p : getPlugins()) { - if(pluginClazz.isInstance(p.getPlugin())) + if (pluginClazz.isInstance(p.getPlugin())) return p; } return null; @@ -1278,7 +1279,7 @@ public PluginWrapper getPlugin(Class pluginClazz) { public List getPlugins(Class pluginSuperclass) { List result = new ArrayList<>(); for (PluginWrapper p : getPlugins()) { - if(pluginSuperclass.isInstance(p.getPlugin())) + if (pluginSuperclass.isInstance(p.getPlugin())) result.add(p); } return Collections.unmodifiableList(result); @@ -1310,7 +1311,7 @@ public Icon getSearchItemIcon() { * @deprecated Use {@link ServiceLoader} instead, or (more commonly) {@link ExtensionList}. */ @Deprecated - public Collection> discover( Class spi ) { + public Collection> discover(Class spi) { Set> result = new HashSet<>(); for (PluginWrapper p : activePlugins) { @@ -1329,8 +1330,8 @@ public PluginWrapper whichPlugin(Class c) { PluginWrapper oneAndOnly = null; ClassLoader cl = c.getClassLoader(); for (PluginWrapper p : activePlugins) { - if (p.classLoader==cl) { - if (oneAndOnly!=null) + if (p.classLoader == cl) { + if (oneAndOnly != null) return null; // ambiguous oneAndOnly = p; } @@ -1360,7 +1361,7 @@ public synchronized void stop() { public static boolean isNonMetaLabel(String label) { return !("adopt-this-plugin".equals(label) || "deprecated".equals(label)); } - + @Restricted(NoExternalUse.class) public HttpResponse doPluginsSearch(@QueryParameter String query, @QueryParameter Integer limit) { List plugins = new ArrayList<>(); @@ -1471,10 +1472,10 @@ public HttpResponse doPluginsSearch(@QueryParameter String query, @QueryParamete JSONArray mappedPlugins = new JSONArray(); mappedPlugins.addAll(plugins); - + return hudson.util.HttpResponses.okJSON(mappedPlugins); } - + /** * Get the list of all plugins - available and installed. * @return The list of all plugins - available and installed. @@ -1483,7 +1484,7 @@ public HttpResponse doPluginsSearch(@QueryParameter String query, @QueryParamete public HttpResponse doPlugins() { Jenkins.get().checkPermission(Jenkins.ADMINISTER); JSONArray response = new JSONArray(); - Map allPlugins = new HashMap<>(); + Map allPlugins = new HashMap<>(); for (PluginWrapper plugin : plugins) { JSONObject pluginInfo = new JSONObject(); pluginInfo.put("installed", true); @@ -1508,11 +1509,11 @@ public HttpResponse doPlugins() { response.add(pluginInfo); } for (UpdateSite site : Jenkins.get().getUpdateCenter().getSiteList()) { - for (UpdateSite.Plugin plugin: site.getAvailables()) { + for (UpdateSite.Plugin plugin : site.getAvailables()) { JSONObject pluginInfo = allPlugins.get(plugin.name); - if(pluginInfo == null) { - pluginInfo = new JSONObject(); - pluginInfo.put("installed", false); + if (pluginInfo == null) { + pluginInfo = new JSONObject(); + pluginInfo.put("installed", false); } pluginInfo.put("name", plugin.name); pluginInfo.put("title", plugin.getDisplayName()); @@ -1545,9 +1546,9 @@ public HttpResponse doUpdateSources(StaplerRequest req) throws IOException { return new HttpRedirect("./sites"); } - + /** - * Called to progress status beyond installing plugins, e.g. if + * Called to progress status beyond installing plugins, e.g. if * there were failures that prevented installation from naturally proceeding */ @RequirePOST @@ -1569,13 +1570,13 @@ public void doInstall(StaplerRequest req, StaplerResponse rsp) throws IOExceptio Enumeration en = req.getParameterNames(); while (en.hasMoreElements()) { String n = en.nextElement(); - if(n.startsWith("plugin.")) { + if (n.startsWith("plugin.")) { n = n.substring(7); plugins.add(n); } } - boolean dynamicLoad = req.getParameter("dynamicLoad")!=null; + boolean dynamicLoad = req.getParameter("dynamicLoad") != null; install(plugins, dynamicLoad); rsp.sendRedirect("../updateCenter/"); @@ -1664,7 +1665,7 @@ private List> install(@NonNull Collection jobFuture : installJobs) { - if(!jobFuture.isDone() && !jobFuture.isCancelled()) { + if (!jobFuture.isDone() && !jobFuture.isCancelled()) { continue INSTALLING; } UpdateCenter.UpdateCenterJob job = jobFuture.get(); - if(job instanceof InstallationJob && ((InstallationJob)job).status instanceof DownloadJob.Failure) { + if (job instanceof InstallationJob && ((InstallationJob) job).status instanceof DownloadJob.Failure) { failures = true; } } @@ -1708,7 +1709,7 @@ public void run() { break; } updateCenter.persistInstallStatus(); - if(!failures) { + if (!failures) { try (ACLContext acl = ACL.as2(currentAuth)) { InstallUtil.proceedToNextStateFrom(InstallState.INITIAL_PLUGINS_INSTALLING); } @@ -1750,7 +1751,7 @@ public HttpResponse doProxyConfigure(StaplerRequest req) throws IOException, Ser jenkins.checkPermission(Jenkins.ADMINISTER); ProxyConfiguration pc = req.bindJSON(ProxyConfiguration.class, req.getSubmittedForm()); - if (pc.name==null) { + if (pc.name == null) { jenkins.proxy = null; ProxyConfiguration.getXmlFile().delete(); } else { @@ -1762,6 +1763,7 @@ public HttpResponse doProxyConfigure(StaplerRequest req) throws IOException, Ser interface PluginCopier { void copy(File target) throws Exception; + void cleanup(); } @@ -1792,10 +1794,8 @@ static class UrlPluginCopier implements PluginCopier { @Override public void copy(File target) throws Exception { - try(InputStream input = ProxyConfiguration.getInputStream(new URL(url))) { + try (InputStream input = ProxyConfiguration.getInputStream(new URL(url))) { Files.copy(input, target.toPath()); - } catch(Exception e) { - throw e; } } @@ -1817,7 +1817,7 @@ public HttpResponse doUploadPlugin(StaplerRequest req) throws IOException, Servl PluginCopier copier; ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory()); List items = upload.parseRequest(req); - if(StringUtils.isNotBlank(items.get(1).getString())) { + if (StringUtils.isNotBlank(items.get(1).getString())) { // this is a URL deployment fileName = items.get(1).getString(); copier = new UrlPluginCopier(fileName); @@ -1828,11 +1828,11 @@ public HttpResponse doUploadPlugin(StaplerRequest req) throws IOException, Servl copier = new FileUploadPluginCopier(fileItem); } - if("".equals(fileName)){ + if ("".equals(fileName)) { return new HttpRedirect("advanced"); } // we allow the upload of the new jpi's and the legacy hpi's - if(!fileName.endsWith(".jpi") && !fileName.endsWith(".hpi")){ + if (!fileName.endsWith(".jpi") && !fileName.endsWith(".hpi")) { throw new Failure(hudson.model.Messages.Hudson_NotAPlugin(fileName)); } @@ -1873,7 +1873,7 @@ public HttpResponse doUploadPlugin(StaplerRequest req) throws IOException, Servl .element("optional", p.contains("resolution:=optional"))); } } - } catch(IOException e) { + } catch (IOException e) { LOGGER.log(WARNING, "Unable to setup dependency list for plugin upload", e); } @@ -1892,17 +1892,17 @@ public HttpResponse doUploadPlugin(StaplerRequest req) throws IOException, Servl @Restricted(NoExternalUse.class) @RequirePOST public FormValidation doCheckPluginUrl(StaplerRequest request, @QueryParameter String value) throws IOException { - if(StringUtils.isNotBlank(value)) { + if (StringUtils.isNotBlank(value)) { try { URL url = new URL(value); - if(!url.getProtocol().startsWith("http")) { + if (!url.getProtocol().startsWith("http")) { return FormValidation.error(Messages.PluginManager_invalidUrl()); } - if(!url.getProtocol().equals("https")) { + if (!url.getProtocol().equals("https")) { return FormValidation.warning(Messages.PluginManager_insecureUrl()); } - } catch(MalformedURLException e) { + } catch (MalformedURLException e) { return FormValidation.error(e.getMessage()); } } @@ -1934,7 +1934,7 @@ public HttpResponse doUploadPlugin(StaplerRequest req) throws IOException, Servl .withDuringActionExceptions(new Class[] {Exception.class}) // what we do with a failed attempt due to an allowed exception, return an FormValidation.error with the message - .withDuringActionExceptionListener( (attempt, e) -> FormValidation.errorWithMarkup(e.getClass().getSimpleName() + ": " + e.getLocalizedMessage())) + .withDuringActionExceptionListener((attempt, e) -> FormValidation.errorWithMarkup(e.getClass().getSimpleName() + ": " + e.getLocalizedMessage())) // lets get our retrier object .build(); @@ -2001,7 +2001,7 @@ protected String identifyPluginShortName(File t) { if (name != null) return name; } } catch (IOException e) { - LOGGER.log(WARNING, "Failed to identify the short name from "+t,e); + LOGGER.log(WARNING, "Failed to identify the short name from " + t, e); } return FilenameUtils.getBaseName(t.getName()); // fall back to the base name of what's uploaded } @@ -2033,7 +2033,7 @@ public List> prevalidateConfig(InputStream List> jobs = new ArrayList<>(); UpdateCenter uc = Jenkins.get().getUpdateCenter(); // TODO call uc.updateAllSites() when available? perhaps not, since we should not block on network here - for (Map.Entry requestedPlugin : parseRequestedPlugins(configXml).entrySet()) { + for (Map.Entry requestedPlugin : parseRequestedPlugins(configXml).entrySet()) { PluginWrapper pw = getPlugin(requestedPlugin.getKey()); if (pw == null) { // install new UpdateSite.Plugin toInstall = uc.getPlugin(requestedPlugin.getKey(), requestedPlugin.getValue()); @@ -2091,7 +2091,7 @@ public JSONArray doPrevalidateConfig(StaplerRequest req) throws IOException { JSONArray response = new JSONArray(); - for (Map.Entry p : parseRequestedPlugins(req.getInputStream()).entrySet()) { + for (Map.Entry p : parseRequestedPlugins(req.getInputStream()).entrySet()) { PluginWrapper pw = getPlugin(p.getKey()); JSONObject j = new JSONObject() .accumulate("name", p.getKey()) @@ -2119,8 +2119,8 @@ public HttpResponse doInstallNecessaryPlugins(StaplerRequest req) throws IOExcep /** * Parses configuration XML files and picks up references to XML files. */ - public Map parseRequestedPlugins(InputStream configXml) throws IOException { - final Map requestedPlugins = new TreeMap<>(); + public Map parseRequestedPlugins(InputStream configXml) throws IOException { + final Map requestedPlugins = new TreeMap<>(); try { SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); @@ -2150,7 +2150,7 @@ public Map parseRequestedPlugins(InputStream configXml) th }); } catch (SAXException x) { - throw new IOException("Failed to parse XML",x); + throw new IOException("Failed to parse XML", x); } catch (ParserConfigurationException e) { throw new AssertionError(e); // impossible since we don't tweak XMLParser } @@ -2190,6 +2190,7 @@ public MetadataCache createCache() { @Restricted(NoExternalUse.class) // table.jelly public static final class MetadataCache { private final Map data = new HashMap<>(); + public T of(String key, Class type, Supplier func) { return type.cast(data.computeIfAbsent(key, _ignored -> func.get())); } @@ -2272,16 +2273,17 @@ public String toString() { return "classLoader " + getClass().getName(); } } + @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "for script console") - public static boolean FAST_LOOKUP = !SystemProperties.getBoolean(PluginManager.class.getName()+".noFastLookup"); + public static boolean FAST_LOOKUP = !SystemProperties.getBoolean(PluginManager.class.getName() + ".noFastLookup"); /** @deprecated in Jenkins 2.222 use {@link Jenkins#ADMINISTER} instead */ @Deprecated - public static final Permission UPLOAD_PLUGINS = new Permission(Jenkins.PERMISSIONS, "UploadPlugins", Messages._PluginManager_UploadPluginsPermission_Description(),Jenkins.ADMINISTER,PermissionScope.JENKINS); + public static final Permission UPLOAD_PLUGINS = new Permission(Jenkins.PERMISSIONS, "UploadPlugins", Messages._PluginManager_UploadPluginsPermission_Description(), Jenkins.ADMINISTER, PermissionScope.JENKINS); /** @deprecated in Jenkins 2.222 use {@link Jenkins#ADMINISTER} instead */ @Deprecated - public static final Permission CONFIGURE_UPDATECENTER = new Permission(Jenkins.PERMISSIONS, "ConfigureUpdateCenter", Messages._PluginManager_ConfigureUpdateCenterPermission_Description(),Jenkins.ADMINISTER,PermissionScope.JENKINS); + public static final Permission CONFIGURE_UPDATECENTER = new Permission(Jenkins.PERMISSIONS, "ConfigureUpdateCenter", Messages._PluginManager_ConfigureUpdateCenterPermission_Description(), Jenkins.ADMINISTER, PermissionScope.JENKINS); /** * Remembers why a plugin failed to deploy. @@ -2319,7 +2321,7 @@ public String getExceptionString() { * Stores {@link Plugin} instances. */ /*package*/ static final class PluginInstanceStore { - final Map store = new ConcurrentHashMap<>(); + final Map store = new ConcurrentHashMap<>(); } /** @@ -2339,10 +2341,10 @@ public String getDisplayName() { @Override public boolean isActivated() { - if(pluginsWithCycle == null){ + if (pluginsWithCycle == null) { pluginsWithCycle = new ArrayList<>(); for (PluginWrapper p : Jenkins.get().getPluginManager().getPlugins()) { - if(p.hasCycleDependency()){ + if (p.hasCycleDependency()) { pluginsWithCycle.add(p); isActive = true; } @@ -2380,10 +2382,10 @@ public static PluginUpdateMonitor getInstance() { * @param requiredVersion the lowest version which is OK (e.g. 2.2.2) * @param message the message to show (plain text) */ - public void ifPluginOlderThenReport(String pluginName, String requiredVersion, String message){ + public void ifPluginOlderThenReport(String pluginName, String requiredVersion, String message) { Plugin plugin = Jenkins.get().getPlugin(pluginName); - if(plugin != null){ - if(plugin.getWrapper().getVersionNumber().isOlderThan(new VersionNumber(requiredVersion))) { + if (plugin != null) { + if (plugin.getWrapper().getVersionNumber().isOlderThan(new VersionNumber(requiredVersion))) { pluginsToBeUpdated.put(pluginName, new PluginUpdateInfo(pluginName, message)); } } @@ -2415,6 +2417,7 @@ public Collection getPluginsToBeUpdated() { public static class PluginUpdateInfo { public final String pluginName; public final String message; + private PluginUpdateInfo(String pluginName, String message) { this.pluginName = pluginName; this.message = message; diff --git a/core/src/main/java/hudson/PluginStrategy.java b/core/src/main/java/hudson/PluginStrategy.java index 5dfc8136573aa..2b237931c038e 100644 --- a/core/src/main/java/hudson/PluginStrategy.java +++ b/core/src/main/java/hudson/PluginStrategy.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import edu.umd.cs.findbugs.annotations.NonNull; @@ -43,13 +44,13 @@ */ public interface PluginStrategy extends ExtensionPoint { - /** - * Creates a plugin wrapper, which provides a management interface for the plugin - * @param archive + /** + * Creates a plugin wrapper, which provides a management interface for the plugin + * @param archive * Either a directory that points to a pre-exploded plugin, or an jpi file, or an jpl file. - */ - PluginWrapper createPluginWrapper(File archive) - throws IOException; + */ + PluginWrapper createPluginWrapper(File archive) + throws IOException; /** * Finds the plugin name without actually unpacking anything {@link #createPluginWrapper} would. @@ -58,32 +59,32 @@ PluginWrapper createPluginWrapper(File archive) */ @NonNull String getShortName(File archive) throws IOException; - /** - * Loads the plugin and starts it. - * - *

- * This should be done after all the classloaders are constructed for all - * the plugins, so that dependencies can be properly loaded by plugins. - */ - void load(PluginWrapper wrapper) throws IOException; + /** + * Loads the plugin and starts it. + * + *

+ * This should be done after all the classloaders are constructed for all + * the plugins, so that dependencies can be properly loaded by plugins. + */ + void load(PluginWrapper wrapper) throws IOException; - /** - * Optionally start services provided by the plugin. Should be called - * when all plugins are loaded. - */ - void initializeComponents(PluginWrapper plugin); + /** + * Optionally start services provided by the plugin. Should be called + * when all plugins are loaded. + */ + void initializeComponents(PluginWrapper plugin); - /** - * Find components of the given type using the assigned strategy. - * - * + /** + * Find components of the given type using the assigned strategy. + * + * * @param type The component type * @param hudson The Hudson scope * @return Sequence of components - * @since 1.400 - */ - List> findComponents(Class type, Hudson hudson); - + * @since 1.400 + */ + List> findComponents(Class type, Hudson hudson); + /** * Called when a plugin is installed, but there was already a plugin installed which optionally depended on that plugin. * The class loader of the existing depending plugin should be updated diff --git a/core/src/main/java/hudson/PluginWrapper.java b/core/src/main/java/hudson/PluginWrapper.java index a04ad5188f65b..a42596726cdbd 100644 --- a/core/src/main/java/hudson/PluginWrapper.java +++ b/core/src/main/java/hudson/PluginWrapper.java @@ -1,19 +1,19 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, * Yahoo! Inc., Erik Ramfelt, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import static hudson.PluginWrapper.PluginDisableStatus.ALREADY_DISABLED; @@ -118,7 +119,7 @@ public class PluginWrapper implements Comparable, ModelObject { * A plugin won't be loaded unless his declared dependencies are present and match the required minimal version. * This can be set to false to disable the version check (legacy behaviour) */ - private static final boolean ENABLE_PLUGIN_DEPENDENCIES_VERSION_CHECK = Boolean.parseBoolean(System.getProperty(PluginWrapper.class.getName()+"." + "dependenciesVersionCheck.enabled", "true")); + private static final boolean ENABLE_PLUGIN_DEPENDENCIES_VERSION_CHECK = Boolean.parseBoolean(System.getProperty(PluginWrapper.class.getName() + "." + "dependenciesVersionCheck.enabled", "true")); /** * {@link PluginManager} to which this belongs to. @@ -168,7 +169,7 @@ public class PluginWrapper implements Comparable, ModelObject { * The snapshot of {@code disableFile.exists()} as of the start up. */ private final boolean active; - + private boolean hasCycleDependency = false; private final List dependencies; @@ -384,11 +385,11 @@ public boolean isDeprecated() { /** * Inject the specified jar file(s) to the plugins classpath. *

Warning: This is advanced usage that you should not be needed in 99.9% of all cases, any jar insertion - * should happen early into the plugins lifecycle to prevent classloading issues in dependent plugins. + * should happen early into the plugins lifecycle to prevent classloading issues in dependent plugins. *

* Rather than use this functionality it is to have co-operative behaviour between any consumer of the libraries and load the classes in a separate {@link ClassLoader}. * you can expose third-party libraries from a dynamic location in various ways, such as: - * + * *

    *
  • You could split your plugin into two modules: *
      @@ -409,7 +410,7 @@ public boolean isDeprecated() { * For a concrete example see the database * plugin. * - * + * * @throws Exception if the File could not be inserted into the classpath for some reason. * @since 2.313 */ @@ -442,10 +443,10 @@ public static final class Dependency { public Dependency(String s) { int idx = s.indexOf(':'); - if(idx==-1) - throw new IllegalArgumentException("Illegal dependency specifier "+s); - this.shortName = Util.intern(s.substring(0,idx)); - String version = Util.intern(s.substring(idx+1)); + if (idx == -1) + throw new IllegalArgumentException("Illegal dependency specifier " + s); + this.shortName = Util.intern(s.substring(0, idx)); + String version = Util.intern(s.substring(idx + 1)); boolean isOptional = false; String[] osgiProperties = version.split("[;]"); @@ -467,35 +468,35 @@ public Dependency(String s) { @Override public String toString() { return shortName + " (" + version + ")" + (optional ? " optional" : ""); - } + } } /** * @param archive * A .jpi archive file jar file, or a .jpl linked plugin. * @param manifest - * The manifest for the plugin + * The manifest for the plugin * @param baseResourceURL - * A URL pointing to the resources for this plugin + * A URL pointing to the resources for this plugin * @param classLoader - * a classloader that loads classes from this plugin and its dependencies + * a classloader that loads classes from this plugin and its dependencies * @param disableFile - * if this file exists on startup, the plugin will not be activated + * if this file exists on startup, the plugin will not be activated * @param dependencies a list of mandatory dependencies * @param optionalDependencies a list of optional dependencies */ - public PluginWrapper(PluginManager parent, File archive, Manifest manifest, URL baseResourceURL, - ClassLoader classLoader, File disableFile, - List dependencies, List optionalDependencies) { + public PluginWrapper(PluginManager parent, File archive, Manifest manifest, URL baseResourceURL, + ClassLoader classLoader, File disableFile, + List dependencies, List optionalDependencies) { this.parent = parent; - this.manifest = manifest; - this.shortName = Util.intern(computeShortName(manifest, archive.getName())); - this.baseResourceURL = baseResourceURL; - this.classLoader = classLoader; - this.disableFile = disableFile; - this.active = !disableFile.exists(); - this.dependencies = dependencies; - this.optionalDependencies = optionalDependencies; + this.manifest = manifest; + this.shortName = Util.intern(computeShortName(manifest, archive.getName())); + this.baseResourceURL = baseResourceURL; + this.classLoader = classLoader; + this.disableFile = disableFile; + this.active = !disableFile.exists(); + this.dependencies = dependencies; + this.optionalDependencies = optionalDependencies; for (Dependency d : optionalDependencies) { assert d.optional : d + " included among optionalDependencies of " + shortName + " but was not marked optional"; } @@ -533,11 +534,11 @@ static String computeShortName(Manifest manifest, String fileName) { // use the name captured in the manifest, as often plugins // depend on the specific short name in its URLs. String n = manifest.getMainAttributes().getValue("Short-Name"); - if(n!=null) return n; + if (n != null) return n; // maven seems to put this automatically, so good fallback to check. n = manifest.getMainAttributes().getValue("Extension-Name"); - if(n!=null) return n; + if (n != null) return n; // otherwise infer from the file name, since older plugins don't have // this entry. @@ -608,7 +609,7 @@ public String getUrl() { List siteMetadataList = getInfoFromAllSites(); String firstSiteUrl = null; if (!siteMetadataList.isEmpty()) { - firstSiteUrl = siteMetadataList.get(0).wiki; + firstSiteUrl = siteMetadataList.get(0).wiki; if (allUrlsMatch(firstSiteUrl, siteMetadataList)) { return firstSiteUrl; } @@ -618,7 +619,7 @@ public String getUrl() { // use manifest (since maven-hpi-plugin 1.30) String url = manifest.getMainAttributes().getValue("Url"); if (url != null) { - return url; + return url; } return firstSiteUrl; } @@ -627,7 +628,7 @@ private boolean allUrlsMatch(String url, List uiList) { return uiList.stream().allMatch(k -> k.wiki != null && k.wiki.equals(url)); } - @Override + @Override public String toString() { return "Plugin:" + getShortName(); } @@ -641,7 +642,7 @@ public String toString() { @Deprecated public String getLongName() { String name = manifest.getMainAttributes().getValue("Long-Name"); - if(name!=null) return name; + if (name != null) return name; return shortName; } @@ -651,7 +652,7 @@ public String getLongName() { @Exported public YesNoMaybe supportsDynamicLoad() { String v = manifest.getMainAttributes().getValue("Support-Dynamic-Loading"); - if (v==null) return YesNoMaybe.MAYBE; + if (v == null) return YesNoMaybe.MAYBE; return Boolean.parseBoolean(v) ? YesNoMaybe.YES : YesNoMaybe.NO; } @@ -665,11 +666,11 @@ public String getVersion() { private String getVersionOf(Manifest manifest) { String v = manifest.getMainAttributes().getValue("Plugin-Version"); - if(v!=null) return v; + if (v != null) return v; // plugins generated before maven-hpi-plugin 1.3 should still have this attribute v = manifest.getMainAttributes().getValue("Implementation-Version"); - if(v!=null) return v; + if (v != null) return v; return "???"; } @@ -682,10 +683,10 @@ private String getVersionOf(Manifest manifest) { @Exported public @CheckForNull String getRequiredCoreVersion() { String v = manifest.getMainAttributes().getValue("Jenkins-Version"); - if (v!= null) return v; + if (v != null) return v; v = manifest.getMainAttributes().getValue("Hudson-Version"); - if (v!= null) return v; + if (v != null) return v; return null; } @@ -718,7 +719,7 @@ public boolean isOlderThan(VersionNumber v) { return getVersionNumber().compareTo(v) < 0; } catch (IllegalArgumentException e) { // if we can't figure out our current version, it probably means it's very old, - // since the version information is missing only from the very old plugins + // since the version information is missing only from the very old plugins return true; } } @@ -748,7 +749,7 @@ public void releaseClassLoader() { try { ((Closeable) classLoader).close(); } catch (IOException e) { - LOGGER.log(WARNING, "Failed to shut down classloader",e); + LOGGER.log(WARNING, "Failed to shut down classloader", e); } } @@ -760,8 +761,8 @@ public void enable() throws IOException { LOGGER.log(Level.FINEST, "Plugin {0} has been already enabled. Skipping the enable() operation", getShortName()); return; } - if(!disableFile.delete()) - throw new IOException("Failed to delete "+disableFile); + if (!disableFile.delete()) + throw new IOException("Failed to delete " + disableFile); } /** @@ -889,12 +890,12 @@ private Set dependentsToCheck(PluginDisableStrategy strategy) { public boolean isActive() { return active && !hasCycleDependency(); } - - public boolean hasCycleDependency(){ + + public boolean hasCycleDependency() { return hasCycleDependency; } - public void setHasCycleDependency(boolean hasCycle){ + public void setHasCycleDependency(boolean hasCycle) { hasCycleDependency = hasCycle; } @@ -922,7 +923,7 @@ public Manifest getManifest() { } public void setPlugin(Plugin plugin) { - Jenkins.lookup(PluginInstanceStore.class).store.put(this,plugin); + Jenkins.lookup(PluginInstanceStore.class).store.put(this, plugin); plugin.wrapper = this; } @@ -932,7 +933,7 @@ public String getPluginClass() { public boolean hasLicensesXml() { try { - new URL(baseResourceURL,"WEB-INF/licenses.xml").openStream().close(); + new URL(baseResourceURL, "WEB-INF/licenses.xml").openStream().close(); return true; } catch (IOException e) { return false; @@ -972,7 +973,7 @@ public boolean hasLicensesXml() { if (dependency == null) { PluginWrapper failedDependency = NOTICE.getPlugin(d.shortName); if (failedDependency != null) { - dependencyErrors.put(Messages.PluginWrapper_failed_to_load_dependency(failedDependency.getLongName(), failedDependency.getVersion()), true); + dependencyErrors.put(Messages.PluginWrapper_failed_to_load_dependency_2(failedDependency.getLongName(), failedDependency.getShortName(), failedDependency.getVersion()), true); break; } else { dependencyErrors.put(Messages.PluginWrapper_missing(d.shortName, d.version), false); @@ -980,13 +981,13 @@ public boolean hasLicensesXml() { } else { if (dependency.isActive()) { if (isDependencyObsolete(d, dependency)) { - versionDependencyError(Messages.PluginWrapper_obsolete(dependency.getLongName(), dependency.getVersion(), d.version), dependency.getVersion(), d.version); + versionDependencyError(Messages.PluginWrapper_obsolete_2(dependency.getLongName(), dependency.getShortName(), dependency.getVersion(), d.version), dependency.getVersion(), d.version); } } else { if (isDependencyObsolete(d, dependency)) { - versionDependencyError(Messages.PluginWrapper_disabledAndObsolete(dependency.getLongName(), dependency.getVersion(), d.version), dependency.getVersion(), d.version); + versionDependencyError(Messages.PluginWrapper_obsolete_2(dependency.getLongName(), dependency.getShortName(), dependency.getVersion(), d.version), dependency.getVersion(), d.version); } else { - dependencyErrors.put(Messages.PluginWrapper_disabled(dependency.getLongName()), false); + dependencyErrors.put(Messages.PluginWrapper_disabled_2(dependency.getLongName(), dependency.getShortName()), false); } } @@ -997,7 +998,7 @@ public boolean hasLicensesXml() { PluginWrapper dependency = parent.getPlugin(d.shortName); if (dependency != null && dependency.isActive()) { if (isDependencyObsolete(d, dependency)) { - versionDependencyError(Messages.PluginWrapper_obsolete(dependency.getLongName(), dependency.getVersion(), d.version), dependency.getVersion(), d.version); + versionDependencyError(Messages.PluginWrapper_obsolete_2(dependency.getLongName(), dependency.getShortName(), dependency.getVersion(), d.version), dependency.getVersion(), d.version); } else { dependencies.add(d); } @@ -1006,7 +1007,7 @@ public boolean hasLicensesXml() { if (!dependencyErrors.isEmpty()) { NOTICE.addPlugin(this); StringBuilder messageBuilder = new StringBuilder(); - messageBuilder.append(Messages.PluginWrapper_failed_to_load_plugin(getLongName(), getVersion())).append(System.lineSeparator()); + messageBuilder.append(Messages.PluginWrapper_failed_to_load_plugin_2(getLongName(), getShortName(), getVersion())).append(System.lineSeparator()); for (Iterator iterator = dependencyErrors.keySet().iterator(); iterator.hasNext(); ) { String dependencyError = iterator.next(); messageBuilder.append(" - ").append(dependencyError); @@ -1029,7 +1030,7 @@ private boolean isDependencyObsolete(Dependency d, PluginWrapper dependency) { */ private void versionDependencyError(String message, String actual, String minimum) { if (isSnapshot(actual) || isSnapshot(minimum)) { - LOGGER.log(WARNING, "Suppressing dependency error in {0} v{1}: {2}", new Object[] {getLongName(), getVersion(), message}); + LOGGER.log(WARNING, "Suppressing dependency error in {0} v{1}: {2}", new Object[] {getShortName(), getVersion(), message}); } else { dependencyErrors.put(message, false); } @@ -1053,10 +1054,10 @@ static boolean isSnapshot(@NonNull String version) { public UpdateSite.Plugin getUpdateInfo() { UpdateCenter uc = Jenkins.get().getUpdateCenter(); UpdateSite.Plugin p = uc.getPlugin(getShortName(), getVersionNumber()); - if(p!=null && p.isNewerThan(getVersion())) return p; + if (p != null && p.isNewerThan(getVersion())) return p; return null; } - + /** * returns the {@link hudson.model.UpdateSite.Plugin} object, or null. */ @@ -1081,9 +1082,9 @@ private List getInfoFromAllSites() { */ @Exported public boolean hasUpdate() { - return getUpdateInfo()!=null; + return getUpdateInfo() != null; } - + @Exported @Deprecated // See https://groups.google.com/d/msg/jenkinsci-dev/kRobm-cxFw8/6V66uhibAwAJ public boolean isPinned() { @@ -1165,7 +1166,7 @@ public boolean isDowngradable() { * Where is the backup file? */ public File getBackupFile() { - return new File(Jenkins.get().getRootDir(),"plugins/"+getShortName() + ".bak"); + return new File(Jenkins.get().getRootDir(), "plugins/" + getShortName() + ".bak"); } /** @@ -1238,8 +1239,8 @@ public PluginWrapper getPlugin(String shortName) { * Depending on whether the user said "dismiss" or "correct", send him to the right place. */ public void doAct(StaplerRequest req, StaplerResponse rsp) throws IOException { - if(req.hasParameter("correct")) { - rsp.sendRedirect(req.getContextPath()+"/pluginManager"); + if (req.hasParameter("correct")) { + rsp.sendRedirect(req.getContextPath() + "/pluginManager"); } } @@ -1376,7 +1377,7 @@ public HttpResponse doUnpin() throws IOException { @RequirePOST public HttpResponse doDoUninstall() throws IOException { Jenkins jenkins = Jenkins.get(); - + jenkins.checkPermission(Jenkins.ADMINISTER); Files.deleteIfExists(Util.fileToPath(archive)); diff --git a/core/src/main/java/hudson/Proc.java b/core/src/main/java/hudson/Proc.java index dd94d2097c396..6bcb6d416819a 100644 --- a/core/src/main/java/hudson/Proc.java +++ b/core/src/main/java/hudson/Proc.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, CloudBees, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -39,6 +40,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.charset.Charset; import java.util.Locale; import java.util.Map; import java.util.concurrent.CancellationException; @@ -140,7 +142,7 @@ protected Proc() {} public abstract OutputStream getStdin(); private static final ExecutorService executor = Executors.newCachedThreadPool(new ExceptionCatchingThreadFactory(new NamingThreadFactory(new ClassLoaderSanityThreadFactory(new DaemonThreadFactory()), "Proc.executor"))); - + /** * Like {@link #join} but can be given a maximum time to wait. * @param timeout number of time units @@ -174,42 +176,42 @@ public void run() { latch.countDown(); } } - + /** * Locally launched process. */ public static final class LocalProc extends Proc { private final Process proc; - private final Thread copier,copier2; + private final Thread copier, copier2; private final OutputStream out; private final EnvVars cookie; private final String name; - private final InputStream stdout,stderr; + private final InputStream stdout, stderr; private final OutputStream stdin; - public LocalProc(String cmd, Map env, OutputStream out, File workDir) throws IOException { - this(cmd,Util.mapToEnv(env),out,workDir); + public LocalProc(String cmd, Map env, OutputStream out, File workDir) throws IOException { + this(cmd, Util.mapToEnv(env), out, workDir); } - public LocalProc(String[] cmd, Map env,InputStream in, OutputStream out) throws IOException { - this(cmd,Util.mapToEnv(env),in,out); + public LocalProc(String[] cmd, Map env, InputStream in, OutputStream out) throws IOException { + this(cmd, Util.mapToEnv(env), in, out); } - public LocalProc(String cmd,String[] env,OutputStream out, File workDir) throws IOException { - this( Util.tokenize(cmd), env, out, workDir ); + public LocalProc(String cmd, String[] env, OutputStream out, File workDir) throws IOException { + this(Util.tokenize(cmd), env, out, workDir); } - public LocalProc(String[] cmd,String[] env,OutputStream out, File workDir) throws IOException { - this(cmd,env,null,out,workDir); + public LocalProc(String[] cmd, String[] env, OutputStream out, File workDir) throws IOException { + this(cmd, env, null, out, workDir); } - public LocalProc(String[] cmd,String[] env,InputStream in,OutputStream out) throws IOException { - this(cmd,env,in,out,null); + public LocalProc(String[] cmd, String[] env, InputStream in, OutputStream out) throws IOException { + this(cmd, env, in, out, null); } - public LocalProc(String[] cmd,String[] env,InputStream in,OutputStream out, File workDir) throws IOException { - this(cmd,env,in,out,null,workDir); + public LocalProc(String[] cmd, String[] env, InputStream in, OutputStream out, File workDir) throws IOException { + this(cmd, env, in, out, null, workDir); } /** @@ -217,30 +219,30 @@ public LocalProc(String[] cmd,String[] env,InputStream in,OutputStream out, File * null to redirect stderr to stdout. */ @SuppressFBWarnings(value = "COMMAND_INJECTION", justification = "Command injection is the point of this old, barely used class.") - public LocalProc(String[] cmd,String[] env,InputStream in,OutputStream out,OutputStream err,File workDir) throws IOException { - this( calcName(cmd), - stderr(environment(new ProcessBuilder(cmd),env).directory(workDir), err==null || err== SELFPUMP_OUTPUT), - in, out, err ); + public LocalProc(String[] cmd, String[] env, InputStream in, OutputStream out, OutputStream err, File workDir) throws IOException { + this(calcName(cmd), + stderr(environment(new ProcessBuilder(cmd), env).directory(workDir), err == null || err == SELFPUMP_OUTPUT), + in, out, err); } private static ProcessBuilder stderr(ProcessBuilder pb, boolean redirectError) { - if(redirectError) pb.redirectErrorStream(true); + if (redirectError) pb.redirectErrorStream(true); return pb; } private static ProcessBuilder environment(ProcessBuilder pb, String[] env) { - if(env!=null) { + if (env != null) { Map m = pb.environment(); m.clear(); for (String e : env) { int idx = e.indexOf('='); - m.put(e.substring(0,idx),e.substring(idx+1)); + m.put(e.substring(0, idx), e.substring(idx + 1)); } } return pb; } - private LocalProc( String name, ProcessBuilder procBuilder, InputStream in, OutputStream out, OutputStream err ) throws IOException { + private LocalProc(String name, ProcessBuilder procBuilder, InputStream in, OutputStream out, OutputStream err) throws IOException { Logger.getLogger(Proc.class.getName()).log(Level.FINE, "Running: {0}", name); this.name = name; this.out = out; @@ -252,11 +254,11 @@ private LocalProc( String name, ProcessBuilder procBuilder, InputStream in, Outp this.proc = procBuilder.start(); InputStream procInputStream = proc.getInputStream(); - if (out==SELFPUMP_OUTPUT) { + if (out == SELFPUMP_OUTPUT) { stdout = procInputStream; copier = null; } else { - copier = new StreamCopyThread(name+": stdout copier", procInputStream, out); + copier = new StreamCopyThread(name + ": stdout copier", procInputStream, out); copier.start(); stdout = null; } @@ -266,21 +268,21 @@ private LocalProc( String name, ProcessBuilder procBuilder, InputStream in, Outp stdin = null; proc.getOutputStream().close(); } else - if (in==SELFPUMP_INPUT) { + if (in == SELFPUMP_INPUT) { stdin = proc.getOutputStream(); } else { - new StdinCopyThread(name+": stdin copier",in,proc.getOutputStream()).start(); + new StdinCopyThread(name + ": stdin copier", in, proc.getOutputStream()).start(); stdin = null; } InputStream procErrorStream = proc.getErrorStream(); - if(err!=null) { - if (err==SELFPUMP_OUTPUT) { + if (err != null) { + if (err == SELFPUMP_OUTPUT) { stderr = procErrorStream; copier2 = null; } else { stderr = null; - copier2 = new StreamCopyThread(name+": stderr copier", procErrorStream, err); + copier2 = new StreamCopyThread(name + ": stderr copier", procErrorStream, err); copier2.start(); } } else { @@ -289,7 +291,7 @@ private LocalProc( String name, ProcessBuilder procBuilder, InputStream in, Outp // according to the source code, Sun JREs still still returns a distinct reader end of a pipe that needs to be closed. // but apparently at least on some IBM JDK5, returned input and error streams are the same. // so try to close them smartly - if (procErrorStream!=procInputStream) { + if (procErrorStream != procInputStream) { procErrorStream.close(); } copier2 = null; @@ -318,12 +320,12 @@ public OutputStream getStdin() { @Override public int join() throws InterruptedException, IOException { // show what we are waiting for in the thread title - // since this involves some native work, let's have some soak period before enabling this by default + // since this involves some native work, let's have some soak period before enabling this by default Thread t = Thread.currentThread(); String oldName = t.getName(); if (SHOW_PID) { ProcessTree.OSProcess p = ProcessTree.get().get(proc); - t.setName(oldName+" "+(p!=null?"waiting for pid="+p.getPid():"waiting for "+name)); + t.setName(oldName + " " + (p != null ? "waiting for pid=" + p.getPid() : "waiting for " + name)); } try { @@ -331,14 +333,14 @@ public int join() throws InterruptedException, IOException { // see https://www.jenkins.io/redirect/troubleshooting/process-leaked-file-descriptors // problems like that shows up as infinite wait in join(), which confuses great many users. // So let's do a timed wait here and try to diagnose the problem - if (copier!=null) copier.join(TimeUnit.SECONDS.toMillis(10)); - if(copier2!=null) copier2.join(TimeUnit.SECONDS.toMillis(10)); - if((copier!=null && copier.isAlive()) || (copier2!=null && copier2.isAlive())) { + if (copier != null) copier.join(TimeUnit.SECONDS.toMillis(10)); + if (copier2 != null) copier2.join(TimeUnit.SECONDS.toMillis(10)); + if ((copier != null && copier.isAlive()) || (copier2 != null && copier2.isAlive())) { // looks like handles are leaking. // closing these handles should terminate the threads. String msg = "Process leaked file descriptors. See https://www.jenkins.io/redirect/troubleshooting/process-leaked-file-descriptors for more information"; Throwable e = new Exception().fillInStackTrace(); - LOGGER.log(Level.WARNING,msg,e); + LOGGER.log(Level.WARNING, msg, e); // doing proc.getInputStream().close() hangs in FileInputStream.close0() // it could be either because another thread is blocking on read, or @@ -354,7 +356,7 @@ public int join() throws InterruptedException, IOException { // } catch (IOException x) { // LOGGER.log(Level.FINE,"stderr termination failed",x); // } - out.write(msg.getBytes()); + out.write(msg.getBytes(Charset.defaultCharset())); out.write('\n'); } return r; @@ -387,7 +389,7 @@ public void kill() throws InterruptedException, IOException { * Destroys the child process without join. */ private void destroy() throws InterruptedException { - ProcessTree.get().killAll(proc,cookie); + ProcessTree.get().killAll(proc, cookie); } /** @@ -466,9 +468,9 @@ public int join() throws IOException, InterruptedException { kill(); throw e; } catch (ExecutionException e) { - if(e.getCause() instanceof IOException) - throw (IOException)e.getCause(); - throw new IOException("Failed to join the process",e); + if (e.getCause() instanceof IOException) + throw (IOException) e.getCause(); + throw new IOException("Failed to join the process", e); } catch (CancellationException x) { return -1; } finally { @@ -505,7 +507,7 @@ public OutputStream getStdin() { */ @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "for debugging") public static boolean SHOW_PID = false; - + /** * An instance of {@link Proc}, which has an internal workaround for JENKINS-23271. * It presumes that the instance of the object is guaranteed to be used after the {@link Proc#join()} call. diff --git a/core/src/main/java/hudson/ProxyConfiguration.java b/core/src/main/java/hudson/ProxyConfiguration.java index cecd40f979a0f..c087c00ceb8c8 100644 --- a/core/src/main/java/hudson/ProxyConfiguration.java +++ b/core/src/main/java/hudson/ProxyConfiguration.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import com.thoughtworks.xstream.XStream; @@ -89,8 +90,8 @@ public final class ProxyConfiguration extends AbstractDescribableImpl getNoProxyHostPatterns(String noProxyHost) { - if (noProxyHost==null) return Collections.emptyList(); + if (noProxyHost == null) return Collections.emptyList(); List r = new ArrayList<>(); for (String s : noProxyHost.split("[ \t\n,|]+")) { - if (s.length()==0) continue; + if (s.length() == 0) continue; r.add(Pattern.compile(s.replace(".", "\\.").replace("*", ".*"))); } return r; @@ -257,18 +258,18 @@ public Proxy createProxy(String host) { } public static Proxy createProxy(String host, String name, int port, String noProxyHost) { - if (host!=null && noProxyHost!=null) { + if (host != null && noProxyHost != null) { for (Pattern p : getNoProxyHostPatterns(noProxyHost)) { if (p.matcher(host).matches()) return Proxy.NO_PROXY; } } - return new Proxy(Proxy.Type.HTTP, new InetSocketAddress(name,port)); + return new Proxy(Proxy.Type.HTTP, new InetSocketAddress(name, port)); } @Override public void save() throws IOException { - if(BulkChange.contains(this)) return; + if (BulkChange.contains(this)) return; XmlFile config = getXmlFile(); config.write(this); SaveableListener.fireOnChange(this, config); @@ -289,7 +290,7 @@ public static XmlFile getXmlFile() { public static ProxyConfiguration load() throws IOException { XmlFile f = getXmlFile(); - if(f.exists()) + if (f.exists()) return (ProxyConfiguration) f.read(); else return null; @@ -300,24 +301,24 @@ public static ProxyConfiguration load() throws IOException { */ public static URLConnection open(URL url) throws IOException { final ProxyConfiguration p = get(); - + URLConnection con; - if(p==null) { + if (p == null) { con = url.openConnection(); } else { Proxy proxy = p.createProxy(url.getHost()); con = url.openConnection(proxy); - if(p.getUserName()!=null) { + if (p.getUserName() != null) { // Add an authenticator which provides the credentials for proxy authentication Authenticator.setDefault(p.authenticator); p.jenkins48775workaround(proxy, url); } } - - if(DEFAULT_CONNECT_TIMEOUT_MILLIS > 0) { + + if (DEFAULT_CONNECT_TIMEOUT_MILLIS > 0) { con.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT_MILLIS); } - + if (JenkinsJVM.isJenkinsJVM()) { // this code may run on an agent decorate(con); } @@ -362,7 +363,7 @@ private void jenkins48775workaround(Proxy proxy, URL url) { } } authCacheSeeded = true; - } else if ("https".equals(url.getProtocol())){ + } else if ("https".equals(url.getProtocol())) { // if we access any http url using a proxy then the auth cache will have been seeded authCacheSeeded = authCacheSeeded || proxy != Proxy.NO_PROXY; } @@ -445,8 +446,8 @@ public FormValidation doValidateProxy( GetMethod method = null; try { method = new GetMethod(testUrl); - method.getParams().setParameter("http.socket.timeout", DEFAULT_CONNECT_TIMEOUT_MILLIS > 0 ? DEFAULT_CONNECT_TIMEOUT_MILLIS : (int)TimeUnit.SECONDS.toMillis(30)); - + method.getParams().setParameter("http.socket.timeout", DEFAULT_CONNECT_TIMEOUT_MILLIS > 0 ? DEFAULT_CONNECT_TIMEOUT_MILLIS : (int) TimeUnit.SECONDS.toMillis(30)); + HttpClient client = new HttpClient(); if (Util.fixEmptyAndTrim(name) != null && !isNoProxyHost(host, noProxyHost)) { client.getHostConfiguration().setProxy(name, port); @@ -454,7 +455,7 @@ public FormValidation doValidateProxy( AuthScope scope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT); client.getState().setProxyCredentials(scope, credentials); } - + int code = client.executeMethod(method); if (code != HttpURLConnection.HTTP_OK) { return FormValidation.error(Messages.ProxyConfiguration_FailedToConnect(testUrl, code)); @@ -466,12 +467,12 @@ public FormValidation doValidateProxy( method.releaseConnection(); } } - + return FormValidation.ok(Messages.ProxyConfiguration_Success()); } private boolean isNoProxyHost(String host, String noProxyHost) { - if (host!=null && noProxyHost!=null) { + if (host != null && noProxyHost != null) { for (Pattern p : getNoProxyHostPatterns(noProxyHost)) { if (p.matcher(host).matches()) { return true; @@ -482,7 +483,7 @@ private boolean isNoProxyHost(String host, String noProxyHost) { } private Credentials createCredentials(String userName, String password) { - if (userName.indexOf('\\') >= 0){ + if (userName.indexOf('\\') >= 0) { final String domain = userName.substring(0, userName.indexOf('\\')); final String user = userName.substring(userName.indexOf('\\') + 1); return new NTCredentials(user, Secret.fromString(password).getPlainText(), "", domain); diff --git a/core/src/main/java/hudson/ResponseHeaderFilter.java b/core/src/main/java/hudson/ResponseHeaderFilter.java index 4460208a733db..90fb0be87d37a 100644 --- a/core/src/main/java/hudson/ResponseHeaderFilter.java +++ b/core/src/main/java/hudson/ResponseHeaderFilter.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, id:digerata - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import java.io.IOException; @@ -47,61 +48,61 @@ * down Hudson page load times. *

      * To enable this filter, edit the web.xml file to include: - * + * *

        * <filter>
      - * 		<filter-name>change-headers-filter</filter-name>
      - * 		<filter-class>hudson.ResponseHeaderFilter</filter-class>
      - * 		<init-param>
      - * 			<param-name>Pragma</param-name>
      - * 			<param-value>public</param-value>
      - * 		</init-param>
      - * 		<init-param>
      - * 			<param-name>Cache-Control</param-name>
      - * 			<param-value>max-age=86400, public</param-value>
      - * 		</init-param>
      + *         <filter-name>change-headers-filter</filter-name>
      + *         <filter-class>hudson.ResponseHeaderFilter</filter-class>
      + *         <init-param>
      + *             <param-name>Pragma</param-name>
      + *             <param-value>public</param-value>
      + *         </init-param>
      + *         <init-param>
      + *             <param-name>Cache-Control</param-name>
      + *             <param-value>max-age=86400, public</param-value>
      + *         </init-param>
        * </filter>
      - * 
      + *
        * And down below that:
      - * 
      + *
        * <filter-mapping>
      - * 		<filter-name>Headers</filter-name>
      - * 		<url-pattern>/*</url-pattern>
      + *         <filter-name>Headers</filter-name>
      + *         <url-pattern>/*</url-pattern>
        * </filter-mapping>
        * 
      - * + * *

      - * In the case of the tomcat cache problem, it is important that the url-pattern for + * In the case of the tomcat cache problem, it is important that the url-pattern for * the filter matches the url-pattern set for the security-constraint. - * + * * @author Mike Wille */ public class ResponseHeaderFilter implements Filter { - private FilterConfig config; + private FilterConfig config; - @Override - public void init(FilterConfig filterConfig) throws ServletException { - config = filterConfig; - } + @Override + public void init(FilterConfig filterConfig) throws ServletException { + config = filterConfig; + } - @Override - public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, - ServletException { - HttpServletResponse httpResp = (HttpServletResponse) resp; + @Override + public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, + ServletException { + HttpServletResponse httpResp = (HttpServletResponse) resp; - Enumeration e = config.getInitParameterNames(); + Enumeration e = config.getInitParameterNames(); - // for each configuration element... - while(e.hasMoreElements()) { - String headerName = (String) e.nextElement(); - String headerValue = config.getInitParameter(headerName); - // set the header with the given name and value - httpResp.setHeader(headerName, headerValue); - } - chain.doFilter(req, resp); - } + // for each configuration element... + while (e.hasMoreElements()) { + String headerName = (String) e.nextElement(); + String headerValue = config.getInitParameter(headerName); + // set the header with the given name and value + httpResp.setHeader(headerName, headerValue); + } + chain.doFilter(req, resp); + } - @Override - public void destroy() { - } + @Override + public void destroy() { + } } diff --git a/core/src/main/java/hudson/StructuredForm.java b/core/src/main/java/hudson/StructuredForm.java index 5d0e28dc5c6ef..708d0120dc9df 100644 --- a/core/src/main/java/hudson/StructuredForm.java +++ b/core/src/main/java/hudson/StructuredForm.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import java.util.Collections; @@ -58,15 +59,16 @@ public static JSONObject get(StaplerRequest req) throws ServletException { * Because of the way structured form submission work, this is convenient way of * handling repeated multi-value entries. * - * @since 1.233 + * @since 1.233 */ + public static List toList(JSONObject parent, String propertyName) { Object v = parent.get(propertyName); - if(v==null) + if (v == null) return Collections.emptyList(); - if(v instanceof JSONObject) - return Collections.singletonList((JSONObject)v); - if(v instanceof JSONArray) + if (v instanceof JSONObject) + return Collections.singletonList((JSONObject) v); + if (v instanceof JSONArray) return (List) v; throw new IllegalArgumentException(); diff --git a/core/src/main/java/hudson/TcpSlaveAgentListener.java b/core/src/main/java/hudson/TcpSlaveAgentListener.java index 717c1df919531..eb6358f7a3f31 100644 --- a/core/src/main/java/hudson/TcpSlaveAgentListener.java +++ b/core/src/main/java/hudson/TcpSlaveAgentListener.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Stephen Connolly - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import edu.umd.cs.findbugs.annotations.Nullable; @@ -90,12 +91,12 @@ public final class TcpSlaveAgentListener extends Thread { * Use 0 to choose a random port. */ public TcpSlaveAgentListener(int port) throws IOException { - super("TCP agent listener port="+port); + super("TCP agent listener port=" + port); try { serverSocket = ServerSocketChannel.open(); serverSocket.socket().bind(new InetSocketAddress(port)); } catch (BindException e) { - throw (BindException)new BindException("Failed to listen on port "+port+" because it's already in use.").initCause(e); + throw (BindException) new BindException("Failed to listen on port " + port + " because it's already in use.").initCause(e); } this.configuredPort = port; setUncaughtExceptionHandler((t, e) -> { @@ -193,8 +194,8 @@ public void run(Throwable cause) { }).start(); } } catch (IOException e) { - if(!shuttingDown) { - LOGGER.log(Level.SEVERE,"Failed to accept TCP connections", e); + if (!shuttingDown) { + LOGGER.log(Level.SEVERE, "Failed to accept TCP connections", e); } } } @@ -218,7 +219,7 @@ public void shutdown() { try { serverSocket.close(); } catch (IOException e) { - LOGGER.log(Level.WARNING, "Failed to close down TCP port",e); + LOGGER.log(Level.WARNING, "Failed to close down TCP port", e); } } @@ -235,10 +236,10 @@ private final class ConnectionHandler extends Thread { ConnectionHandler(Socket s, ConnectionHandlerFailureCallback parentTerminator) { this.s = s; - synchronized(getClass()) { + synchronized (getClass()) { id = iotaGen++; } - setName("TCP agent connection handler #"+id+" with "+s.getRemoteSocketAddress()); + setName("TCP agent connection handler #" + id + " with " + s.getRemoteSocketAddress()); setUncaughtExceptionHandler((t, e) -> { LOGGER.log(Level.SEVERE, "Uncaught exception in TcpSlaveAgentListener ConnectionHandler " + t, e); try { @@ -264,17 +265,17 @@ public void run() { String header = new String(head, StandardCharsets.US_ASCII); if (header.startsWith("GET ")) { // this looks like an HTTP client - respondHello(header,s); + respondHello(header, s); return; } // otherwise assume this is AgentProtocol and start from the beginning - String s = new DataInputStream(new SequenceInputStream(new ByteArrayInputStream(head),in)).readUTF(); + String s = new DataInputStream(new SequenceInputStream(new ByteArrayInputStream(head), in)).readUTF(); - if(s.startsWith("Protocol:")) { + if (s.startsWith("Protocol:")) { String protocol = s.substring(9); AgentProtocol p = AgentProtocol.of(protocol); - if (p!=null) { + if (p != null) { if (Jenkins.get().getAgentProtocols().contains(protocol)) { LOGGER.log(p instanceof PingAgentProtocol ? Level.FINE : Level.INFO, "Accepted {0} connection #{1} from {2}", new Object[] {protocol, id, this.s.getRemoteSocketAddress()}); p.handle(this.s); @@ -287,7 +288,7 @@ public void run() { error("Unrecognized protocol: " + s, this.s); } } catch (InterruptedException e) { - LOGGER.log(Level.WARNING,"Connection #"+id+" aborted",e); + LOGGER.log(Level.WARNING, "Connection #" + id + " aborted", e); try { s.close(); } catch (IOException ex) { @@ -319,7 +320,7 @@ private void respondHello(String header, Socket s) throws IOException { response = "HTTP/1.0 200 OK\r\n" + "Content-Type: text/plain;charset=UTF-8\r\n" + "\r\n" + - "Jenkins-Agent-Protocols: " + getAgentProtocolNames()+"\r\n" + + "Jenkins-Agent-Protocols: " + getAgentProtocolNames() + "\r\n" + "Jenkins-Version: " + Jenkins.VERSION + "\r\n" + "Jenkins-Session: " + Jenkins.SESSION_HASH + "\r\n" + "Client: " + s.getInetAddress().getHostAddress() + "\r\n" + @@ -505,7 +506,7 @@ protected void doAperiodicRun() { } public static void schedule(Thread originThread, Throwable cause) { - schedule(originThread, cause,5000); + schedule(originThread, cause, 5000); } public static void schedule(Thread originThread, Throwable cause, long approxDelay) { @@ -528,7 +529,7 @@ public String toString() { } } - private static int iotaGen=1; + private static int iotaGen = 1; private static final Logger LOGGER = Logger.getLogger(TcpSlaveAgentListener.class.getName()); @@ -541,7 +542,7 @@ public String toString() { */ @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "Accessible via System Groovy Scripts") @Restricted(NoExternalUse.class) - public static String CLI_HOST_NAME = SystemProperties.getString(TcpSlaveAgentListener.class.getName()+".hostName"); + public static String CLI_HOST_NAME = SystemProperties.getString(TcpSlaveAgentListener.class.getName() + ".hostName"); /** * Port number that we advertise protocol clients to connect to. @@ -555,5 +556,5 @@ public String toString() { */ @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "Accessible via System Groovy Scripts") @Restricted(NoExternalUse.class) - public static Integer CLI_PORT = SystemProperties.getInteger(TcpSlaveAgentListener.class.getName()+".port"); + public static Integer CLI_PORT = SystemProperties.getInteger(TcpSlaveAgentListener.class.getName() + ".port"); } diff --git a/core/src/main/java/hudson/URLConnectionDecorator.java b/core/src/main/java/hudson/URLConnectionDecorator.java index f3794f4e33ea0..95c8a4e6bd349 100644 --- a/core/src/main/java/hudson/URLConnectionDecorator.java +++ b/core/src/main/java/hudson/URLConnectionDecorator.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; diff --git a/core/src/main/java/hudson/Util.java b/core/src/main/java/hudson/Util.java index 32d114efb20f5..a43295601c3b2 100644 --- a/core/src/main/java/hudson/Util.java +++ b/core/src/main/java/hudson/Util.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -56,6 +57,7 @@ import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.StandardCharsets; +import java.nio.file.CopyOption; import java.nio.file.FileAlreadyExistsException; import java.nio.file.FileSystemException; import java.nio.file.FileSystems; @@ -67,6 +69,7 @@ import java.nio.file.StandardCopyOption; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.DosFileAttributes; +import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import java.security.DigestInputStream; @@ -137,10 +140,10 @@ public class Util { * @since 1.176 */ @NonNull - public static List filter( @NonNull Iterable base, @NonNull Class type ) { + public static List filter(@NonNull Iterable base, @NonNull Class type) { List r = new ArrayList<>(); for (Object i : base) { - if(type.isInstance(i)) + if (type.isInstance(i)) r.add(type.cast(i)); } return r; @@ -150,8 +153,8 @@ public static List filter( @NonNull Iterable base, @NonNull Class t * Creates a filtered sublist. */ @NonNull - public static List filter( @NonNull List base, @NonNull Class type ) { - return filter((Iterable)base,type); + public static List filter(@NonNull List base, @NonNull Class type) { + return filter((Iterable) base, type); } /** @@ -167,7 +170,7 @@ public static List filter( @NonNull List base, @NonNull Class type * */ @Nullable - public static String replaceMacro( @CheckForNull String s, @NonNull Map properties) { + public static String replaceMacro(@CheckForNull String s, @NonNull Map properties) { return replaceMacro(s, new VariableResolver.ByMap<>(properties)); } @@ -179,30 +182,30 @@ public static String replaceMacro( @CheckForNull String s, @NonNull Map resolver) { - if (s == null) { - return null; - } + if (s == null) { + return null; + } - int idx=0; - while(true) { + int idx = 0; + while (true) { Matcher m = VARIABLE.matcher(s); - if(!m.find(idx)) return s; + if (!m.find(idx)) return s; String key = m.group().substring(1); // escape the dollar sign or get the key to resolve String value; - if(key.charAt(0)=='$') { + if (key.charAt(0) == '$') { value = "$"; } else { - if(key.charAt(0)=='{') key = key.substring(1,key.length()-1); + if (key.charAt(0) == '{') key = key.substring(1, key.length() - 1); value = resolver.resolve(key); } - if(value==null) + if (value == null) idx = m.end(); // skip this else { - s = s.substring(0,m.start())+value+s.substring(m.end()); + s = s.substring(0, m.start()) + value + s.substring(m.end()); idx = m.start() + value.length(); } } @@ -434,15 +437,15 @@ public static File createTempDir() throws IOException { * On Windows, error messages for IOException aren't very helpful. * This method generates additional user-friendly error message to the listener */ - public static void displayIOException(@NonNull IOException e, @NonNull TaskListener listener ) { + public static void displayIOException(@NonNull IOException e, @NonNull TaskListener listener) { String msg = getWin32ErrorMessage(e); - if(msg!=null) + if (msg != null) listener.getLogger().println(msg); } @CheckForNull public static String getWin32ErrorMessage(@NonNull IOException e) { - return getWin32ErrorMessage((Throwable)e); + return getWin32ErrorMessage((Throwable) e); } /** @@ -454,19 +457,19 @@ public static String getWin32ErrorMessage(@NonNull IOException e) { @CheckForNull public static String getWin32ErrorMessage(Throwable e) { String msg = e.getMessage(); - if(msg!=null) { + if (msg != null) { Matcher m = errorCodeParser.matcher(msg); - if(m.matches()) { + if (m.matches()) { try { ResourceBundle rb = ResourceBundle.getBundle("/hudson/win32errors"); - return rb.getString("error"+m.group(1)); + return rb.getString("error" + m.group(1)); } catch (RuntimeException ignored) { // silently recover from resource related failures } } } - if(e.getCause()!=null) + if (e.getCause() != null) return getWin32ErrorMessage(e.getCause()); return null; // no message } @@ -481,9 +484,9 @@ public static String getWin32ErrorMessage(Throwable e) { public static String getWin32ErrorMessage(int n) { try { ResourceBundle rb = ResourceBundle.getBundle("/hudson/win32errors"); - return rb.getString("error"+n); + return rb.getString("error" + n); } catch (MissingResourceException e) { - LOGGER.log(Level.WARNING,"Failed to find resource bundle",e); + LOGGER.log(Level.WARNING, "Failed to find resource bundle", e); return null; } } @@ -504,7 +507,7 @@ public static String getHostName() { * @deprecated Use {@link IOUtils#copy(InputStream, OutputStream)} */ @Deprecated - public static void copyStream(@NonNull InputStream in,@NonNull OutputStream out) throws IOException { + public static void copyStream(@NonNull InputStream in, @NonNull OutputStream out) throws IOException { IOUtils.copy(in, out); } @@ -548,23 +551,23 @@ public static void copyStreamAndClose(@NonNull Reader in, @NonNull Writer out) t */ @NonNull public static String[] tokenize(@NonNull String s, @CheckForNull String delimiter) { - return QuotedStringTokenizer.tokenize(s,delimiter); + return QuotedStringTokenizer.tokenize(s, delimiter); } @NonNull public static String[] tokenize(@NonNull String s) { - return tokenize(s," \t\n\r\f"); + return tokenize(s, " \t\n\r\f"); } /** * Converts the map format of the environment variables to the K=V format in the array. */ @NonNull - public static String[] mapToEnv(@NonNull Map m) { + public static String[] mapToEnv(@NonNull Map m) { String[] r = new String[m.size()]; - int idx=0; + int idx = 0; - for (final Map.Entry e : m.entrySet()) { + for (final Map.Entry e : m.entrySet()) { r[idx++] = e.getKey() + '=' + e.getValue(); } return r; @@ -572,8 +575,8 @@ public static String[] mapToEnv(@NonNull Map m) { public static int min(int x, @NonNull int... values) { for (int i : values) { - if(i 0) else if (seconds >= 10) return Messages.Util_second(seconds); else if (seconds >= 1) - return Messages.Util_second(seconds+(float)(millisecs/100)/10); // render "1.2 sec" - else if(millisecs>=100) - return Messages.Util_second((float)(millisecs/10)/100); // render "0.12 sec". + return Messages.Util_second(seconds + (float) (millisecs / 100) / 10); // render "1.2 sec" + else if (millisecs >= 100) + return Messages.Util_second((float) (millisecs / 10) / 100); // render "0.12 sec". else return Messages.Util_millisecond(millisecs); } @@ -808,9 +811,9 @@ public static String getPastTimeString(long duration) { @NonNull @Deprecated public static String combine(long n, @NonNull String suffix) { - String s = Long.toString(n)+' '+suffix; - if(n!=1) - // Just adding an 's' won't work in most natural languages, even English has exception to the rule (e.g. copy/copies). + String s = Long.toString(n) + ' ' + suffix; + if (n != 1) + // Just adding an 's' won't work in most natural languages, even English has exception to the rule (e.g. copy/copies). s += "s"; return s; } @@ -819,10 +822,10 @@ public static String combine(long n, @NonNull String suffix) { * Create a sub-list by only picking up instances of the specified type. */ @NonNull - public static List createSubList(@NonNull Collection source, @NonNull Class type ) { + public static List createSubList(@NonNull Collection source, @NonNull Class type) { List r = new ArrayList<>(); for (Object item : source) { - if(type.isInstance(item)) + if (type.isInstance(item)) r.add(type.cast(item)); } return r; @@ -849,7 +852,7 @@ public static String encode(@NonNull String s) { for (int i = 0; i < s.length(); i++) { int c = s.charAt(i); - if (c<128 && c!=' ') { + if (c < 128 && c != ' ') { out.append((char) c); } else { // 1 char -> UTF8 @@ -872,6 +875,7 @@ public static String encode(@NonNull String s) { } private static final boolean[] uriMap = new boolean[123]; + static { String raw = "! $ &'()*+,-. 0123456789 = @ABCDEFGHIJKLMNOPQRSTUVWXYZ _ abcdefghijklmnopqrstuvwxyz"; @@ -887,6 +891,7 @@ public static String encode(@NonNull String s) { } private static final boolean[] fullUriMap = new boolean[123]; + static { String raw = " 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz"; // !"#$%&'()*+,-./0123456789:;<=>?@ [\]^_` {|}~ @@ -923,11 +928,11 @@ public static String rawEncode(@NonNull String s) { * single path component used in constructing a URL. */ @NonNull - public static String fullEncode(@NonNull String s){ + public static String fullEncode(@NonNull String s) { return encode(s, fullUriMap); } - private static String encode(String s, boolean[] map){ + private static String encode(String s, boolean[] map) { boolean escaped = false; StringBuilder out = null; CharsetEncoder enc = null; @@ -935,7 +940,7 @@ private static String encode(String s, boolean[] map){ char c; for (int i = 0, m = s.length(); i < m; i++) { int codePoint = Character.codePointAt(s, i); - if((codePoint&0xffffff80)==0) { // 1 byte + if ((codePoint & 0xffffff80) == 0) { // 1 byte c = s.charAt(i); if (c > 122 || map[c]) { if (!escaped) { @@ -977,7 +982,7 @@ private static String encode(String s, boolean[] map){ out.append(toDigit(aByte & 0xF)); } - if(Character.charCount(codePoint) > 1) { + if (Character.charCount(codePoint) > 1) { i++; // we processed two characters } } @@ -986,14 +991,14 @@ private static String encode(String s, boolean[] map){ } private static char toDigit(int n) { - return (char)(n < 10 ? '0' + n : 'A' + n - 10); + return (char) (n < 10 ? '0' + n : 'A' + n - 10); } /** * Surrounds by a single-quote. */ public static String singleQuote(String s) { - return '\''+s+'\''; + return '\'' + s + '\''; } /** @@ -1001,34 +1006,34 @@ public static String singleQuote(String s) { */ @Nullable public static String escape(@CheckForNull String text) { - if (text==null) return null; - StringBuilder buf = new StringBuilder(text.length()+64); - for( int i=0; i"); else - if(ch=='<') + if (ch == '<') buf.append("<"); else - if(ch=='>') + if (ch == '>') buf.append(">"); else - if(ch=='&') + if (ch == '&') buf.append("&"); else - if(ch=='"') + if (ch == '"') buf.append("""); else - if(ch=='\'') + if (ch == '\'') buf.append("'"); else - if(ch==' ') { + if (ch == ' ') { // All spaces in a block of consecutive spaces are converted to // non-breaking space ( ) except for the last one. This allows // significant whitespace to be retained without prohibiting wrapping. - char nextCh = i+1 < text.length() ? text.charAt(i+1) : 0; - buf.append(nextCh==' ' ? " " : " "); + char nextCh = i + 1 < text.length() ? text.charAt(i + 1) : 0; + buf.append(nextCh == ' ' ? " " : " "); } else buf.append(ch); @@ -1038,16 +1043,16 @@ public static String escape(@CheckForNull String text) { @NonNull public static String xmlEscape(@NonNull String text) { - StringBuilder buf = new StringBuilder(text.length()+64); - for( int i=0; i') + if (ch == '>') buf.append(">"); else - if(ch=='&') + if (ch == '&') buf.append("&"); else buf.append(ch); @@ -1067,7 +1072,12 @@ public static void touch(@NonNull File file) throws IOException { /** * Copies a single file by using Ant. + * + * @deprecated since TODO; use {@link Files#copy(Path, Path, CopyOption...)} directly */ + @Deprecated + @Restricted(NoExternalUse.class) + @RestrictedSince("TODO") public static void copyFile(@NonNull File src, @NonNull File dst) throws BuildException { Copy cp = new Copy(); cp.setProject(new Project()); @@ -1100,7 +1110,7 @@ public static T fixNull(@CheckForNull T s, @NonNull T defaultValue) { */ @CheckForNull public static String fixEmpty(@CheckForNull String s) { - if(s==null || s.length()==0) return null; + if (s == null || s.length() == 0) return null; return s; } @@ -1111,7 +1121,7 @@ public static String fixEmpty(@CheckForNull String s) { */ @CheckForNull public static String fixEmptyAndTrim(@CheckForNull String s) { - if(s==null) return null; + if (s == null) return null; return fixEmpty(s.trim()); } @@ -1177,25 +1187,25 @@ public static Iterable fixNull(@CheckForNull Iterable l) { @NonNull public static String getFileName(@NonNull String filePath) { int idx = filePath.lastIndexOf('\\'); - if(idx>=0) - return getFileName(filePath.substring(idx+1)); + if (idx >= 0) + return getFileName(filePath.substring(idx + 1)); idx = filePath.lastIndexOf('/'); - if(idx>=0) - return getFileName(filePath.substring(idx+1)); + if (idx >= 0) + return getFileName(filePath.substring(idx + 1)); return filePath; } /** * Concatenate multiple strings by inserting a separator. - * @deprecated since TODO; use {@link String#join(CharSequence, Iterable)} + * @deprecated since 2.292; use {@link String#join(CharSequence, Iterable)} */ @Deprecated @NonNull public static String join(@NonNull Collection strings, @NonNull String separator) { StringBuilder buf = new StringBuilder(); - boolean first=true; + boolean first = true; for (Object s : strings) { - if(first) first=false; + if (first) first = false; else buf.append(separator); buf.append(s); } @@ -1241,14 +1251,14 @@ public static FileSet createFileSet(@NonNull File baseDir, @NonNull String inclu StringTokenizer tokens; - tokens = new StringTokenizer(includes,","); - while(tokens.hasMoreTokens()) { + tokens = new StringTokenizer(includes, ","); + while (tokens.hasMoreTokens()) { String token = tokens.nextToken().trim(); fs.createInclude().setName(token); } - if(excludes!=null) { - tokens = new StringTokenizer(excludes,","); - while(tokens.hasMoreTokens()) { + if (excludes != null) { + tokens = new StringTokenizer(excludes, ","); + while (tokens.hasMoreTokens()) { String token = tokens.nextToken().trim(); fs.createExclude().setName(token); } @@ -1258,7 +1268,7 @@ public static FileSet createFileSet(@NonNull File baseDir, @NonNull String inclu @NonNull public static FileSet createFileSet(@NonNull File baseDir, @NonNull String includes) { - return createFileSet(baseDir,includes,null); + return createFileSet(baseDir, includes, null); } private static void tryToDeleteSymlink(@NonNull File symlink) { @@ -1375,6 +1385,7 @@ public static void createSymlink(@NonNull File baseDir, @NonNull String targetPa } private static final AtomicBoolean warnedSymlinks = new AtomicBoolean(); + private static void warnWindowsSymlink() { if (warnedSymlinks.compareAndSet(false, true)) { LOGGER.warning("Symbolic links enabled on this platform but disabled for this user; run as administrator or use Local Security Policy > Security Settings > Local Policies > User Rights Assignment > Create symbolic links"); @@ -1399,11 +1410,11 @@ public static String resolveSymlink(File link, TaskListener listener) throws Int @CheckForNull public static File resolveSymlinkToFile(@NonNull File link) throws InterruptedException, IOException { String target = resolveSymlink(link); - if (target==null) return null; + if (target == null) return null; File f = new File(target); if (f.isAbsolute()) return f; // absolute symlink - return new File(link.getParentFile(),target); // relative symlink + return new File(link.getParentFile(), target); // relative symlink } /** @@ -1449,7 +1460,7 @@ public static String resolveSymlink(@NonNull File link) throws IOException { @Deprecated public static String encodeRFC2396(String url) { try { - return new URI(null,url,null).toASCIIString(); + return new URI(null, url, null).toASCIIString(); } catch (URISyntaxException e) { LOGGER.log(Level.WARNING, "Failed to encode {0}", url); // could this ever happen? return url; @@ -1462,7 +1473,7 @@ public static String encodeRFC2396(String url) { */ @NonNull public static String wrapToErrorSpan(@NonNull String s) { - s = ""+s+""; + s = "" + s + ""; return s; } @@ -1595,8 +1606,8 @@ private static Method getMethod(@NonNull Class clazz, @Nullable Class base public static File changeExtension(@NonNull File dst, @NonNull String ext) { String p = dst.getPath(); int pos = p.lastIndexOf('.'); - if (pos<0) return new File(p+ext); - else return new File(p.substring(0,pos)+ext); + if (pos < 0) return new File(p + ext); + else return new File(p.substring(0, pos) + ext); } /** @@ -1605,7 +1616,7 @@ public static File changeExtension(@NonNull File dst, @NonNull String ext) { */ @Nullable public static String intern(@CheckForNull String s) { - return s==null ? s : s.intern(); + return s == null ? s : s.intern(); } /** @@ -1622,10 +1633,10 @@ public static String intern(@CheckForNull String s) { @Restricted(NoExternalUse.class) public static boolean isAbsoluteUri(@NonNull String uri) { int idx = uri.indexOf(':'); - if (idx<0) return false; // no ':'. can't be absolute + if (idx < 0) return false; // no ':'. can't be absolute // #, ?, and / must not be before ':' - return idx<_indexOf(uri, '#') && idx<_indexOf(uri,'?') && idx<_indexOf(uri,'/'); + return idx < _indexOf(uri, '#') && idx < _indexOf(uri, '?') && idx < _indexOf(uri, '/'); } /** @@ -1642,7 +1653,7 @@ public static boolean isSafeToRedirectTo(@NonNull String uri) { */ private static int _indexOf(@NonNull String s, char ch) { int idx = s.indexOf(ch); - if (idx<0) return s.length(); + if (idx < 0) return s.length(); return idx; } @@ -1656,7 +1667,7 @@ public static Properties loadProperties(@NonNull String properties) throws IOExc p.load(new StringReader(properties)); return p; } - + /** * Closes the item and logs error to the log in the case of error. * Logging will be performed on the {@code WARNING} level. @@ -1667,14 +1678,14 @@ public static Properties loadProperties(@NonNull String properties) throws IOExc * @since 2.19, but TODO update once un-restricted */ @Restricted(NoExternalUse.class) - public static void closeAndLogFailures(@CheckForNull Closeable toClose, @NonNull Logger logger, + public static void closeAndLogFailures(@CheckForNull Closeable toClose, @NonNull Logger logger, @NonNull String closeableName, @NonNull String closeableOwner) { if (toClose == null) { return; } try { toClose.close(); - } catch(IOException ex) { + } catch (IOException ex) { LogRecord record = new LogRecord(Level.WARNING, "Failed to close {0} of {1}"); record.setParameters(new Object[] { closeableName, closeableOwner }); record.setThrown(ex); @@ -1726,28 +1737,85 @@ public static Set modeToPermissions(int mode) throws IOExce throw new IOException(e); } } - + + /** + * Create a directory by creating all nonexistent parent directories first. + * + *

      Unlike {@link Files#createDirectory}, an exception is not thrown + * if the directory could not be created because it already exists. + * Unlike {@link Files#createDirectories}, an exception is not thrown + * if the directory (or one of its parents) is a symbolic link. + * + *

      The {@code attrs} parameter contains optional {@link FileAttribute file attributes} + * to set atomically when creating the nonexistent directories. + * Each file attribute is identified by its {@link FileAttribute#name}. + * If more than one attribute of the same name is included in the array, + * then all but the last occurrence is ignored. + * + *

      If this method fails, + * then it may do so after creating some, but not all, of the parent directories. + * + * @param dir The directory to create. + * @param attrs An optional list of file attributes to set atomically + * when creating the directory. + * @return The directory. + * @throws UnsupportedOperationException If the array contains an attribute + * that cannot be set atomically when creating the directory. + * @throws FileAlreadyExistsException If {@code dir} exists but is not a directory. + * @throws IOException If an I/O error occurs. + * @see Files#createDirectories(Path, FileAttribute[]) + */ + @Restricted(NoExternalUse.class) + public static Path createDirectories(@NonNull Path dir, FileAttribute... attrs) throws IOException { + dir = dir.toAbsolutePath(); + + Path parent; + for (parent = dir.getParent(); parent != null; parent = parent.getParent()) { + if (Files.exists(parent)) { + break; + } + } + + if (parent == null) { + if (Files.isDirectory(dir)) { + return dir; + } else { + return Files.createDirectory(dir, attrs); + } + } + + Path child = parent; + for (Path name : parent.relativize(dir)) { + child = child.resolve(name); + if (!Files.isDirectory(child)) { + Files.createDirectory(child, attrs); + } + } + + return dir; + } + /** * Compute the number of calendar days elapsed since the given date. * As it's only the calendar days difference that matter, "11.00pm" to "2.00am the day after" returns 1, * even if there are only 3 hours between. As well as "10am" to "2pm" both on the same day, returns 0. */ @Restricted(NoExternalUse.class) - public static long daysBetween(@NonNull Date a, @NonNull Date b){ + public static long daysBetween(@NonNull Date a, @NonNull Date b) { LocalDate aLocal = a.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); LocalDate bLocal = b.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); return ChronoUnit.DAYS.between(aLocal, bLocal); } - + /** * @return positive number of days between the given date and now * @see #daysBetween(Date, Date) */ @Restricted(NoExternalUse.class) - public static long daysElapsedSince(@NonNull Date date){ + public static long daysElapsedSince(@NonNull Date date) { return Math.max(0, daysBetween(date, new Date())); } - + /** * Find the specific ancestor, or throw an exception. * Useful for an ancestor we know is inside the URL to ease readability @@ -1761,7 +1829,7 @@ public static long daysElapsedSince(@NonNull Date date){ return t; } - public static final FastDateFormat XS_DATETIME_FORMATTER = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss'Z'",new SimpleTimeZone(0,"GMT")); + public static final FastDateFormat XS_DATETIME_FORMATTER = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss'Z'", new SimpleTimeZone(0, "GMT")); // Note: RFC822 dates must not be localized! public static final FastDateFormat RFC822_DATETIME_FORMATTER @@ -1772,9 +1840,9 @@ public static long daysElapsedSince(@NonNull Date date){ /** * On Unix environment that cannot run "ln", set this to true. */ - public static boolean NO_SYMLINK = SystemProperties.getBoolean(Util.class.getName()+".noSymLink"); + public static boolean NO_SYMLINK = SystemProperties.getBoolean(Util.class.getName() + ".noSymLink"); - public static boolean SYMLINK_ESCAPEHATCH = SystemProperties.getBoolean(Util.class.getName()+".symlinkEscapeHatch"); + public static boolean SYMLINK_ESCAPEHATCH = SystemProperties.getBoolean(Util.class.getName() + ".symlinkEscapeHatch"); /** * The number of additional times we will attempt to delete files/directory trees diff --git a/core/src/main/java/hudson/WebAppMain.java b/core/src/main/java/hudson/WebAppMain.java index f41de96eac8d7..c63e1f813a96e 100644 --- a/core/src/main/java/hudson/WebAppMain.java +++ b/core/src/main/java/hudson/WebAppMain.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Jean-Baptiste Quenot, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import static java.util.logging.Level.FINE; @@ -29,7 +30,6 @@ import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider; import com.thoughtworks.xstream.core.JVM; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.model.Hudson; import hudson.security.ACL; import hudson.security.ACLContext; @@ -50,6 +50,7 @@ import java.io.OutputStream; import java.net.URL; import java.net.URLClassLoader; +import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.StandardOpenOption; @@ -63,16 +64,11 @@ import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.NamingException; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.ServletResponse; import javax.servlet.SessionTrackingMode; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.TransformerFactoryConfigurationError; import jenkins.model.Jenkins; import jenkins.util.JenkinsJVM; import jenkins.util.SystemProperties; @@ -101,7 +97,7 @@ public class WebAppMain implements ServletContextListener { *

      * The SecurityRealm should be corrected but this is a hardening in Jenkins core. *

      - * As this property is read during startup, you will not be able to change it at runtime + * As this property is read during startup, you will not be able to change it at runtime * depending on your application server (not possible with Jetty nor Tomcat) *

      * When running hpi:run, the default tracking is COOKIE+URL. @@ -112,7 +108,7 @@ public class WebAppMain implements ServletContextListener { public static final String FORCE_SESSION_TRACKING_BY_COOKIE_PROP = WebAppMain.class.getName() + ".forceSessionTrackingByCookie"; private final RingBufferLogHandler handler = new RingBufferLogHandler(WebAppMain.getDefaultRingBufferSize()) { - + @Override public synchronized void publish(LogRecord record) { if (record.getLevel().intValue() >= Level.INFO.intValue()) { super.publish(record); @@ -145,7 +141,7 @@ public void contextInitialized(ServletContextEvent event) { if (Main.isDevelopmentMode && System.getProperty("java.util.logging.config.file") == null) { try { Formatter formatter = (Formatter) Class.forName("io.jenkins.lib.support_log_formatter.SupportLogFormatter").newInstance(); - for (Handler h : java.util.logging.Logger.getLogger("").getHandlers()) { + for (Handler h : Logger.getLogger("").getHandlers()) { if (h instanceof ConsoleHandler) { ((ConsoleHandler) h).setFormatter(formatter); } @@ -159,7 +155,7 @@ public void contextInitialized(ServletContextEvent event) { JenkinsJVMAccess._setJenkinsJVM(true); final ServletContext context = event.getServletContext(); - File home=null; + File home = null; try { // use the current request to determine the language @@ -174,12 +170,12 @@ public Locale get() { JVM jvm; try { jvm = new JVM(); - new URLClassLoader(new URL[0],getClass().getClassLoader()); - } catch(SecurityException e) { + new URLClassLoader(new URL[0], getClass().getClassLoader()); + } catch (SecurityException e) { throw new InsufficientPermissionDetected(e); } - try {// remove Sun PKCS11 provider if present. See http://wiki.jenkins-ci.org/display/JENKINS/Solaris+Issue+6276483 + try { // remove Sun PKCS11 provider if present. See http://wiki.jenkins-ci.org/display/JENKINS/Solaris+Issue+6276483 Security.removeProvider("SunPKCS11-Solaris"); } catch (SecurityException e) { // ignore this error. @@ -190,35 +186,35 @@ public Locale get() { final FileAndDescription describedHomeDir = getHomeDir(event); home = describedHomeDir.file.getAbsoluteFile(); try { - Files.createDirectories(home.toPath()); + Util.createDirectories(home.toPath()); } catch (IOException | InvalidPathException e) { - throw (NoHomeDir)new NoHomeDir(home).initCause(e); + throw (NoHomeDir) new NoHomeDir(home).initCause(e); } - LOGGER.info("Jenkins home directory: "+ home +" found at: " + describedHomeDir.description); + LOGGER.info("Jenkins home directory: " + home + " found at: " + describedHomeDir.description); recordBootAttempt(home); // make sure that we are using XStream in the "enhanced" (JVM-specific) mode - if(jvm.bestReflectionProvider().getClass()==PureJavaReflectionProvider.class) { + if (jvm.bestReflectionProvider().getClass() == PureJavaReflectionProvider.class) { throw new IncompatibleVMDetected(); // nope } // make sure this is servlet 2.4 container or above try { - ServletResponse.class.getMethod("setCharacterEncoding",String.class); + ServletResponse.class.getMethod("setCharacterEncoding", String.class); } catch (NoSuchMethodException e) { - throw (IncompatibleServletVersionDetected)new IncompatibleServletVersionDetected(ServletResponse.class).initCause(e); + throw (IncompatibleServletVersionDetected) new IncompatibleServletVersionDetected(ServletResponse.class).initCause(e); } // make sure that we see Ant 1.7 try { FileSet.class.getMethod("getDirectoryScanner"); } catch (NoSuchMethodException e) { - throw (IncompatibleAntVersionDetected)new IncompatibleAntVersionDetected(FileSet.class).initCause(e); + throw (IncompatibleAntVersionDetected) new IncompatibleAntVersionDetected(FileSet.class).initCause(e); } // make sure AWT is functioning, or else JFreeChart won't even load. - if(ChartUtil.awtProblemCause!=null) { + if (ChartUtil.awtProblemCause != null) { throw new AWTProblem(ChartUtil.awtProblemCause); } @@ -235,33 +231,15 @@ public Locale get() { throw new NoTempDir(e); } - // Tomcat breaks XSLT with JDK 5.0 and onward. Check if that's the case, and if so, - // try to correct it - try { - TransformerFactory.newInstance(); - // if this works we are all happy - } catch (TransformerFactoryConfigurationError x) { - // no it didn't. - LOGGER.log(WARNING, "XSLT not configured correctly. Hudson will try to fix this. See https://bz.apache.org/bugzilla/show_bug.cgi?id=40895 for more details",x); - System.setProperty(TransformerFactory.class.getName(),"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl"); - try { - TransformerFactory.newInstance(); - LOGGER.info("XSLT is set to the JAXP RI in JRE"); - } catch(TransformerFactoryConfigurationError y) { - LOGGER.log(SEVERE, "Failed to correct the problem."); - } - } - installExpressionFactory(event); - context.setAttribute(APP,new HudsonIsLoading()); + context.setAttribute(APP, new HudsonIsLoading()); if (SystemProperties.getBoolean(FORCE_SESSION_TRACKING_BY_COOKIE_PROP, true)) { context.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE)); } final File _home = home; initThread = new Thread("Jenkins initialization thread") { - @SuppressFBWarnings(value = "RV_RETURN_VALUE_IGNORED_BAD_PRACTICE", justification = "TODO needs triage") @Override public void run() { boolean success = false; @@ -274,19 +252,19 @@ public void run() { context.setAttribute(APP, instance); - BootFailure.getBootFailureFile(_home).delete(); + Files.deleteIfExists(BootFailure.getBootFailureFile(_home).toPath()); // at this point we are open for business and serving requests normally - LOGGER.info("Jenkins is fully up and running"); + Jenkins.get().getLifecycle().onReady(); success = true; } catch (Error e) { - new HudsonFailedToLoad(e).publish(context,_home); + new HudsonFailedToLoad(e).publish(context, _home); throw e; } catch (Exception e) { - new HudsonFailedToLoad(e).publish(context,_home); + new HudsonFailedToLoad(e).publish(context, _home); } finally { Jenkins instance = Jenkins.getInstanceOrNull(); - if(!success && instance!=null) + if (!success && instance != null) instance.cleanUp(); } } @@ -295,7 +273,7 @@ public void run() { } catch (BootFailure e) { e.publish(context, home); } catch (Error | RuntimeException e) { - LOGGER.log(SEVERE, "Failed to initialize Jenkins",e); + LOGGER.log(SEVERE, "Failed to initialize Jenkins", e); throw e; } } @@ -311,10 +289,10 @@ public void joinInit() throws InterruptedException { * @see BootFailure */ private void recordBootAttempt(File home) { - try (OutputStream o=Files.newOutputStream(BootFailure.getBootFailureFile(home).toPath(), StandardOpenOption.CREATE, StandardOpenOption.APPEND)) { - o.write((new Date() + System.getProperty("line.separator", "\n")).getBytes()); + try (OutputStream o = Files.newOutputStream(BootFailure.getBootFailureFile(home).toPath(), StandardOpenOption.CREATE, StandardOpenOption.APPEND)) { + o.write((new Date() + System.getProperty("line.separator", "\n")).getBytes(Charset.defaultCharset())); } catch (IOException | InvalidPathException e) { - LOGGER.log(WARNING, "Failed to record boot attempts",e); + LOGGER.log(WARNING, "Failed to record boot attempts", e); } } @@ -322,10 +300,9 @@ public static void installExpressionFactory(ServletContextEvent event) { JellyFacet.setExpressionFactory(event, new ExpressionFactory2()); } - /** + /** * Installs log handler to monitor all Hudson logs. */ - @SuppressFBWarnings(value = "LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE", justification = "TODO needs triage") private void installLogger() { Jenkins.logRecords = handler.getView(); Logger.getLogger("").addHandler(handler); @@ -335,7 +312,8 @@ private void installLogger() { public static class FileAndDescription { public final File file; public final String description; - public FileAndDescription(File file,String description) { + + public FileAndDescription(File file, String description) { this.file = file; this.description = description; } @@ -344,67 +322,47 @@ public FileAndDescription(File file,String description) { /** * Determines the home directory for Jenkins. * - *

      - * We look for a setting that affects the smallest scope first, then bigger ones later. + *

      We look for a setting that affects the smallest scope first, then bigger ones later. * - *

      - * People makes configuration mistakes, so we are trying to be nice + *

      People make configuration mistakes, so we are trying to be nice * with those by doing {@link String#trim()}. - * - *

      + * * @return the File alongside with some description to help the user troubleshoot issues */ public FileAndDescription getHomeDir(ServletContextEvent event) { - // check JNDI for the home directory first - for (String name : HOME_NAMES) { - try { - InitialContext iniCtxt = new InitialContext(); - Context env = (Context) iniCtxt.lookup("java:comp/env"); - String value = (String) env.lookup(name); - if(value!=null && value.trim().length()>0) - return new FileAndDescription(new File(value.trim()),"JNDI/java:comp/env/"+name); - // look at one more place. See issue JENKINS-1314 - value = (String) iniCtxt.lookup(name); - if(value!=null && value.trim().length()>0) - return new FileAndDescription(new File(value.trim()),"JNDI/"+name); - } catch (NamingException e) { - // ignore - } - } - - // next the system property + // check the system property for the home directory first for (String name : HOME_NAMES) { String sysProp = SystemProperties.getString(name); - if(sysProp!=null) - return new FileAndDescription(new File(sysProp.trim()),"SystemProperties.getProperty(\""+name+"\")"); + if (sysProp != null) + return new FileAndDescription(new File(sysProp.trim()), "SystemProperties.getProperty(\"" + name + "\")"); } // look at the env var next for (String name : HOME_NAMES) { String env = EnvVars.masterEnvVars.get(name); - if(env!=null) - return new FileAndDescription(new File(env.trim()).getAbsoluteFile(),"EnvVars.masterEnvVars.get(\""+name+"\")"); + if (env != null) + return new FileAndDescription(new File(env.trim()).getAbsoluteFile(), "EnvVars.masterEnvVars.get(\"" + name + "\")"); } // otherwise pick a place by ourselves String root = event.getServletContext().getRealPath("/WEB-INF/workspace"); - if(root!=null) { + if (root != null) { File ws = new File(root.trim()); - if(ws.exists()) + if (ws.exists()) // Hudson <1.42 used to prefer this before ~/.hudson, so // check the existence and if it's there, use it. // otherwise if this is a new installation, prefer ~/.hudson - return new FileAndDescription(ws,"getServletContext().getRealPath(\"/WEB-INF/workspace\")"); + return new FileAndDescription(ws, "getServletContext().getRealPath(\"/WEB-INF/workspace\")"); } - File legacyHome = new File(new File(System.getProperty("user.home")),".hudson"); + File legacyHome = new File(new File(System.getProperty("user.home")), ".hudson"); if (legacyHome.exists()) { - return new FileAndDescription(legacyHome,"$user.home/.hudson"); // before rename, this is where it was stored + return new FileAndDescription(legacyHome, "$user.home/.hudson"); // before rename, this is where it was stored } - File newHome = new File(new File(System.getProperty("user.home")),".jenkins"); - return new FileAndDescription(newHome,"$user.home/.jenkins"); + File newHome = new File(new File(System.getProperty("user.home")), ".jenkins"); + return new FileAndDescription(newHome, "$user.home/.jenkins"); } @Override @@ -442,5 +400,5 @@ private static void _setJenkinsJVM(boolean jenkinsJVM) { } } - private static final String[] HOME_NAMES = {"JENKINS_HOME","HUDSON_HOME"}; + private static final String[] HOME_NAMES = {"JENKINS_HOME", "HUDSON_HOME"}; } diff --git a/core/src/main/java/hudson/WorkspaceSnapshot.java b/core/src/main/java/hudson/WorkspaceSnapshot.java index 25938f580f05c..19d536700f8a3 100644 --- a/core/src/main/java/hudson/WorkspaceSnapshot.java +++ b/core/src/main/java/hudson/WorkspaceSnapshot.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import hudson.model.AbstractBuild; @@ -44,7 +45,7 @@ public abstract class WorkspaceSnapshot implements Action { * @param listener * Send the progress of the restoration to this listener. Never null. */ - public abstract void restoreTo(AbstractBuild owner, FilePath dst, TaskListener listener) throws IOException, InterruptedException; + public abstract void restoreTo(AbstractBuild owner, FilePath dst, TaskListener listener) throws IOException, InterruptedException; @Override public String getIconFileName() { diff --git a/core/src/main/java/hudson/XmlFile.java b/core/src/main/java/hudson/XmlFile.java index 46e70835a23a5..f624104df673e 100644 --- a/core/src/main/java/hudson/XmlFile.java +++ b/core/src/main/java/hudson/XmlFile.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson; import com.thoughtworks.xstream.XStream; @@ -126,7 +127,7 @@ public final class XmlFile { private static final ThreadLocal writing = new ThreadLocal<>(); public XmlFile(File file) { - this(DEFAULT_XSTREAM,file); + this(DEFAULT_XSTREAM, file); } public XmlFile(XStream xs, File file) { @@ -158,12 +159,12 @@ public XStream getXStream() { */ public Object read() throws IOException { if (LOGGER.isLoggable(Level.FINE)) { - LOGGER.fine("Reading "+file); + LOGGER.fine("Reading " + file); } try (InputStream in = new BufferedInputStream(Files.newInputStream(file.toPath()))) { return xs.fromXML(in); } catch (RuntimeException | Error e) { - throw new IOException("Unable to read "+file,e); + throw new IOException("Unable to read " + file, e); } } @@ -174,7 +175,7 @@ public Object read() throws IOException { * The unmarshalled object. Usually the same as {@code o}, but would be different * if the XML representation is completely new. */ - public Object unmarshal( Object o ) throws IOException { + public Object unmarshal(Object o) throws IOException { return unmarshal(o, false); } @@ -195,11 +196,11 @@ private Object unmarshal(Object o, boolean nullOut) throws IOException { return xs.unmarshal(DEFAULT_DRIVER.createReader(in), o); } } catch (RuntimeException | Error e) { - throw new IOException("Unable to read "+file,e); + throw new IOException("Unable to read " + file, e); } } - public void write( Object o ) throws IOException { + public void write(Object o) throws IOException { mkdirs(); AtomicFileWriter w = force ? new AtomicFileWriter(file) @@ -215,7 +216,7 @@ public void write( Object o ) throws IOException { writing.set(null); } w.commit(); - } catch(RuntimeException e) { + } catch (RuntimeException e) { throw new IOException(e); } finally { w.abort(); @@ -250,9 +251,9 @@ public boolean exists() { public void delete() throws IOException { Files.deleteIfExists(Util.fileToPath(file)); } - + public void mkdirs() throws IOException { - Files.createDirectories(Util.fileToPath(file.getParentFile())); + Util.createDirectories(Util.fileToPath(file.getParentFile())); } @Override @@ -313,6 +314,7 @@ public void writeRawTo(Writer w) throws IOException { public String sniffEncoding() throws IOException { class Eureka extends SAXException { final String encoding; + Eureka(String encoding) { this.encoding = encoding; } @@ -345,11 +347,11 @@ public void startElement(String uri, String localName, String qName, Attributes } private void attempt() throws Eureka { - if(loc==null) return; + if (loc == null) return; if (loc instanceof Locator2) { Locator2 loc2 = (Locator2) loc; String e = loc2.getEncoding(); - if(e!=null) + if (e != null) throw new Eureka(e); } } @@ -357,7 +359,7 @@ private void attempt() throws Eureka { // can't reach here throw new AssertionError(); } catch (Eureka e) { - if(e.encoding!=null) + if (e.encoding != null) return e.encoding; // the environment can contain old version of Xerces and others that do not support Locator2 // in such a case, assume UTF-8 rather than fail, since Jenkins internally always write XML in UTF-8 diff --git a/core/src/main/java/hudson/cli/AbstractBuildRangeCommand.java b/core/src/main/java/hudson/cli/AbstractBuildRangeCommand.java index 8d966dc924d96..ead7f267ff608 100644 --- a/core/src/main/java/hudson/cli/AbstractBuildRangeCommand.java +++ b/core/src/main/java/hudson/cli/AbstractBuildRangeCommand.java @@ -15,18 +15,18 @@ */ @Deprecated public abstract class AbstractBuildRangeCommand extends CLICommand { - @Argument(metaVar="JOB",usage="Name of the job to build",required=true,index=0) - public AbstractProject job; + @Argument(metaVar = "JOB", usage = "Name of the job to build", required = true, index = 0) + public AbstractProject job; - @Argument(metaVar="RANGE",usage="Range of the build records to delete. 'N-M', 'N,M', or 'N'",required=true,index=1) + @Argument(metaVar = "RANGE", usage = "Range of the build records to delete. 'N-M', 'N,M', or 'N'", required = true, index = 1) public String range; @Override protected int run() throws Exception { - RangeSet rs = RangeSet.fromString(range,false); + RangeSet rs = RangeSet.fromString(range, false); - return act((List)job.getBuilds(rs)); + return act((List) job.getBuilds(rs)); } - protected abstract int act(List> builds) throws IOException; + protected abstract int act(List> builds) throws IOException; } diff --git a/core/src/main/java/hudson/cli/AddJobToViewCommand.java b/core/src/main/java/hudson/cli/AddJobToViewCommand.java index 116ab82adf28b..6bab9deeb7d1a 100644 --- a/core/src/main/java/hudson/cli/AddJobToViewCommand.java +++ b/core/src/main/java/hudson/cli/AddJobToViewCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -37,11 +38,11 @@ @Extension public class AddJobToViewCommand extends CLICommand { - @Argument(usage="Name of the view", required=true, index=0) + @Argument(usage = "Name of the view", required = true, index = 0) private View view; @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") - @Argument(usage="Job names", required=true, index=1) + @Argument(usage = "Job names", required = true, index = 1) private List jobs; @Override @@ -56,7 +57,7 @@ protected int run() throws Exception { if (!(view instanceof DirectlyModifiableView)) throw new IllegalStateException( "'" + view.getDisplayName() + "' view can not be modified directly"); - for (TopLevelItem job: jobs) { + for (TopLevelItem job : jobs) { ((DirectlyModifiableView) view).add(job); } diff --git a/core/src/main/java/hudson/cli/BuildCommand.java b/core/src/main/java/hudson/cli/BuildCommand.java index bb84871a7f1c9..b4f7ae15e0a1e 100644 --- a/core/src/main/java/hudson/cli/BuildCommand.java +++ b/core/src/main/java/hudson/cli/BuildCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.AbortException; @@ -70,28 +71,28 @@ public String getShortDescription() { return Messages.BuildCommand_ShortDescription(); } - @Argument(metaVar="JOB",usage="Name of the job to build",required=true) - public Job job; + @Argument(metaVar = "JOB", usage = "Name of the job to build", required = true) + public Job job; - @Option(name="-f", usage="Follow the build progress. Like -s only interrupts are not passed through to the build.") + @Option(name = "-f", usage = "Follow the build progress. Like -s only interrupts are not passed through to the build.") public boolean follow = false; - @Option(name="-s",usage="Wait until the completion/abortion of the command. Interrupts are passed through to the build.") + @Option(name = "-s", usage = "Wait until the completion/abortion of the command. Interrupts are passed through to the build.") public boolean sync = false; - @Option(name="-w",usage="Wait until the start of the command") + @Option(name = "-w", usage = "Wait until the start of the command") public boolean wait = false; - @Option(name="-c",usage="Check for SCM changes before starting the build, and if there's no change, exit without doing a build") + @Option(name = "-c", usage = "Check for SCM changes before starting the build, and if there's no change, exit without doing a build") public boolean checkSCM = false; - @Option(name="-p",usage="Specify the build parameters in the key=value format.") - public Map parameters = new HashMap<>(); + @Option(name = "-p", usage = "Specify the build parameters in the key=value format.") + public Map parameters = new HashMap<>(); - @Option(name="-v",usage="Prints out the console output of the build. Use with -s") + @Option(name = "-v", usage = "Prints out the console output of the build. Use with -s") public boolean consoleOutput = false; - @Option(name="-r") @Deprecated + @Option(name = "-r") @Deprecated public int retryCnt = 10; protected static final String BUILD_SCHEDULING_REFUSED = "Build scheduling Refused by an extension, hence not in Queue."; @@ -103,8 +104,8 @@ protected int run() throws Exception { ParametersAction a = null; if (!parameters.isEmpty()) { ParametersDefinitionProperty pdp = job.getProperty(ParametersDefinitionProperty.class); - if (pdp==null) - throw new IllegalStateException(job.getFullDisplayName()+" is not parameterized but the -p option was specified."); + if (pdp == null) + throw new IllegalStateException(job.getFullDisplayName() + " is not parameterized but the -p option was specified."); //TODO: switch to type annotations after the migration to Java 1.8 List values = new ArrayList<>(); @@ -112,7 +113,7 @@ protected int run() throws Exception { for (Map.Entry e : parameters.entrySet()) { String name = e.getKey(); ParameterDefinition pd = pdp.getParameterDefinition(name); - if (pd==null) { + if (pd == null) { String nearest = EditDistance.findNearest(name, pdp.getParameterDefinitionNames()); throw new CmdLineException(null, nearest == null ? String.format("'%s' is not a valid parameter.", name) : @@ -120,20 +121,20 @@ protected int run() throws Exception { } ParameterValue val = pd.createValue(this, Util.fixNull(e.getValue())); if (val == null) { - throw new CmdLineException(null, String.format("Cannot resolve the value for the parameter '%s'.",name)); + throw new CmdLineException(null, String.format("Cannot resolve the value for the parameter '%s'.", name)); } values.add(val); } // handle missing parameters by adding as default values ISSUE JENKINS-7162 - for(ParameterDefinition pd : pdp.getParameterDefinitions()) { + for (ParameterDefinition pd : pdp.getParameterDefinitions()) { if (parameters.containsKey(pd.getName())) continue; // not passed in use default ParameterValue defaultValue = pd.getDefaultParameterValue(); if (defaultValue == null) { - throw new CmdLineException(null, String.format("No default value for the parameter '%s'.",pd.getName())); + throw new CmdLineException(null, String.format("No default value for the parameter '%s'.", pd.getName())); } values.add(defaultValue); } @@ -144,7 +145,7 @@ protected int run() throws Exception { if (checkSCM) { SCMTriggerItem item = SCMTriggerItem.SCMTriggerItems.asSCMTriggerItem(job); if (item == null) - throw new AbortException(job.getFullDisplayName()+" has no SCM trigger, but checkSCM was specified"); + throw new AbortException(job.getFullDisplayName() + " has no SCM trigger, but checkSCM was specified"); // preemptively check for a polling veto if (SCMDecisionHandler.firstShouldPollVeto(job) != null) { return 0; @@ -157,21 +158,21 @@ protected int run() throws Exception { String msg = Messages.BuildCommand_CLICause_CannotBuildUnknownReasons(job.getFullDisplayName()); if (job instanceof ParameterizedJobMixIn.ParameterizedJob && ((ParameterizedJobMixIn.ParameterizedJob) job).isDisabled()) { msg = Messages.BuildCommand_CLICause_CannotBuildDisabled(job.getFullDisplayName()); - } else if (job.isHoldOffBuildUntilSave()){ + } else if (job.isHoldOffBuildUntilSave()) { msg = Messages.BuildCommand_CLICause_CannotBuildConfigNotSaved(job.getFullDisplayName()); } throw new IllegalStateException(msg); } Queue.Item item = ParameterizedJobMixIn.scheduleBuild2(job, 0, new CauseAction(new CLICause(Jenkins.getAuthentication2().getName())), a); - QueueTaskFuture> f = item != null ? (QueueTaskFuture)item.getFuture() : null; - + QueueTaskFuture> f = item != null ? (QueueTaskFuture) item.getFuture() : null; + if (wait || sync || follow) { if (f == null) { throw new IllegalStateException(BUILD_SCHEDULING_REFUSED); } - Run b = f.waitForStart(); // wait for the start - stdout.println("Started "+b.getFullDisplayName()); + Run b = f.waitForStart(); // wait for the start + stdout.println("Started " + b.getFullDisplayName()); stdout.flush(); if (sync || follow) { @@ -182,13 +183,13 @@ protected int run() throws Exception { // exception on a slow/busy machine, if it takes // longish to create the log file int retryInterval = 100; - for (int i=0;i<=retryCnt;) { + for (int i = 0; i <= retryCnt; ) { try { b.writeWholeLogTo(stdout); break; } catch (FileNotFoundException | NoSuchFileException e) { - if ( i == retryCnt ) { + if (i == retryCnt) { Exception myException = new AbortException(); myException.initCause(e); throw myException; @@ -199,7 +200,7 @@ protected int run() throws Exception { } } f.get(); // wait for the completion - stdout.println("Completed "+b.getFullDisplayName()+" : "+b.getResult()); + stdout.println("Completed " + b.getFullDisplayName() + " : " + b.getResult()); return b.getResult().ordinal; } catch (InterruptedException e) { if (follow) { @@ -238,15 +239,15 @@ protected void printUsageSummary(PrintStream stderr) { public static class CLICause extends UserIdCause { - private String startedBy; + private String startedBy; - public CLICause(){ - startedBy = "unknown"; - } + public CLICause() { + startedBy = "unknown"; + } - public CLICause(String startedBy){ - this.startedBy = startedBy; - } + public CLICause(String startedBy) { + this.startedBy = startedBy; + } @Override public String getShortDescription() { diff --git a/core/src/main/java/hudson/cli/CLIAction.java b/core/src/main/java/hudson/cli/CLIAction.java index a5583b874c972..d42e974452a2c 100644 --- a/core/src/main/java/hudson/cli/CLIAction.java +++ b/core/src/main/java/hudson/cli/CLIAction.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -128,14 +129,17 @@ public void send(byte[] data) throws IOException { sentBytes += data.length; sentCount++; } + @Override public void close() throws IOException { doClose(); } } + private void doClose() { close(); } + @Override protected void opened() { try { @@ -156,6 +160,7 @@ protected void opened() { } }, "CLI handler for " + authentication.getName()).start(); } + @Override protected void binary(byte[] payload, int offset, int len) { try { @@ -166,10 +171,12 @@ protected void binary(byte[] payload, int offset, int len) { error(x); } } + @Override protected void error(Throwable cause) { LOGGER.log(Level.WARNING, null, cause); } + @Override protected void closed(int statusCode, String reason) { LOGGER.fine(() -> "closed: " + statusCode + ": " + reason); @@ -182,7 +189,7 @@ protected void closed(int statusCode, String reason) { @Override public Object getTarget() { StaplerRequest req = Stapler.getCurrentRequest(); - if (req.getRestOfPath().length()==0 && "POST".equals(req.getMethod())) { + if (req.getRestOfPath().length() == 0 && "POST".equals(req.getMethod())) { // CLI connection request if ("false".equals(req.getParameter("remoting"))) { throw new PlainCliEndpointResponse(); @@ -204,15 +211,18 @@ static class ServerSideImpl extends PlainCLIProtocol.ServerSide { private final PipedInputStream stdin = new PipedInputStream(); private final PipedOutputStream stdinMatch = new PipedOutputStream(); private final Authentication authentication; + ServerSideImpl(PlainCLIProtocol.Output out, Authentication authentication) throws IOException { super(out); stdinMatch.connect(stdin); this.authentication = authentication; } + @Override protected void onArg(String text) { args.add(text); } + @Override protected void onLocale(String text) { for (Locale _locale : Locale.getAvailableLocales()) { @@ -223,6 +233,7 @@ protected void onLocale(String text) { } LOGGER.log(Level.WARNING, "unknown client locale {0}", text); } + @Override protected void onEncoding(String text) { try { @@ -231,18 +242,22 @@ protected void onEncoding(String text) { LOGGER.log(Level.WARNING, "unknown client charset {0}", text); } } + @Override protected void onStart() { ready(); } + @Override protected void onStdin(byte[] chunk) throws IOException { stdinMatch.write(chunk); } + @Override protected void onEndStdin() throws IOException { stdinMatch.close(); } + @Override protected void handleClose() { ready(); @@ -250,10 +265,12 @@ protected void handleClose() { runningThread.interrupt(); } } + private synchronized void ready() { ready = true; notifyAll(); } + void run() throws IOException, InterruptedException { synchronized (this) { while (!ready) { diff --git a/core/src/main/java/hudson/cli/CLICommand.java b/core/src/main/java/hudson/cli/CLICommand.java index 198736dc9fca6..ab0a7266aec1d 100644 --- a/core/src/main/java/hudson/cli/CLICommand.java +++ b/core/src/main/java/hudson/cli/CLICommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -40,6 +41,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; +import java.io.UncheckedIOException; +import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Type; import java.nio.charset.Charset; @@ -114,15 +117,15 @@ public abstract class CLICommand implements ExtensionPoint, Cloneable { * (In contrast, calling {@code System.out.println(...)} would print out * the message to the server log file, which is probably not what you want. */ - public transient PrintStream stdout,stderr; + public transient PrintStream stdout, stderr; /** - * Shared text, which is reported back to CLI if an error happens in commands + * Shared text, which is reported back to CLI if an error happens in commands * taking lists of parameters. * @since 2.26 */ static final String CLI_LISTPARAM_SUMMARY_ERROR_TEXT = "Error occurred while performing this command, see previous stderr output."; - + /** * Connected to stdin of the CLI agent. * @@ -167,13 +170,13 @@ public abstract class CLICommand implements ExtensionPoint, Cloneable { public String getName() { String name = getClass().getName(); name = name.substring(name.lastIndexOf('.') + 1); // short name - name = name.substring(name.lastIndexOf('$')+1); - if(name.endsWith("Command")) - name = name.substring(0,name.length()-7); // trim off the command + name = name.substring(name.lastIndexOf('$') + 1); + if (name.endsWith("Command")) + name = name.substring(0, name.length() - 7); // trim off the command // convert "FooBarZot" into "foo-bar-zot" // Locale is fixed so that "CreateInstance" always become "create-instance" no matter where this is run. - return name.replaceAll("([a-z0-9])([A-Z])","$1-$2").toLowerCase(Locale.ENGLISH); + return name.replaceAll("([a-z0-9])([A-Z])", "$1-$2").toLowerCase(Locale.ENGLISH); } /** @@ -184,7 +187,7 @@ public String getName() { /** * Entry point to the CLI command. - * + * *

      * The default implementation uses args4j to parse command line arguments and call {@link #run()}, * but if that processing is undesirable, subtypes can directly override this method and leave {@link #run()} @@ -279,7 +282,7 @@ public int main(List args, Locale locale, InputStream stdin, PrintStream Functions.printStackTrace(e, stderr); return 1; } finally { - if(sc != null) + if (sc != null) sc.setAuthentication(old); // restore } } @@ -334,8 +337,8 @@ public Channel checkChannel() throws AbortException { * @since 2.266 */ public Authentication getTransportAuthentication2() { - Authentication a = transportAuth; - if (a==null) a = Jenkins.ANONYMOUS2; + Authentication a = transportAuth; + if (a == null) a = Jenkins.ANONYMOUS2; return a; } @@ -364,7 +367,7 @@ public void setTransportAuth(org.acegisecurity.Authentication transportAuth) { /** * Executes the command, and return the exit code. - * + * *

      * This is an internal contract between {@link CLICommand} and its subtype. * To execute CLI method from outside, use {@link #main(List, Locale, InputStream, PrintStream, PrintStream)} @@ -404,7 +407,19 @@ protected void printUsage(PrintStream stderr, CmdLineParser p) { public final String getSingleLineSummary() { ByteArrayOutputStream out = new ByteArrayOutputStream(); getCmdLineParser().printSingleLineUsage(out); - return out.toString(); + Charset charset; + try { + charset = getClientCharset(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + try { + return out.toString(charset.name()); + } catch (UnsupportedEncodingException e) { + throw new AssertionError(e); + } } /** @@ -414,7 +429,19 @@ public final String getSingleLineSummary() { public final String getUsage() { ByteArrayOutputStream out = new ByteArrayOutputStream(); getCmdLineParser().printUsage(out); - return out.toString(); + Charset charset; + try { + charset = getClientCharset(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + try { + return out.toString(charset.name()); + } catch (UnsupportedEncodingException e) { + throw new AssertionError(e); + } } /** @@ -423,17 +450,34 @@ public final String getUsage() { @Restricted(NoExternalUse.class) public final String getLongDescription() { ByteArrayOutputStream out = new ByteArrayOutputStream(); - PrintStream ps = new PrintStream(out); + Charset charset; + try { + charset = getClientCharset(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + PrintStream ps; + try { + ps = new PrintStream(out, false, charset.name()); + } catch (UnsupportedEncodingException e) { + throw new AssertionError(e); + } printUsageSummary(ps); ps.close(); - return out.toString(); + try { + return out.toString(charset.name()); + } catch (UnsupportedEncodingException e) { + throw new AssertionError(e); + } } /** * Called while producing usage. This is a good method to override * to render the general description of the command that goes beyond - * a single-line summary. + * a single-line summary. */ protected void printUsageSummary(PrintStream stderr) { stderr.println(getShortDescription()); @@ -492,9 +536,9 @@ protected CLICommand createClone() { */ protected void registerOptionHandlers() { try { - for (Class c : Index.list(OptionHandlerExtension.class, Jenkins.get().pluginManager.uberClassLoader,Class.class)) { + for (Class c : Index.list(OptionHandlerExtension.class, Jenkins.get().pluginManager.uberClassLoader, Class.class)) { Type t = Types.getBaseClass(c, OptionHandler.class); - CmdLineParser.registerHandler(Types.erasure(Types.getTypeArgument(t,0)), c); + CmdLineParser.registerHandler(Types.erasure(Types.getTypeArgument(t, 0)), c); } } catch (IOException e) { throw new Error(e); @@ -513,7 +557,7 @@ public static ExtensionList all() { */ public static CLICommand clone(String name) { for (CLICommand cmd : all()) - if(name.equals(cmd.getName())) + if (name.equals(cmd.getName())) return cmd.createClone(); return null; } @@ -547,10 +591,10 @@ public static CLICommand getCurrent() { final ResourceClassIterator itr = new DiscoverClasses(cls).findResourceClasses(servicesIter); - while(itr.hasNext()) { + while (itr.hasNext()) { Class h = itr.nextResourceClass().loadClass(); Class c = Types.erasure(Types.getTypeArgument(Types.getBaseClass(h, OptionHandler.class), 0)); - CmdLineParser.registerHandler(c,h); + CmdLineParser.registerHandler(c, h); } } } diff --git a/core/src/main/java/hudson/cli/CliCrumbExclusion.java b/core/src/main/java/hudson/cli/CliCrumbExclusion.java index f965477886107..4e3064f431782 100644 --- a/core/src/main/java/hudson/cli/CliCrumbExclusion.java +++ b/core/src/main/java/hudson/cli/CliCrumbExclusion.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; diff --git a/core/src/main/java/hudson/cli/CloneableCLICommand.java b/core/src/main/java/hudson/cli/CloneableCLICommand.java index f6a4c60b02c12..74d789179f5f8 100644 --- a/core/src/main/java/hudson/cli/CloneableCLICommand.java +++ b/core/src/main/java/hudson/cli/CloneableCLICommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; /** @@ -34,7 +35,7 @@ public abstract class CloneableCLICommand extends CLICommand implements Cloneabl @Override protected CLICommand createClone() { try { - return (CLICommand)clone(); + return (CLICommand) clone(); } catch (CloneNotSupportedException e) { throw new AssertionError(e); } diff --git a/core/src/main/java/hudson/cli/ConnectNodeCommand.java b/core/src/main/java/hudson/cli/ConnectNodeCommand.java index 6968bb274f77c..0d3e9049205ad 100644 --- a/core/src/main/java/hudson/cli/ConnectNodeCommand.java +++ b/core/src/main/java/hudson/cli/ConnectNodeCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.AbortException; @@ -41,10 +42,10 @@ public class ConnectNodeCommand extends CLICommand { @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") - @Argument(metaVar="NAME", usage="Agent name, or empty string for built-in node; comma-separated list is supported", required=true, multiValued=true) + @Argument(metaVar = "NAME", usage = "Agent name, or empty string for built-in node; comma-separated list is supported", required = true, multiValued = true) private List nodes; - @Option(name="-f", usage="Cancel any currently pending connect operation and retry from scratch") + @Option(name = "-f", usage = "Cancel any currently pending connect operation and retry from scratch") public boolean force = false; private static final Logger LOGGER = Logger.getLogger(ConnectNodeCommand.class.getName()); diff --git a/core/src/main/java/hudson/cli/Connection.java b/core/src/main/java/hudson/cli/Connection.java index fb2568717532c..eb97d996ff01f 100644 --- a/core/src/main/java/hudson/cli/Connection.java +++ b/core/src/main/java/hudson/cli/Connection.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -69,7 +70,7 @@ public class Connection { public final DataOutputStream dout; public Connection(Socket socket) throws IOException { - this(SocketChannelStream.in(socket),SocketChannelStream.out(socket)); + this(SocketChannelStream.in(socket), SocketChannelStream.out(socket)); } public Connection(InputStream in, OutputStream out) { @@ -118,7 +119,7 @@ public void writeObject(Object o) throws IOException { public T readObject() throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStreamEx(in, getClass().getClassLoader(), ClassFilter.DEFAULT); - return (T)ois.readObject(); + return (T) ois.readObject(); } public void writeKey(Key key) throws IOException { @@ -153,8 +154,9 @@ public byte[] readByteArray() throws IOException { * each other. */ public KeyAgreement diffieHellman(boolean side) throws IOException, GeneralSecurityException { - return diffieHellman(side,512); + return diffieHellman(side, 512); } + public KeyAgreement diffieHellman(boolean side, int keySize) throws IOException, GeneralSecurityException { KeyPair keyPair; PublicKey otherHalf; @@ -203,7 +205,7 @@ public Connection encryptConnection(SecretKey sessionKey, String algorithm) thro cin.init(Cipher.DECRYPT_MODE, sessionKey, createIv(sessionKey)); CipherInputStream i = new CipherInputStream(in, cin); - return new Connection(i,o); + return new Connection(i, o); } private IvParameterSpec createIv(SecretKey sessionKey) { @@ -218,8 +220,8 @@ private IvParameterSpec createIv(SecretKey sessionKey) { */ public static byte[] fold(byte[] bytes, int size) { byte[] r = new byte[size]; - for (int i=Math.max(bytes.length,size)-1; i>=0; i-- ) { - r[i%r.length] ^= bytes[i%bytes.length]; + for (int i = Math.max(bytes.length, size) - 1; i >= 0; i--) { + r[i % r.length] ^= bytes[i % bytes.length]; } return r; } @@ -231,7 +233,7 @@ private String detectKeyAlgorithm(KeyPair kp) { private String detectKeyAlgorithm(PublicKey kp) { if (kp instanceof RSAPublicKey) return "RSA"; if (kp instanceof DSAPublicKey) return "DSA"; - throw new IllegalArgumentException("Unknown public key type: "+kp); + throw new IllegalArgumentException("Unknown public key type: " + kp); } /** @@ -243,7 +245,7 @@ public void proveIdentity(byte[] sharedSecret, KeyPair key) throws IOException, writeUTF(algorithm); writeKey(key.getPublic()); - Signature sig = Signature.getInstance("SHA1with"+algorithm); + Signature sig = Signature.getInstance("SHA1with" + algorithm); sig.initSign(key.getPrivate()); sig.update(key.getPublic().getEncoded()); sig.update(sharedSecret); @@ -259,7 +261,7 @@ public PublicKey verifyIdentity(byte[] sharedSecret) throws IOException, General PublicKey spk = KeyFactory.getInstance(serverKeyAlgorithm).generatePublic(readKey()); // verify the identity of the server - Signature sig = Signature.getInstance("SHA1with"+serverKeyAlgorithm); + Signature sig = Signature.getInstance("SHA1with" + serverKeyAlgorithm); sig.initVerify(spk); sig.update(spk.getEncoded()); sig.update(sharedSecret); diff --git a/core/src/main/java/hudson/cli/ConsoleCommand.java b/core/src/main/java/hudson/cli/ConsoleCommand.java index 771a40b8c9f74..12d9ef1dff2d3 100644 --- a/core/src/main/java/hudson/cli/ConsoleCommand.java +++ b/core/src/main/java/hudson/cli/ConsoleCommand.java @@ -27,36 +27,36 @@ public String getShortDescription() { return Messages.ConsoleCommand_ShortDescription(); } - @Argument(metaVar="JOB",usage="Name of the job",required=true) - public Job job; + @Argument(metaVar = "JOB", usage = "Name of the job", required = true) + public Job job; - @Argument(metaVar="BUILD",usage="Build number or permalink to point to the build. Defaults to the last build",required=false,index=1) - public String build="lastBuild"; + @Argument(metaVar = "BUILD", usage = "Build number or permalink to point to the build. Defaults to the last build", required = false, index = 1) + public String build = "lastBuild"; - @Option(name="-f",usage="If the build is in progress, stay around and append console output as it comes, like 'tail -f'") + @Option(name = "-f", usage = "If the build is in progress, stay around and append console output as it comes, like 'tail -f'") public boolean follow = false; - @Option(name="-n",metaVar="N",usage="Display the last N lines") + @Option(name = "-n", metaVar = "N", usage = "Display the last N lines") public int n = -1; @Override protected int run() throws Exception { job.checkPermission(Item.READ); - Run run; + Run run; try { int n = Integer.parseInt(build); run = job.getBuildByNumber(n); - if (run==null) - throw new IllegalArgumentException("No such build #"+n); + if (run == null) + throw new IllegalArgumentException("No such build #" + n); } catch (NumberFormatException e) { // maybe a permalink? Permalink p = job.getPermalinks().get(build); - if (p!=null) { + if (p != null) { run = p.resolve(job); - if (run==null) - throw new IllegalStateException("Permalink "+build+" produced no build", e); + if (run == null) + throw new IllegalStateException("Permalink " + build + " produced no build", e); } else { Permalink nearest = job.getPermalinks().findNearest(build); throw new IllegalArgumentException(nearest == null ? @@ -68,7 +68,7 @@ protected int run() throws Exception { OutputStreamWriter w = new OutputStreamWriter(stdout, getClientCharset()); try { - long pos = n>=0 ? seek(run) : 0; + long pos = n >= 0 ? seek(run) : 0; if (follow) { AnnotatedLargeText logText; @@ -97,38 +97,39 @@ protected int run() throws Exception { private long seek(Run run) throws IOException { class RingBuffer { long[] lastNlines = new long[n]; - int ptr=0; + int ptr = 0; RingBuffer() { - for (int i=0; i=0) { - for (int i=0; i= 0) { + for (int i = 0; i < len; i++) { byte ch = buf[i]; - boolean isNL = ch=='\r' || ch=='\n'; + boolean isNL = ch == '\r' || ch == '\n'; if (!isNL && prevIsNL) rb.add(pos); - if (isNL && prevIsNL && !(prev=='\r' && ch=='\n')) rb.add(pos); + if (isNL && prevIsNL && !(prev == '\r' && ch == '\n')) rb.add(pos); pos++; prev = ch; prevIsNL = isNL; diff --git a/core/src/main/java/hudson/cli/CopyJobCommand.java b/core/src/main/java/hudson/cli/CopyJobCommand.java index 41aa8836b704e..021d34d761672 100644 --- a/core/src/main/java/hudson/cli/CopyJobCommand.java +++ b/core/src/main/java/hudson/cli/CopyJobCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -32,7 +33,7 @@ /** * Copies a job from CLI. - * + * * @author Kohsuke Kawaguchi */ @Extension @@ -42,18 +43,18 @@ public String getShortDescription() { return Messages.CopyJobCommand_ShortDescription(); } - @Argument(metaVar="SRC",usage="Name of the job to copy",required=true) + @Argument(metaVar = "SRC", usage = "Name of the job to copy", required = true) public TopLevelItem src; - @Argument(metaVar="DST",usage="Name of the new job to be created.",index=1,required=true) + @Argument(metaVar = "DST", usage = "Name of the new job to be created.", index = 1, required = true) public String dst; @Override protected int run() throws Exception { Jenkins jenkins = Jenkins.get(); - if (jenkins.getItemByFullName(dst)!=null) { - throw new IllegalStateException("Job '"+dst+"' already exists"); + if (jenkins.getItemByFullName(dst) != null) { + throw new IllegalStateException("Job '" + dst + "' already exists"); } ModifiableTopLevelItemGroup ig = jenkins; @@ -73,7 +74,7 @@ protected int run() throws Exception { dst = dst.substring(i + 1); } - ig.copy(src,dst).save(); + ig.copy(src, dst).save(); return 0; } } diff --git a/core/src/main/java/hudson/cli/CreateJobCommand.java b/core/src/main/java/hudson/cli/CreateJobCommand.java index 859d3e060c137..4b3dc23d98579 100644 --- a/core/src/main/java/hudson/cli/CreateJobCommand.java +++ b/core/src/main/java/hudson/cli/CreateJobCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -31,7 +32,7 @@ /** * Creates a new job by reading stdin as a configuration XML file. - * + * * @author Kohsuke Kawaguchi */ @Extension @@ -41,15 +42,15 @@ public String getShortDescription() { return Messages.CreateJobCommand_ShortDescription(); } - @Argument(metaVar="NAME",usage="Name of the job to create",required=true) + @Argument(metaVar = "NAME", usage = "Name of the job to create", required = true) public String name; @Override protected int run() throws Exception { Jenkins h = Jenkins.get(); - if (h.getItemByFullName(name)!=null) { - throw new IllegalStateException("Job '"+name+"' already exists"); + if (h.getItemByFullName(name) != null) { + throw new IllegalStateException("Job '" + name + "' already exists"); } ModifiableTopLevelItemGroup ig = h; diff --git a/core/src/main/java/hudson/cli/CreateNodeCommand.java b/core/src/main/java/hudson/cli/CreateNodeCommand.java index 81b91af89986a..24aa9256e0067 100644 --- a/core/src/main/java/hudson/cli/CreateNodeCommand.java +++ b/core/src/main/java/hudson/cli/CreateNodeCommand.java @@ -37,7 +37,7 @@ @Extension public class CreateNodeCommand extends CLICommand { - @Argument(metaVar="NODE", usage="Name of the node") + @Argument(metaVar = "NODE", usage = "Name of the node") public String nodeName; @Override diff --git a/core/src/main/java/hudson/cli/CreateViewCommand.java b/core/src/main/java/hudson/cli/CreateViewCommand.java index 0506c3a002376..db61aa5912767 100644 --- a/core/src/main/java/hudson/cli/CreateViewCommand.java +++ b/core/src/main/java/hudson/cli/CreateViewCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -36,7 +37,7 @@ @Extension public class CreateViewCommand extends CLICommand { - @Argument(usage="Name of the view to use instead of the one in XML") + @Argument(usage = "Name of the view to use instead of the one in XML") public String viewName = null; @Override diff --git a/core/src/main/java/hudson/cli/DeleteBuildsCommand.java b/core/src/main/java/hudson/cli/DeleteBuildsCommand.java index c0a86ad3cbc4f..6d62eb9db937f 100644 --- a/core/src/main/java/hudson/cli/DeleteBuildsCommand.java +++ b/core/src/main/java/hudson/cli/DeleteBuildsCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -65,7 +66,7 @@ protected int act(List> builds) throws IOException { } } - stdout.println("Deleted "+hsBuilds.size()+" builds"); + stdout.println("Deleted " + hsBuilds.size() + " builds"); return 0; } diff --git a/core/src/main/java/hudson/cli/DeleteJobCommand.java b/core/src/main/java/hudson/cli/DeleteJobCommand.java index f3c4924968f1e..b203fc59c1c25 100644 --- a/core/src/main/java/hudson/cli/DeleteJobCommand.java +++ b/core/src/main/java/hudson/cli/DeleteJobCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.AbortException; @@ -41,7 +42,7 @@ public class DeleteJobCommand extends CLICommand { @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") - @Argument(usage="Name of the job(s) to delete", required=true, multiValued=true) + @Argument(usage = "Name of the job(s) to delete", required = true, multiValued = true) private List jobs; @Override @@ -58,20 +59,20 @@ protected int run() throws Exception { final HashSet hs = new HashSet<>(jobs); - for (String job_s: hs) { + for (String job_s : hs) { AbstractItem job; try { job = (AbstractItem) jenkins.getItemByFullName(job_s); - if(job == null) { + if (job == null) { throw new IllegalArgumentException("No such job '" + job_s + "'"); } job.checkPermission(Item.DELETE); job.delete(); } catch (Exception e) { - if(hs.size() == 1) { + if (hs.size() == 1) { throw e; } diff --git a/core/src/main/java/hudson/cli/DeleteNodeCommand.java b/core/src/main/java/hudson/cli/DeleteNodeCommand.java index 1b77a8e20eabe..5989aa247b672 100644 --- a/core/src/main/java/hudson/cli/DeleteNodeCommand.java +++ b/core/src/main/java/hudson/cli/DeleteNodeCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.AbortException; @@ -40,7 +41,7 @@ public class DeleteNodeCommand extends CLICommand { @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") - @Argument(usage="Names of nodes to delete", required=true, multiValued=true) + @Argument(usage = "Names of nodes to delete", required = true, multiValued = true) private List nodes; @Override @@ -69,7 +70,7 @@ protected int run() throws Exception { node.toComputer().doDoDelete(); } catch (Exception e) { - if(hs.size() == 1) { + if (hs.size() == 1) { throw e; } diff --git a/core/src/main/java/hudson/cli/DeleteViewCommand.java b/core/src/main/java/hudson/cli/DeleteViewCommand.java index 436bf34f30d35..33a1743464b43 100644 --- a/core/src/main/java/hudson/cli/DeleteViewCommand.java +++ b/core/src/main/java/hudson/cli/DeleteViewCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.AbortException; @@ -40,7 +41,7 @@ public class DeleteViewCommand extends CLICommand { @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") - @Argument(usage="View names to delete", required=true, multiValued=true) + @Argument(usage = "View names to delete", required = true, multiValued = true) private List views; @Override @@ -59,7 +60,7 @@ protected int run() throws Exception { ViewOptionHandler voh = new ViewOptionHandler(null, null, null); - for(String view_s : hs) { + for (String view_s : hs) { View view; try { @@ -80,7 +81,7 @@ protected int run() throws Exception { group.deleteView(view); } catch (Exception e) { - if(hs.size() == 1) { + if (hs.size() == 1) { throw e; } diff --git a/core/src/main/java/hudson/cli/DisablePluginCommand.java b/core/src/main/java/hudson/cli/DisablePluginCommand.java index 79d3a09f82501..53af28828ddb6 100644 --- a/core/src/main/java/hudson/cli/DisablePluginCommand.java +++ b/core/src/main/java/hudson/cli/DisablePluginCommand.java @@ -221,13 +221,13 @@ private int getResultCode(List results) { */ private int getResultCode(PluginWrapper.PluginDisableResult result) { int returnCode = 0; - switch (result.getStatus()){ + switch (result.getStatus()) { case NOT_DISABLED_DEPENDANTS: returnCode = RETURN_CODE_NOT_DISABLED_DEPENDANTS; break; case NO_SUCH_PLUGIN: returnCode = RETURN_CODE_NO_SUCH_PLUGIN; - break; + break; default: for (PluginWrapper.PluginDisableResult oneDependentResult : result.getDependentsDisableStatus()) { returnCode = getResultCode(oneDependentResult); diff --git a/core/src/main/java/hudson/cli/DisconnectNodeCommand.java b/core/src/main/java/hudson/cli/DisconnectNodeCommand.java index 4ae3b057532d2..eb080cf1eb987 100644 --- a/core/src/main/java/hudson/cli/DisconnectNodeCommand.java +++ b/core/src/main/java/hudson/cli/DisconnectNodeCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.AbortException; diff --git a/core/src/main/java/hudson/cli/GetJobCommand.java b/core/src/main/java/hudson/cli/GetJobCommand.java index f26ad48bdb3a4..d94044ef461c2 100644 --- a/core/src/main/java/hudson/cli/GetJobCommand.java +++ b/core/src/main/java/hudson/cli/GetJobCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -32,7 +33,7 @@ */ @Extension public class GetJobCommand extends CLICommand { - @Argument(metaVar="JOB",usage="Name of the job",required=true) + @Argument(metaVar = "JOB", usage = "Name of the job", required = true) public AbstractItem job; @Override diff --git a/core/src/main/java/hudson/cli/GetNodeCommand.java b/core/src/main/java/hudson/cli/GetNodeCommand.java index d508a59407593..62dd21826029e 100644 --- a/core/src/main/java/hudson/cli/GetNodeCommand.java +++ b/core/src/main/java/hudson/cli/GetNodeCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -37,7 +38,7 @@ @Extension public class GetNodeCommand extends CLICommand { - @Argument(metaVar="NODE", usage="Name of the node", required=true) + @Argument(metaVar = "NODE", usage = "Name of the node", required = true) public Node node; @Override diff --git a/core/src/main/java/hudson/cli/GetViewCommand.java b/core/src/main/java/hudson/cli/GetViewCommand.java index 1486d324ebc82..e94bb7947a812 100644 --- a/core/src/main/java/hudson/cli/GetViewCommand.java +++ b/core/src/main/java/hudson/cli/GetViewCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -34,7 +35,7 @@ @Extension public class GetViewCommand extends CLICommand { - @Argument(usage="Name of the view to obtain", required=true) + @Argument(usage = "Name of the view to obtain", required = true) private View view; @Override diff --git a/core/src/main/java/hudson/cli/GroovyCommand.java b/core/src/main/java/hudson/cli/GroovyCommand.java index bb894bf5389c3..0d7e45e6ca18c 100644 --- a/core/src/main/java/hudson/cli/GroovyCommand.java +++ b/core/src/main/java/hudson/cli/GroovyCommand.java @@ -21,12 +21,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import groovy.lang.Binding; import groovy.lang.GroovyShell; import hudson.Extension; import java.io.IOException; +import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; @@ -47,13 +49,13 @@ public String getShortDescription() { return Messages.GroovyCommand_ShortDescription(); } - @Argument(metaVar="SCRIPT",usage="Script to be executed. Only '=' (to represent stdin) is supported.") + @Argument(metaVar = "SCRIPT", usage = "Script to be executed. Only '=' (to represent stdin) is supported.") public String script; /** * Remaining arguments. */ - @Argument(metaVar="ARGUMENTS", index=1, usage="Command line arguments to pass into script.") + @Argument(metaVar = "ARGUMENTS", index = 1, usage = "Command line arguments to pass into script.") public List remaining = new ArrayList<>(); @Override @@ -62,13 +64,13 @@ protected int run() throws Exception { Jenkins.get().checkPermission(Jenkins.ADMINISTER); Binding binding = new Binding(); - binding.setProperty("out",new PrintWriter(stdout,true)); - binding.setProperty("stdin",stdin); - binding.setProperty("stdout",stdout); - binding.setProperty("stderr",stderr); + binding.setProperty("out", new PrintWriter(new OutputStreamWriter(stdout, getClientCharset()), true)); + binding.setProperty("stdin", stdin); + binding.setProperty("stdout", stdout); + binding.setProperty("stderr", stderr); GroovyShell groovy = new GroovyShell(Jenkins.get().getPluginManager().uberClassLoader, binding); - groovy.run(loadScript(),"RemoteClass",remaining.toArray(new String[0])); + groovy.run(loadScript(), "RemoteClass", remaining.toArray(new String[0])); return 0; } @@ -76,7 +78,7 @@ protected int run() throws Exception { * Loads the script from the argument. */ private String loadScript() throws CmdLineException, IOException, InterruptedException { - if(script==null) + if (script == null) throw new CmdLineException(null, "No script is specified"); if (script.equals("=")) return IOUtils.toString(stdin); diff --git a/core/src/main/java/hudson/cli/GroovyshCommand.java b/core/src/main/java/hudson/cli/GroovyshCommand.java index d7eb47453be3a..4f6c741c8a472 100644 --- a/core/src/main/java/hudson/cli/GroovyshCommand.java +++ b/core/src/main/java/hudson/cli/GroovyshCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -28,9 +29,13 @@ import groovy.lang.Closure; import hudson.Extension; import java.io.BufferedInputStream; +import java.io.IOException; import java.io.InputStream; +import java.io.OutputStreamWriter; import java.io.PrintStream; import java.io.PrintWriter; +import java.io.UncheckedIOException; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import jenkins.model.Jenkins; @@ -54,7 +59,7 @@ public String getShortDescription() { return Messages.GroovyshCommand_ShortDescription(); } - @Argument(metaVar="ARGS") public List args = new ArrayList<>(); + @Argument(metaVar = "ARGS") public List args = new ArrayList<>(); @Override protected int run() { @@ -83,23 +88,31 @@ protected Groovysh createShell(InputStream stdin, PrintStream stdout, Binding binding = new Binding(); // redirect "println" to the CLI - binding.setProperty("out", new PrintWriter(stdout,true)); + Charset charset; + try { + charset = getClientCharset(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + binding.setProperty("out", new PrintWriter(new OutputStreamWriter(stdout, charset), true)); binding.setProperty("hudson", Jenkins.get()); // backward compatibility binding.setProperty("jenkins", Jenkins.get()); - IO io = new IO(new BufferedInputStream(stdin),stdout,stderr); + IO io = new IO(new BufferedInputStream(stdin), stdout, stderr); final ClassLoader cl = Jenkins.get().pluginManager.uberClassLoader; Closure registrar = new Closure(null, null) { private static final long serialVersionUID = 1L; @SuppressWarnings("unused") - @SuppressFBWarnings(value="UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS",justification="Closure invokes this via reflection") + @SuppressFBWarnings(value = "UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS", justification = "Closure invokes this via reflection") public Object doCall(Object[] args) { assert args.length == 1; assert args[0] instanceof Shell; - Shell shell = (Shell)args[0]; + Shell shell = (Shell) args[0]; XmlCommandRegistrar r = new XmlCommandRegistrar(shell, cl); r.register(GroovyshCommand.class.getResource("commands.xml")); diff --git a/core/src/main/java/hudson/cli/HelpCommand.java b/core/src/main/java/hudson/cli/HelpCommand.java index 0743dc8e4d840..9e606102894b6 100644 --- a/core/src/main/java/hudson/cli/HelpCommand.java +++ b/core/src/main/java/hudson/cli/HelpCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.AbortException; @@ -39,7 +40,7 @@ @Extension public class HelpCommand extends CLICommand { - @Argument(metaVar="COMMAND", usage="Name of the command") + @Argument(metaVar = "COMMAND", usage = "Name of the command") public String command; @Override @@ -63,13 +64,13 @@ protected int run() throws Exception { } private int showAllCommands() { - Map commands = new TreeMap<>(); + Map commands = new TreeMap<>(); for (CLICommand c : CLICommand.all()) - commands.put(c.getName(),c); + commands.put(c.getName(), c); for (CLICommand c : commands.values()) { - stderr.println(" "+c.getName()); - stderr.println(" "+c.getShortDescription()); + stderr.println(" " + c.getName()); + stderr.println(" " + c.getShortDescription()); } return 0; @@ -83,7 +84,7 @@ private int showCommandDetails() throws Exception { } command.printUsage(stderr, command.getCmdLineParser()); - + return 0; } } diff --git a/core/src/main/java/hudson/cli/InstallPluginCommand.java b/core/src/main/java/hudson/cli/InstallPluginCommand.java index d39c13f6a8c8b..cc9d3b59f91d4 100644 --- a/core/src/main/java/hudson/cli/InstallPluginCommand.java +++ b/core/src/main/java/hudson/cli/InstallPluginCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.AbortException; @@ -48,7 +49,7 @@ /** * Installs a plugin either from a file, an URL, or from update center. - * + * * @author Kohsuke Kawaguchi * @since 1.331 */ @@ -60,7 +61,7 @@ public String getShortDescription() { return Messages.InstallPluginCommand_ShortDescription(); } - @Argument(metaVar="SOURCE",required=true,usage= + @Argument(metaVar = "SOURCE", required = true, usage = "If this is an URL, Jenkins downloads the URL and installs that as a plugin. " + "If it is the string ‘=’, the file will be read from standard input of the command. " + "Otherwise the name is assumed to be the short name of the plugin in the existing update center (like ‘findbugs’), " + @@ -73,10 +74,10 @@ public String getShortDescription() { @Option(name = "-name", usage = "No longer used.") public String name; - @Option(name="-restart",usage="Restart Jenkins upon successful installation.") + @Option(name = "-restart", usage = "Restart Jenkins upon successful installation.") public boolean restart; - @Option(name="-deploy",usage="Deploy plugins right away without postponing them until the reboot.") + @Option(name = "-deploy", usage = "Deploy plugins right away without postponing them until the reboot.") public boolean dynamicLoad; @Override @@ -124,15 +125,15 @@ protected int run() throws Exception { } else { // try to find matching min version number VersionNumber version = new VersionNumber(source.substring(index + 1)); - p = h.getUpdateCenter().getPlugin(source.substring(0,index), version); + p = h.getUpdateCenter().getPlugin(source.substring(0, index), version); if (p == null) { p = h.getUpdateCenter().getPlugin(source); } } - if (p!=null) { + if (p != null) { stdout.println(Messages.InstallPluginCommand_InstallingFromUpdateCenter(source)); Throwable e = p.deploy(dynamicLoad).get().getError(); - if (e!=null) { + if (e != null) { AbortException myException = new AbortException("Failed to install plugin " + source); myException.initCause(e); throw myException; @@ -150,12 +151,12 @@ protected int run() throws Exception { Set candidates = new HashSet<>(); for (UpdateSite s : h.getUpdateCenter().getSites()) { Data dt = s.getData(); - if (dt==null) + if (dt == null) stdout.println(Messages.InstallPluginCommand_NoUpdateDataRetrieved(s.getUrl())); else candidates.addAll(dt.plugins.keySet()); } - stdout.println(Messages.InstallPluginCommand_DidYouMean(source,EditDistance.findNearest(source,candidates))); + stdout.println(Messages.InstallPluginCommand_DidYouMean(source, EditDistance.findNearest(source, candidates))); } } diff --git a/core/src/main/java/hudson/cli/ListChangesCommand.java b/core/src/main/java/hudson/cli/ListChangesCommand.java index 618e4d93346ce..6c65f3ef8b2df 100644 --- a/core/src/main/java/hudson/cli/ListChangesCommand.java +++ b/core/src/main/java/hudson/cli/ListChangesCommand.java @@ -5,7 +5,10 @@ import hudson.scm.ChangeLogSet; import hudson.util.QuotedStringTokenizer; import java.io.IOException; +import java.io.OutputStreamWriter; import java.io.PrintWriter; +import java.io.UncheckedIOException; +import java.nio.charset.Charset; import java.util.List; import jenkins.scm.RunWithSCM; import org.kohsuke.accmod.Restricted; @@ -37,7 +40,7 @@ enum Format { XML, CSV, PLAIN } - @Option(name="-format",usage="Controls how the output from this command is printed.") + @Option(name = "-format", usage = "Controls how the output from this command is printed.") public Format format = Format.PLAIN; @Override @@ -46,7 +49,15 @@ protected int act(List> builds) throws IOException { // No other permission check needed. switch (format) { case XML: - PrintWriter w = new PrintWriter(stdout); + Charset charset; + try { + charset = getClientCharset(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + PrintWriter w = new PrintWriter(new OutputStreamWriter(stdout, charset)); w.println(""); for (Run build : builds) { if (build instanceof RunWithSCM) { diff --git a/core/src/main/java/hudson/cli/ListJobsCommand.java b/core/src/main/java/hudson/cli/ListJobsCommand.java index 67207ba3ebccd..1a366227ddbc6 100644 --- a/core/src/main/java/hudson/cli/ListJobsCommand.java +++ b/core/src/main/java/hudson/cli/ListJobsCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -34,7 +35,7 @@ /** * Lists all jobs (in a specific view). - * + * * @author Michael Koch */ @Extension @@ -44,7 +45,7 @@ public String getShortDescription() { return Messages.ListJobsCommand_ShortDescription(); } - @Argument(metaVar="NAME",usage="Name of the view",required=false) + @Argument(metaVar = "NAME", usage = "Name of the view", required = false) public String name; @Override diff --git a/core/src/main/java/hudson/cli/ListPluginsCommand.java b/core/src/main/java/hudson/cli/ListPluginsCommand.java index 1b3b657d8ac3d..9312bedb10ff2 100644 --- a/core/src/main/java/hudson/cli/ListPluginsCommand.java +++ b/core/src/main/java/hudson/cli/ListPluginsCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -50,7 +51,7 @@ public String getShortDescription() { protected int run() { Jenkins h = Jenkins.get(); h.checkPermission(Jenkins.ADMINISTER); - + PluginManager pluginManager = h.getPluginManager(); if (this.name != null) { diff --git a/core/src/main/java/hudson/cli/OnlineNodeCommand.java b/core/src/main/java/hudson/cli/OnlineNodeCommand.java index eaaf2a50e92e3..e4a37fa74c6ed 100644 --- a/core/src/main/java/hudson/cli/OnlineNodeCommand.java +++ b/core/src/main/java/hudson/cli/OnlineNodeCommand.java @@ -68,7 +68,7 @@ protected int run() throws Exception { } } - if (errorOccurred){ + if (errorOccurred) { throw new AbortException(CLI_LISTPARAM_SUMMARY_ERROR_TEXT); } return 0; diff --git a/core/src/main/java/hudson/cli/QuietDownCommand.java b/core/src/main/java/hudson/cli/QuietDownCommand.java index 6df018abddbdd..c4cd7e02a97fc 100644 --- a/core/src/main/java/hudson/cli/QuietDownCommand.java +++ b/core/src/main/java/hudson/cli/QuietDownCommand.java @@ -40,13 +40,13 @@ public class QuietDownCommand extends CLICommand { private static final Logger LOGGER = Logger.getLogger(QuietDownCommand.class.getName()); - @Option(name="-block",usage="Block until the system really quiets down and no builds are running") + @Option(name = "-block", usage = "Block until the system really quiets down and no builds are running") public boolean block = false; - @Option(name="-timeout",usage="If non-zero, only block up to the specified number of milliseconds") + @Option(name = "-timeout", usage = "If non-zero, only block up to the specified number of milliseconds") public int timeout = 0; - @Option(name="-reason",usage="Reason for quiet down that will be visible to users") + @Option(name = "-reason", usage = "Reason for quiet down that will be visible to users") public String reason = null; @Override diff --git a/core/src/main/java/hudson/cli/ReloadJobCommand.java b/core/src/main/java/hudson/cli/ReloadJobCommand.java index b2bac818f409c..cea8823144bc9 100644 --- a/core/src/main/java/hudson/cli/ReloadJobCommand.java +++ b/core/src/main/java/hudson/cli/ReloadJobCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.AbortException; @@ -43,7 +44,7 @@ @Extension public class ReloadJobCommand extends CLICommand { - @Argument(usage="Name of the job(s) to reload", required=true, multiValued=true) + @Argument(usage = "Name of the job(s) to reload", required = true, multiValued = true) private List jobs; private static final Logger LOGGER = Logger.getLogger(ReloadJobCommand.class.getName()); @@ -62,7 +63,7 @@ protected int run() throws Exception { final HashSet hs = new HashSet<>(jobs); - for (String job_s: hs) { + for (String job_s : hs) { AbstractItem job = null; try { @@ -73,7 +74,7 @@ protected int run() throws Exception { LOGGER.log(Level.WARNING, "Unsupported item type: {0}", item.getClass().getName()); } - if(job == null) { + if (job == null) { AbstractItem project = Items.findNearest(AbstractItem.class, job_s, jenkins); throw new IllegalArgumentException(project == null ? "No such item \u2018" + job_s + "\u2019 exists." : @@ -84,7 +85,7 @@ protected int run() throws Exception { job.checkPermission(Item.CONFIGURE); job.doReload(); } catch (Exception e) { - if(hs.size() == 1) { + if (hs.size() == 1) { throw e; } diff --git a/core/src/main/java/hudson/cli/RemoveJobFromViewCommand.java b/core/src/main/java/hudson/cli/RemoveJobFromViewCommand.java index 1da9f978d11c3..416796b82e464 100644 --- a/core/src/main/java/hudson/cli/RemoveJobFromViewCommand.java +++ b/core/src/main/java/hudson/cli/RemoveJobFromViewCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -37,10 +38,10 @@ @Extension public class RemoveJobFromViewCommand extends CLICommand { - @Argument(usage="Name of the view", required=true, index=0) + @Argument(usage = "Name of the view", required = true, index = 0) private View view; - @Argument(usage="Job names", required=true, index=1) + @Argument(usage = "Job names", required = true, index = 1) private List jobs; @Override @@ -55,7 +56,7 @@ protected int run() throws Exception { if (!(view instanceof DirectlyModifiableView)) throw new IllegalStateException("'" + view.getDisplayName() + "' view can not be modified directly"); - for (TopLevelItem job: jobs) { + for (TopLevelItem job : jobs) { ((DirectlyModifiableView) view).remove(job); } diff --git a/core/src/main/java/hudson/cli/RunRangeCommand.java b/core/src/main/java/hudson/cli/RunRangeCommand.java index a7cee1eb7c1f8..6d6afe11caa11 100644 --- a/core/src/main/java/hudson/cli/RunRangeCommand.java +++ b/core/src/main/java/hudson/cli/RunRangeCommand.java @@ -12,18 +12,18 @@ * @since 2.62 */ public abstract class RunRangeCommand extends CLICommand { - @Argument(metaVar="JOB",usage="Name of the job to build",required=true,index=0) - public Job job; + @Argument(metaVar = "JOB", usage = "Name of the job to build", required = true, index = 0) + public Job job; - @Argument(metaVar="RANGE",usage="Range of the build records to delete. 'N-M', 'N,M', or 'N'",required=true,index=1) + @Argument(metaVar = "RANGE", usage = "Range of the build records to delete. 'N-M', 'N,M', or 'N'", required = true, index = 1) public String range; @Override protected int run() throws Exception { - RangeSet rs = RangeSet.fromString(range,false); + RangeSet rs = RangeSet.fromString(range, false); - return act((List)job.getBuilds(rs)); + return act((List) job.getBuilds(rs)); } - protected abstract int act(List> builds) throws IOException; + protected abstract int act(List> builds) throws IOException; } diff --git a/core/src/main/java/hudson/cli/SetBuildDescriptionCommand.java b/core/src/main/java/hudson/cli/SetBuildDescriptionCommand.java index 6560479f22f42..458e22419369f 100644 --- a/core/src/main/java/hudson/cli/SetBuildDescriptionCommand.java +++ b/core/src/main/java/hudson/cli/SetBuildDescriptionCommand.java @@ -18,30 +18,30 @@ public String getShortDescription() { return Messages.SetBuildDescriptionCommand_ShortDescription(); } - @Argument(metaVar="JOB",usage="Name of the job to build",required=true,index=0) - public transient Job job; + @Argument(metaVar = "JOB", usage = "Name of the job to build", required = true, index = 0) + public transient Job job; - @Argument(metaVar="BUILD#",usage="Number of the build",required=true,index=1) + @Argument(metaVar = "BUILD#", usage = "Number of the build", required = true, index = 1) public int number; - - @Argument(metaVar="DESCRIPTION",required=true,usage="Description to be set. '=' to read from stdin.", index=2) + + @Argument(metaVar = "DESCRIPTION", required = true, usage = "Description to be set. '=' to read from stdin.", index = 2) public String description; @Override protected int run() throws Exception { - Run run = job.getBuildByNumber(number); + Run run = job.getBuildByNumber(number); if (run == null) - throw new IllegalArgumentException("No such build #"+number); + throw new IllegalArgumentException("No such build #" + number); run.checkPermission(Run.UPDATE); if ("=".equals(description)) { - description = IOUtils.toString(stdin); + description = IOUtils.toString(stdin); } - + run.setDescription(description); - + return 0; } - + } diff --git a/core/src/main/java/hudson/cli/SetBuildDisplayNameCommand.java b/core/src/main/java/hudson/cli/SetBuildDisplayNameCommand.java index e07a115f4f63a..08befa394684c 100644 --- a/core/src/main/java/hudson/cli/SetBuildDisplayNameCommand.java +++ b/core/src/main/java/hudson/cli/SetBuildDisplayNameCommand.java @@ -16,13 +16,13 @@ public String getShortDescription() { return Messages.SetBuildDisplayNameCommand_ShortDescription(); } - @Argument(metaVar="JOB", usage="Name of the job to build", required=true, index=0) + @Argument(metaVar = "JOB", usage = "Name of the job to build", required = true, index = 0) public transient Job job; - @Argument(metaVar="BUILD#", usage="Number of the build", required=true, index=1) + @Argument(metaVar = "BUILD#", usage = "Number of the build", required = true, index = 1) public int number; - @Argument(metaVar="DISPLAYNAME", required=true, usage="DisplayName to be set. '-' to read from stdin.", index=2) + @Argument(metaVar = "DISPLAYNAME", required = true, usage = "DisplayName to be set. '-' to read from stdin.", index = 2) public String displayName; @Override diff --git a/core/src/main/java/hudson/cli/UpdateJobCommand.java b/core/src/main/java/hudson/cli/UpdateJobCommand.java index 77649867ec812..396d2d229cc2b 100644 --- a/core/src/main/java/hudson/cli/UpdateJobCommand.java +++ b/core/src/main/java/hudson/cli/UpdateJobCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -34,7 +35,7 @@ */ @Extension public class UpdateJobCommand extends CLICommand { - @Argument(metaVar="JOB",usage="Name of the job",required=true) + @Argument(metaVar = "JOB", usage = "Name of the job", required = true) public AbstractItem job; @Override @@ -44,7 +45,7 @@ public String getShortDescription() { @Override protected int run() throws Exception { - job.updateByXml((Source)new StreamSource(stdin)); + job.updateByXml((Source) new StreamSource(stdin)); return 0; } } diff --git a/core/src/main/java/hudson/cli/UpdateNodeCommand.java b/core/src/main/java/hudson/cli/UpdateNodeCommand.java index 1d311908cb5f1..c9210f89cc689 100644 --- a/core/src/main/java/hudson/cli/UpdateNodeCommand.java +++ b/core/src/main/java/hudson/cli/UpdateNodeCommand.java @@ -37,7 +37,7 @@ @Extension public class UpdateNodeCommand extends CLICommand { - @Argument(metaVar="NODE", usage="Name of the node", required=true) + @Argument(metaVar = "NODE", usage = "Name of the node", required = true) public Node node; @Override diff --git a/core/src/main/java/hudson/cli/UpdateViewCommand.java b/core/src/main/java/hudson/cli/UpdateViewCommand.java index d952ae5d03441..36561f34f3f0c 100644 --- a/core/src/main/java/hudson/cli/UpdateViewCommand.java +++ b/core/src/main/java/hudson/cli/UpdateViewCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -35,7 +36,7 @@ @Extension public class UpdateViewCommand extends CLICommand { - @Argument(usage="Name of the view to update", required=true) + @Argument(usage = "Name of the view to update", required = true) private View view; @Override diff --git a/core/src/main/java/hudson/cli/VersionCommand.java b/core/src/main/java/hudson/cli/VersionCommand.java index 17b9cc1d4ad8a..8b77c417d187c 100644 --- a/core/src/main/java/hudson/cli/VersionCommand.java +++ b/core/src/main/java/hudson/cli/VersionCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; diff --git a/core/src/main/java/hudson/cli/WaitNodeOfflineCommand.java b/core/src/main/java/hudson/cli/WaitNodeOfflineCommand.java index 319e4424a9e44..fee99ef6bf1a0 100644 --- a/core/src/main/java/hudson/cli/WaitNodeOfflineCommand.java +++ b/core/src/main/java/hudson/cli/WaitNodeOfflineCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -35,7 +36,7 @@ @Extension public class WaitNodeOfflineCommand extends CLICommand { - @Argument(metaVar="NODE", usage="Name of the node", required=true) + @Argument(metaVar = "NODE", usage = "Name of the node", required = true) public Node node; @Override diff --git a/core/src/main/java/hudson/cli/WaitNodeOnlineCommand.java b/core/src/main/java/hudson/cli/WaitNodeOnlineCommand.java index 2e9713ad6f4cd..95a621b087b03 100644 --- a/core/src/main/java/hudson/cli/WaitNodeOnlineCommand.java +++ b/core/src/main/java/hudson/cli/WaitNodeOnlineCommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -35,7 +36,7 @@ @Extension public class WaitNodeOnlineCommand extends CLICommand { - @Argument(metaVar="NODE", usage="Name of the node", required=true) + @Argument(metaVar = "NODE", usage = "Name of the node", required = true) public Node node; @Override diff --git a/core/src/main/java/hudson/cli/WhoAmICommand.java b/core/src/main/java/hudson/cli/WhoAmICommand.java index 19db3787c3034..a4ecc4af79d06 100644 --- a/core/src/main/java/hudson/cli/WhoAmICommand.java +++ b/core/src/main/java/hudson/cli/WhoAmICommand.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli; import hudson.Extension; @@ -43,10 +44,10 @@ public String getShortDescription() { @Override protected int run() { Authentication a = Jenkins.getAuthentication2(); - stdout.println("Authenticated as: "+a.getName()); + stdout.println("Authenticated as: " + a.getName()); stdout.println("Authorities:"); for (GrantedAuthority ga : a.getAuthorities()) { - stdout.println(" "+ga.getAuthority()); + stdout.println(" " + ga.getAuthority()); } return 0; } diff --git a/core/src/main/java/hudson/cli/declarative/CLIMethod.java b/core/src/main/java/hudson/cli/declarative/CLIMethod.java index 2aecb963df3fd..7b9c35202bb90 100644 --- a/core/src/main/java/hudson/cli/declarative/CLIMethod.java +++ b/core/src/main/java/hudson/cli/declarative/CLIMethod.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli.declarative; import static java.lang.annotation.ElementType.METHOD; @@ -63,7 +64,7 @@ @Documented public @interface CLIMethod { /** - * CLI command name. Used as {@link CLICommand#getName()} + * CLI command name. Used as {@link CLICommand#getName()} */ String name(); diff --git a/core/src/main/java/hudson/cli/declarative/CLIRegisterer.java b/core/src/main/java/hudson/cli/declarative/CLIRegisterer.java index 13b2841db0948..8b2f2348c577a 100644 --- a/core/src/main/java/hudson/cli/declarative/CLIRegisterer.java +++ b/core/src/main/java/hudson/cli/declarative/CLIRegisterer.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli.declarative; import static java.util.logging.Level.SEVERE; @@ -79,8 +80,8 @@ public ExtensionComponentSet refresh() throws ExtensionRefreshException { @Override public Collection> find(Class type, Hudson jenkins) { - if (type==CLICommand.class) - return (List)discover(jenkins); + if (type == CLICommand.class) + return (List) discover(jenkins); else return Collections.emptyList(); } @@ -90,9 +91,9 @@ public Collection> find(Class type, Hudson jenkins) */ private Method findResolver(Class type) throws IOException { List resolvers = Util.filter(Index.list(CLIResolver.class, Jenkins.get().getPluginManager().uberClassLoader), Method.class); - for ( ; type!=null; type=type.getSuperclass()) + for ( ; type != null; type = type.getSuperclass()) for (Method m : resolvers) - if (m.getReturnType()==type) + if (m.getReturnType() == type) return m; return null; } @@ -102,13 +103,13 @@ private List> discover(@NonNull final Jenkins jen List> r = new ArrayList<>(); try { - for ( final Method m : Util.filter(Index.list(CLIMethod.class, jenkins.getPluginManager().uberClassLoader),Method.class)) { + for (final Method m : Util.filter(Index.list(CLIMethod.class, jenkins.getPluginManager().uberClassLoader), Method.class)) { try { // command name final String name = m.getAnnotation(CLIMethod.class).name(); final ResourceBundleHolder res = loadMessageBundle(m); - res.format("CLI."+name+".shortDescription"); // make sure we have the resource, to fail early + res.format("CLI." + name + ".shortDescription"); // make sure we have the resource, to fail early r.add(new ExtensionComponent<>(new CloneableCLICommand() { @Override @@ -277,11 +278,11 @@ protected int run() throws Exception { } })); } catch (ClassNotFoundException | MissingResourceException e) { - LOGGER.log(SEVERE,"Failed to process @CLIMethod: "+m,e); + LOGGER.log(SEVERE, "Failed to process @CLIMethod: " + m, e); } } } catch (IOException e) { - LOGGER.log(SEVERE, "Failed to discover @CLIMethod",e); + LOGGER.log(SEVERE, "Failed to discover @CLIMethod", e); } return r; diff --git a/core/src/main/java/hudson/cli/declarative/CLIResolver.java b/core/src/main/java/hudson/cli/declarative/CLIResolver.java index 71c3cf4e23888..80f1d19edff4e 100644 --- a/core/src/main/java/hudson/cli/declarative/CLIResolver.java +++ b/core/src/main/java/hudson/cli/declarative/CLIResolver.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli.declarative; import static java.lang.annotation.ElementType.METHOD; diff --git a/core/src/main/java/hudson/cli/declarative/MethodBinder.java b/core/src/main/java/hudson/cli/declarative/MethodBinder.java index 08438aac9d870..91dfd11da7f09 100644 --- a/core/src/main/java/hudson/cli/declarative/MethodBinder.java +++ b/core/src/main/java/hudson/cli/declarative/MethodBinder.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli.declarative; import hudson.cli.CLICommand; @@ -93,15 +94,15 @@ public AnnotatedElement asAnnotatedElement() { } }; Option option = p.annotation(Option.class); - if (option!=null) { - parser.addOption(setter,option); + if (option != null) { + parser.addOption(setter, option); } Argument arg = p.annotation(Argument.class); - if (arg!=null) { - if (bias>0) arg = new ArgumentImpl(arg,bias); - parser.addArgument(setter,arg); + if (arg != null) { + if (bias > 0) arg = new ArgumentImpl(arg, bias); + parser.addArgument(setter, arg); } - if (p.type()==CLICommand.class) + if (p.type() == CLICommand.class) arguments[index] = command; if (p.type().isPrimitive()) @@ -111,7 +112,7 @@ public AnnotatedElement asAnnotatedElement() { public Object call(Object instance) throws Exception { try { - return method.invoke(instance,arguments); + return method.invoke(instance, arguments); } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); if (t instanceof Exception) @@ -155,7 +156,7 @@ public Class handler() { @Override public int index() { - return base.index()+bias; + return base.index() + bias; } @Override diff --git a/core/src/main/java/hudson/cli/handlers/AbstractProjectOptionHandler.java b/core/src/main/java/hudson/cli/handlers/AbstractProjectOptionHandler.java index 405ce2fcc32d9..ab7402de65aec 100644 --- a/core/src/main/java/hudson/cli/handlers/AbstractProjectOptionHandler.java +++ b/core/src/main/java/hudson/cli/handlers/AbstractProjectOptionHandler.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli.handlers; import hudson.model.AbstractProject; diff --git a/core/src/main/java/hudson/cli/handlers/JobOptionHandler.java b/core/src/main/java/hudson/cli/handlers/JobOptionHandler.java index bcbbb404a891e..5192931503413 100644 --- a/core/src/main/java/hudson/cli/handlers/JobOptionHandler.java +++ b/core/src/main/java/hudson/cli/handlers/JobOptionHandler.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli.handlers; import hudson.model.Job; diff --git a/core/src/main/java/hudson/cli/handlers/NodeOptionHandler.java b/core/src/main/java/hudson/cli/handlers/NodeOptionHandler.java index 3b2a985f4d3e5..45bd0f4e679b1 100644 --- a/core/src/main/java/hudson/cli/handlers/NodeOptionHandler.java +++ b/core/src/main/java/hudson/cli/handlers/NodeOptionHandler.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli.handlers; import hudson.model.Node; diff --git a/core/src/main/java/hudson/cli/handlers/ParameterizedJobOptionHandler.java b/core/src/main/java/hudson/cli/handlers/ParameterizedJobOptionHandler.java index 5776c221433e4..a37dbf1790f11 100644 --- a/core/src/main/java/hudson/cli/handlers/ParameterizedJobOptionHandler.java +++ b/core/src/main/java/hudson/cli/handlers/ParameterizedJobOptionHandler.java @@ -40,7 +40,7 @@ @MetaInfServices(OptionHandler.class) @SuppressWarnings("rawtypes") public class ParameterizedJobOptionHandler extends GenericItemOptionHandler { - + public ParameterizedJobOptionHandler(CmdLineParser parser, OptionDef option, Setter setter) { super(parser, option, setter); } diff --git a/core/src/main/java/hudson/cli/handlers/ViewOptionHandler.java b/core/src/main/java/hudson/cli/handlers/ViewOptionHandler.java index 7a68946c16515..65656c15e33c8 100644 --- a/core/src/main/java/hudson/cli/handlers/ViewOptionHandler.java +++ b/core/src/main/java/hudson/cli/handlers/ViewOptionHandler.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.cli.handlers; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -94,7 +95,7 @@ public View getView(final String name) { View view = null; final StringTokenizer tok = new StringTokenizer(name, "/"); - while(tok.hasMoreTokens()) { + while (tok.hasMoreTokens()) { String viewName = tok.nextToken(); diff --git a/core/src/main/java/hudson/console/AnnotatedLargeText.java b/core/src/main/java/hudson/console/AnnotatedLargeText.java index af70227ad1a5e..e074044e806da 100644 --- a/core/src/main/java/hudson/console/AnnotatedLargeText.java +++ b/core/src/main/java/hudson/console/AnnotatedLargeText.java @@ -23,6 +23,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.console; import static java.lang.Math.abs; @@ -90,24 +91,24 @@ public AnnotatedLargeText(ByteBuffer memory, Charset charset, boolean completed, } public void doProgressiveHtml(StaplerRequest req, StaplerResponse rsp) throws IOException { - req.setAttribute("html",true); - doProgressText(req,rsp); + req.setAttribute("html", true); + doProgressText(req, rsp); } /** * Aliasing what I think was a wrong name in {@link LargeText} */ public void doProgressiveText(StaplerRequest req, StaplerResponse rsp) throws IOException { - doProgressText(req,rsp); + doProgressText(req, rsp); } /** * For reusing code between text/html and text/plain, we run them both through the same code path - * and use this request attribute to differentiate. + * and use this request attribute to differentiate. */ private boolean isHtml() { StaplerRequest req = Stapler.getCurrentRequest(); - return req!=null && req.getAttribute("html")!=null; + return req != null && req.getAttribute("html") != null; } @Override @@ -117,15 +118,15 @@ protected void setContentType(StaplerResponse rsp) { private ConsoleAnnotator createAnnotator(StaplerRequest req) throws IOException { try { - String base64 = req!=null ? req.getHeader("X-ConsoleAnnotator") : null; - if (base64!=null) { + String base64 = req != null ? req.getHeader("X-ConsoleAnnotator") : null; + if (base64 != null) { Cipher sym = PASSING_ANNOTATOR.decrypt(); try (ObjectInputStream ois = new ObjectInputStreamEx(new GZIPInputStream( new CipherInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(base64.getBytes(StandardCharsets.UTF_8))), sym)), Jenkins.get().pluginManager.uberClassLoader)) { long timestamp = ois.readLong(); - if (TimeUnit.HOURS.toMillis(1) > abs(System.currentTimeMillis()-timestamp)) + if (TimeUnit.HOURS.toMillis(1) > abs(System.currentTimeMillis() - timestamp)) // don't deserialize something too old to prevent a replay attack return getConsoleAnnotator(ois); } catch (RuntimeException ex) { @@ -150,7 +151,7 @@ public long writeLogTo(long start, Writer w) throws IOException { if (isHtml()) return writeHtmlTo(start, w); else - return super.writeLogTo(start,w); + return super.writeLogTo(start, w); } /** @@ -176,22 +177,22 @@ public long writeRawLogTo(long start, OutputStream out) throws IOException { public long writeHtmlTo(long start, Writer w) throws IOException { ConsoleAnnotationOutputStream caw = new ConsoleAnnotationOutputStream<>( w, createAnnotator(Stapler.getCurrentRequest()), context, charset); - long r = super.writeLogTo(start,caw); + long r = super.writeLogTo(start, caw); ByteArrayOutputStream baos = new ByteArrayOutputStream(); Cipher sym = PASSING_ANNOTATOR.encrypt(); - ObjectOutputStream oos = AnonymousClassWarnings.checkingObjectOutputStream(new GZIPOutputStream(new CipherOutputStream(baos,sym))); + ObjectOutputStream oos = AnonymousClassWarnings.checkingObjectOutputStream(new GZIPOutputStream(new CipherOutputStream(baos, sym))); oos.writeLong(System.currentTimeMillis()); // send timestamp to prevent a replay attack oos.writeObject(caw.getConsoleAnnotator()); oos.close(); StaplerResponse rsp = Stapler.getCurrentResponse(); - if (rsp!=null) - rsp.setHeader("X-ConsoleAnnotator", new String(Base64.getEncoder().encode(baos.toByteArray()))); + if (rsp != null) + rsp.setHeader("X-ConsoleAnnotator", Base64.getEncoder().encodeToString(baos.toByteArray())); return r; } /** * Used for sending the state of ConsoleAnnotator to the client, because we are deserializing this object later. */ - private static final CryptoConfidentialKey PASSING_ANNOTATOR = new CryptoConfidentialKey(AnnotatedLargeText.class,"consoleAnnotator"); + private static final CryptoConfidentialKey PASSING_ANNOTATOR = new CryptoConfidentialKey(AnnotatedLargeText.class, "consoleAnnotator"); } diff --git a/core/src/main/java/hudson/console/ConsoleAnnotationDescriptor.java b/core/src/main/java/hudson/console/ConsoleAnnotationDescriptor.java index 3f9a17d143178..e13d65ea46273 100644 --- a/core/src/main/java/hudson/console/ConsoleAnnotationDescriptor.java +++ b/core/src/main/java/hudson/console/ConsoleAnnotationDescriptor.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.console; import hudson.DescriptorExtensionList; @@ -63,26 +64,26 @@ public String getDisplayName() { * Returns true if this descriptor has a JavaScript to be inserted on applicable console page. */ public boolean hasScript() { - return hasResource("/script.js") !=null; + return hasResource("/script.js") != null; } /** * Returns true if this descriptor has a stylesheet to be inserted on applicable console page. */ public boolean hasStylesheet() { - return hasResource("/style.css") !=null; + return hasResource("/style.css") != null; } private URL hasResource(String name) { - return clazz.getClassLoader().getResource(clazz.getName().replace('.','/').replace('$','/')+ name); + return clazz.getClassLoader().getResource(clazz.getName().replace('.', '/').replace('$', '/') + name); } - @WebMethod(name="script.js") + @WebMethod(name = "script.js") public void doScriptJs(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { rsp.serveFile(req, hasResource("/script.js"), TimeUnit.DAYS.toMillis(1)); } - @WebMethod(name="style.css") + @WebMethod(name = "style.css") public void doStyleCss(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { rsp.serveFile(req, hasResource("/style.css"), TimeUnit.DAYS.toMillis(1)); } @@ -90,7 +91,7 @@ public void doStyleCss(StaplerRequest req, StaplerResponse rsp) throws IOExcepti /** * Returns all the registered {@link ConsoleAnnotationDescriptor} descriptors. */ - public static DescriptorExtensionList,ConsoleAnnotationDescriptor> all() { + public static DescriptorExtensionList, ConsoleAnnotationDescriptor> all() { return (DescriptorExtensionList) Jenkins.get().getDescriptorList(ConsoleNote.class); } } diff --git a/core/src/main/java/hudson/console/ConsoleAnnotationOutputStream.java b/core/src/main/java/hudson/console/ConsoleAnnotationOutputStream.java index 00a84b6f46127..d2ac95da65bd7 100644 --- a/core/src/main/java/hudson/console/ConsoleAnnotationOutputStream.java +++ b/core/src/main/java/hudson/console/ConsoleAnnotationOutputStream.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.console; import hudson.MarkupText; @@ -69,7 +70,7 @@ public ConsoleAnnotationOutputStream(Writer out, ConsoleAnnotator ann this.out = out; this.ann = ConsoleAnnotator.cast(ann); this.context = context; - this.lineOut = new WriterOutputStream(line,charset); + this.lineOut = new WriterOutputStream(line, charset); } public ConsoleAnnotator getConsoleAnnotator() { @@ -86,19 +87,19 @@ protected void eol(byte[] in, int sz) throws IOException { line.reset(); final StringBuffer strBuf = line.getStringBuffer(); - int next = ConsoleNote.findPreamble(in,0,sz); + int next = ConsoleNote.findPreamble(in, 0, sz); - List> annotators=null; + List> annotators = null; - {// perform byte[]->char[] while figuring out the char positions of the BLOBs + { // perform byte[]->char[] while figuring out the char positions of the BLOBs int written = 0; - while (next>=0) { - if (next>written) { - lineOut.write(in,written,next-written); + while (next >= 0) { + if (next > written) { + lineOut.write(in, written, next - written); lineOut.flush(); written = next; } else { - assert next==written; + assert next == written; } // character position of this annotation in this line @@ -109,41 +110,41 @@ protected void eol(byte[] in, int sz) throws IOException { try { final ConsoleNote a = ConsoleNote.readFrom(new DataInputStream(b)); - if (a!=null) { - if (annotators==null) + if (a != null) { + if (annotators == null) annotators = new ArrayList<>(); annotators.add(new ConsoleAnnotator() { @Override public ConsoleAnnotator annotate(T context, MarkupText text) { - return a.annotate(context,text,charPos); + return a.annotate(context, text, charPos); } }); } } catch (IOException | ClassNotFoundException e) { // if we failed to resurrect an annotation, ignore it. - LOGGER.log(Level.FINE, "Failed to resurrect annotation from \"" + StringEscapeUtils.escapeJava(new String(in, next, rest)) + "\"", e); + LOGGER.log(Level.FINE, "Failed to resurrect annotation from \"" + StringEscapeUtils.escapeJava(new String(in, next, rest, Charset.defaultCharset())) + "\"", e); } int bytesUsed = rest - b.available(); // bytes consumed by annotations written += bytesUsed; - next = ConsoleNote.findPreamble(in,written,sz-written); + next = ConsoleNote.findPreamble(in, written, sz - written); } // finish the remaining bytes->chars conversion - lineOut.write(in,written,sz-written); + lineOut.write(in, written, sz - written); - if (annotators!=null) { + if (annotators != null) { // aggregate newly retrieved ConsoleAnnotators into the current one. - if (ann!=null) annotators.add(ann); + if (ann != null) annotators.add(ann); ann = ConsoleAnnotator.combine(annotators); } } lineOut.flush(); MarkupText mt = new MarkupText(strBuf.toString()); - if (ann!=null) - ann = ann.annotate(context,mt); + if (ann != null) + ann = ann.annotate(context, mt); out.write(mt.toString(true)); // this perform escapes } @@ -172,14 +173,14 @@ private LineBuffer(int initialSize) { private void reset() { StringBuffer buf = getStringBuffer(); - if (buf.length()>4096) + if (buf.length() > 4096) out = new StringWriter(256); else buf.setLength(0); } private StringBuffer getStringBuffer() { - StringWriter w = (StringWriter)out; + StringWriter w = (StringWriter) out; return w.getBuffer(); } } diff --git a/core/src/main/java/hudson/console/ConsoleAnnotator.java b/core/src/main/java/hudson/console/ConsoleAnnotator.java index 9761439320fee..8f289fd70cb91 100644 --- a/core/src/main/java/hudson/console/ConsoleAnnotator.java +++ b/core/src/main/java/hudson/console/ConsoleAnnotator.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.console; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -81,14 +82,14 @@ public abstract class ConsoleAnnotator implements Serializable { * To indicate that you are not interested in the following lines, return {@code null}. */ @CheckForNull - public abstract ConsoleAnnotator annotate(@NonNull T context, @NonNull MarkupText text ); + public abstract ConsoleAnnotator annotate(@NonNull T context, @NonNull MarkupText text); /** * Cast operation that restricts T. */ @SuppressWarnings("unchecked") public static ConsoleAnnotator cast(ConsoleAnnotator a) { - return (ConsoleAnnotator)a; + return (ConsoleAnnotator) a; } @SuppressWarnings({"unchecked", "rawtypes"}) // unclear to jglick what is going on here @@ -104,9 +105,9 @@ public ConsoleAnnotator annotate(T context, MarkupText text) { ListIterator> itr = list.listIterator(); while (itr.hasNext()) { ConsoleAnnotator a = itr.next(); - ConsoleAnnotator b = a.annotate(context,text); - if (a!=b) { - if (b==null) itr.remove(); + ConsoleAnnotator b = a.annotate(context, text); + if (a != b) { + if (b == null) itr.remove(); else itr.set(b); } } @@ -147,7 +148,7 @@ public static List> _for(T context) { for (ConsoleAnnotatorFactory f : ConsoleAnnotatorFactory.all()) { if (f.type().isInstance(context)) { ConsoleAnnotator ca = f.newInstance(context); - if (ca!=null) + if (ca != null) r.add(ca); } } diff --git a/core/src/main/java/hudson/console/ConsoleAnnotatorFactory.java b/core/src/main/java/hudson/console/ConsoleAnnotatorFactory.java index 538b97359105f..b2f6948fd155f 100644 --- a/core/src/main/java/hudson/console/ConsoleAnnotatorFactory.java +++ b/core/src/main/java/hudson/console/ConsoleAnnotatorFactory.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.console; import hudson.Extension; @@ -61,7 +62,7 @@ * in the same resource directory that you normally put Jelly scripts), which will be loaded into * the HTML page whenever the console notes are used. This allows you to use minimal markup in * code generation, and do the styling in CSS and perform the rest of the interesting work as a CSS behaviour/JavaScript. - * + * * @author Kohsuke Kawaguchi * @since 1.349 */ @@ -87,7 +88,7 @@ public abstract class ConsoleAnnotatorFactory implements ExtensionPoint { public Class type() { Type type = Types.getBaseClass(getClass(), ConsoleAnnotatorFactory.class); if (type instanceof ParameterizedType) - return Types.erasure(Types.getTypeArgument(type,0)); + return Types.erasure(Types.getTypeArgument(type, 0)); else return Object.class; } @@ -96,27 +97,27 @@ public Class type() { * Returns true if this descriptor has a JavaScript to be inserted on applicable console page. */ public boolean hasScript() { - return getResource("/script.js") !=null; + return getResource("/script.js") != null; } public boolean hasStylesheet() { - return getResource("/style.css") !=null; + return getResource("/style.css") != null; } private URL getResource(String fileName) { Class c = getClass(); - return c.getClassLoader().getResource(c.getName().replace('.','/').replace('$','/')+ fileName); + return c.getClassLoader().getResource(c.getName().replace('.', '/').replace('$', '/') + fileName); } /** * Serves the JavaScript file associated with this console annotator factory. */ - @WebMethod(name="script.js") + @WebMethod(name = "script.js") public void doScriptJs(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { rsp.serveFile(req, getResource("/script.js"), TimeUnit.DAYS.toMillis(1)); } - @WebMethod(name="style.css") + @WebMethod(name = "style.css") public void doStyleCss(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { rsp.serveFile(req, getResource("/style.css"), TimeUnit.DAYS.toMillis(1)); } diff --git a/core/src/main/java/hudson/console/ConsoleLogFilter.java b/core/src/main/java/hudson/console/ConsoleLogFilter.java index 3f54674477db4..3523fce8e9d25 100644 --- a/core/src/main/java/hudson/console/ConsoleLogFilter.java +++ b/core/src/main/java/hudson/console/ConsoleLogFilter.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright 2010 Yahoo! Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE diff --git a/core/src/main/java/hudson/console/ConsoleNote.java b/core/src/main/java/hudson/console/ConsoleNote.java index 443625350cb28..8183934aedcec 100644 --- a/core/src/main/java/hudson/console/ConsoleNote.java +++ b/core/src/main/java/hudson/console/ConsoleNote.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.console; import com.jcraft.jzlib.GZIPInputStream; @@ -43,6 +44,7 @@ import java.io.OutputStream; import java.io.Serializable; import java.io.Writer; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; @@ -160,7 +162,7 @@ public abstract class ConsoleNote implements Serializable, Describable removeNotes(Collection logLines) { public static String removeNotes(String line) { while (true) { int idx = line.indexOf(PREAMBLE_STR); - if (idx<0) return line; - int e = line.indexOf(POSTAMBLE_STR,idx); - if (e<0) return line; - line = line.substring(0,idx)+line.substring(e+POSTAMBLE_STR.length()); + if (idx < 0) return line; + int e = line.indexOf(POSTAMBLE_STR, idx); + if (e < 0) return line; + line = line.substring(0, idx) + line.substring(e + POSTAMBLE_STR.length()); } } } diff --git a/core/src/main/java/hudson/console/ExpandableDetailsNote.java b/core/src/main/java/hudson/console/ExpandableDetailsNote.java index f9a86a8d53de1..57ed88e06e22d 100644 --- a/core/src/main/java/hudson/console/ExpandableDetailsNote.java +++ b/core/src/main/java/hudson/console/ExpandableDetailsNote.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.console; import hudson.Extension; @@ -50,7 +51,7 @@ public ExpandableDetailsNote(String caption, String html) { @Override public ConsoleAnnotator annotate(Object context, MarkupText text, int charPos) { text.addMarkup(charPos, - "

      "+html+"
      "); + "
      " + html + "
      "); return null; } @@ -59,7 +60,7 @@ public static String encodeTo(String buttonCaption, String html) { return new ExpandableDetailsNote(buttonCaption, html).encode(); } catch (IOException e) { // impossible, but don't make this a fatal problem - LOGGER.log(Level.WARNING, "Failed to serialize "+HyperlinkNote.class,e); + LOGGER.log(Level.WARNING, "Failed to serialize " + HyperlinkNote.class, e); return ""; } } diff --git a/core/src/main/java/hudson/console/HyperlinkNote.java b/core/src/main/java/hudson/console/HyperlinkNote.java index 38464ceecc9d1..f8e7e65208383 100644 --- a/core/src/main/java/hudson/console/HyperlinkNote.java +++ b/core/src/main/java/hudson/console/HyperlinkNote.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.console; import hudson.Extension; @@ -61,15 +62,15 @@ public ConsoleAnnotator annotate(Object context, MarkupText text, int charPos) { String url = this.url; if (url.startsWith("/")) { StaplerRequest req = Stapler.getCurrentRequest(); - if (req!=null) { + if (req != null) { // if we are serving HTTP request, we want to use app relative URL - url = req.getContextPath()+url; + url = req.getContextPath() + url; } else { // otherwise presumably this is rendered for e-mails and other non-HTTP stuff - url = Jenkins.get().getRootUrl()+url.substring(1); + url = Jenkins.get().getRootUrl() + url.substring(1); } } - text.addMarkup(charPos, charPos + length, "", ""); + text.addMarkup(charPos, charPos + length, "", ""); return null; } @@ -91,10 +92,10 @@ static String encodeTo(String url, String text, BiFunction4096) + if (buf.size() > 4096) buf = new ByteArrayOutputStream2(); else buf.reset(); @@ -68,9 +69,9 @@ private void eol() throws IOException { @Override public void write(byte[] b, int off, int len) throws IOException { - int end = off+len; + int end = off + len; - for( int i=off; i0) { + if (buf.size() > 0) { /* because LargeText cuts output at the line end boundary, this is possible only for the very end of the console output, if the output ends without NL. @@ -97,15 +98,15 @@ public void forceEol() throws IOException { protected String trimEOL(String line) { int slen = line.length(); - while (slen>0) { - char ch = line.charAt(slen-1); - if (ch=='\r' || ch=='\n') { + while (slen > 0) { + char ch = line.charAt(slen - 1); + if (ch == '\r' || ch == '\n') { slen--; continue; } break; } - line = line.substring(0,slen); + line = line.substring(0, slen); return line; } diff --git a/core/src/main/java/hudson/console/ModelHyperlinkNote.java b/core/src/main/java/hudson/console/ModelHyperlinkNote.java index 86d8b044833f4..fa5d57eedd4eb 100644 --- a/core/src/main/java/hudson/console/ModelHyperlinkNote.java +++ b/core/src/main/java/hudson/console/ModelHyperlinkNote.java @@ -27,27 +27,27 @@ public ModelHyperlinkNote(String url, int length) { @Override protected String extraAttributes() { - return " class='model-link'"; + return " class='model-link model-link--float'"; } public static String encodeTo(@NonNull User u) { - return encodeTo(u,u.getDisplayName()); + return encodeTo(u, u.getDisplayName()); } public static String encodeTo(User u, String text) { - return encodeTo('/'+u.getUrl(),text); + return encodeTo('/' + u.getUrl(), text); } public static String encodeTo(Item item) { - return encodeTo(item,item.getFullDisplayName()); + return encodeTo(item, item.getFullDisplayName()); } public static String encodeTo(Item item, String text) { - return encodeTo('/'+item.getUrl(),text); + return encodeTo('/' + item.getUrl(), text); } public static String encodeTo(Run r) { - return encodeTo('/'+r.getUrl(),r.getDisplayName()); + return encodeTo('/' + r.getUrl(), r.getDisplayName()); } public static String encodeTo(Node node) { @@ -77,7 +77,7 @@ public String getDisplayName() { return "Hyperlinks to models"; } } - + private static final long serialVersionUID = 1L; private static final Logger LOGGER = Logger.getLogger(ModelHyperlinkNote.class.getName()); diff --git a/core/src/main/java/hudson/console/PlainTextConsoleOutputStream.java b/core/src/main/java/hudson/console/PlainTextConsoleOutputStream.java index 9b94490f3a312..f3b5bd8adf7e6 100644 --- a/core/src/main/java/hudson/console/PlainTextConsoleOutputStream.java +++ b/core/src/main/java/hudson/console/PlainTextConsoleOutputStream.java @@ -49,16 +49,16 @@ public PlainTextConsoleOutputStream(OutputStream out) { @Override protected void eol(byte[] in, int sz) throws IOException { - int next = ConsoleNote.findPreamble(in,0,sz); + int next = ConsoleNote.findPreamble(in, 0, sz); // perform byte[]->char[] while figuring out the char positions of the BLOBs int written = 0; - while (next>=0) { - if (next>written) { - out.write(in,written,next-written); + while (next >= 0) { + if (next > written) { + out.write(in, written, next - written); written = next; } else { - assert next==written; + assert next == written; } int rest = sz - next; @@ -70,10 +70,10 @@ protected void eol(byte[] in, int sz) throws IOException { written += bytesUsed; - next = ConsoleNote.findPreamble(in,written,sz-written); + next = ConsoleNote.findPreamble(in, written, sz - written); } // finish the remaining bytes->chars conversion - out.write(in,written,sz-written); + out.write(in, written, sz - written); } } diff --git a/core/src/main/java/hudson/console/UrlAnnotator.java b/core/src/main/java/hudson/console/UrlAnnotator.java index f9cc1fc550505..7422faee4b2c1 100644 --- a/core/src/main/java/hudson/console/UrlAnnotator.java +++ b/core/src/main/java/hudson/console/UrlAnnotator.java @@ -23,10 +23,10 @@ private static class UrlConsoleAnnotator extends ConsoleAnnotator { public ConsoleAnnotator annotate(Object context, MarkupText text) { for (SubText t : text.findTokens(URL)) { int prev = t.start() - 1; - char ch = prev>=0 ? text.charAt(prev) : ' '; + char ch = prev >= 0 ? text.charAt(prev) : ' '; int idx = OPEN.indexOf(ch); - if (idx>=0) {// if inside a bracket, exclude the end bracket. - t=t.subText(0,t.getText().indexOf(CLOSE.charAt(idx))); + if (idx >= 0) { // if inside a bracket, exclude the end bracket. + t = t.subText(0, t.getText().indexOf(CLOSE.charAt(idx))); } t.href(t.getText()); } @@ -44,6 +44,6 @@ public ConsoleAnnotator annotate(Object context, MarkupText text) { private static final Pattern URL = Pattern.compile("\\b(http|https|file|ftp)://[^\\s<>]+[^\\s<>,\\.:\"'()\\[\\]=]"); private static final String OPEN = "'\"()[]<>"; - private static final String CLOSE= "'\")(][><"; + private static final String CLOSE = "'\")(][><"; } } diff --git a/core/src/main/java/hudson/diagnosis/HudsonHomeDiskUsageChecker.java b/core/src/main/java/hudson/diagnosis/HudsonHomeDiskUsageChecker.java index 4e3cf6b95febf..8b38c3e5a7766 100644 --- a/core/src/main/java/hudson/diagnosis/HudsonHomeDiskUsageChecker.java +++ b/core/src/main/java/hudson/diagnosis/HudsonHomeDiskUsageChecker.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.diagnosis; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -48,14 +49,14 @@ public long getRecurrencePeriod() { protected void doRun() { long free = Jenkins.get().getRootDir().getUsableSpace(); long total = Jenkins.get().getRootDir().getTotalSpace(); - if(free<=0 || total<=0) { + if (free <= 0 || total <= 0) { // information unavailable. pointless to try. LOGGER.info("JENKINS_HOME disk usage information isn't available. aborting to monitor"); cancel(); return; } - LOGGER.fine("Monitoring disk usage of JENKINS_HOME. total="+total+" free="+free); + LOGGER.fine("Monitoring disk usage of JENKINS_HOME. total=" + total + " free=" + free); // if it's more than 90% full and less than the minimum, activate @@ -71,5 +72,5 @@ protected void doRun() { */ @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "for script console") public static long FREE_SPACE_THRESHOLD = SystemProperties.getLong(HudsonHomeDiskUsageChecker.class.getName() - + ".freeSpaceThreshold", 1024L*1024*1024*10); + + ".freeSpaceThreshold", 1024L * 1024 * 1024 * 10); } diff --git a/core/src/main/java/hudson/diagnosis/HudsonHomeDiskUsageMonitor.java b/core/src/main/java/hudson/diagnosis/HudsonHomeDiskUsageMonitor.java index 9562952408d80..20e112f5ba843 100644 --- a/core/src/main/java/hudson/diagnosis/HudsonHomeDiskUsageMonitor.java +++ b/core/src/main/java/hudson/diagnosis/HudsonHomeDiskUsageMonitor.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.diagnosis; import hudson.Extension; @@ -56,10 +57,10 @@ public HudsonHomeDiskUsageMonitor() { public boolean isActivated() { return activated; } - + @Override public String getDisplayName() { - return Messages.HudsonHomeDiskUsageMonitor_DisplayName(); + return Messages.HudsonHomeDiskUsageMonitor_DisplayName(); } /** @@ -67,7 +68,7 @@ public String getDisplayName() { */ @RequirePOST public HttpResponse doAct(@QueryParameter String no) throws IOException { - if(no!=null) { + if (no != null) { disable(true); return HttpResponses.redirectViaContextPath("/manage"); } else { @@ -83,8 +84,8 @@ public List getSolutions() { * Binds a solution to the URL. */ public Solution getSolution(String id) { - for( Solution s : Solution.all() ) - if(s.id.equals(id)) + for (Solution s : Solution.all()) + if (s.id.equals(id)) return s; return null; } @@ -98,8 +99,8 @@ public static HudsonHomeDiskUsageMonitor get() { /** * Extension point for suggesting solutions for full JENKINS_HOME. + * Views are as follows: * - *

      Views

      *
      *
      message.jelly
      *
      @@ -129,7 +130,7 @@ protected Solution() { * Returns the URL of this monitor, relative to the context path. */ public String getUrl() { - return HudsonHomeDiskUsageMonitor.get().getUrl()+"/solution/"+id; + return HudsonHomeDiskUsageMonitor.get().getUrl() + "/solution/" + id; } /** diff --git a/core/src/main/java/hudson/diagnosis/MemoryUsageMonitor.java b/core/src/main/java/hudson/diagnosis/MemoryUsageMonitor.java index 06ed43cb1a78e..797ee03d6b21e 100644 --- a/core/src/main/java/hudson/diagnosis/MemoryUsageMonitor.java +++ b/core/src/main/java/hudson/diagnosis/MemoryUsageMonitor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.diagnosis; import hudson.Extension; @@ -49,7 +50,7 @@ @Extension @Symbol("memoryUsage") public final class MemoryUsageMonitor extends PeriodicWork { /** - * A memory group is conceptually a set of memory pools. + * A memory group is conceptually a set of memory pools. */ public static final class MemoryGroup { private final List pools = new ArrayList<>(); @@ -58,11 +59,11 @@ public static final class MemoryGroup { * Trend of the memory usage, after GCs. * So this shows the accurate snapshot of the footprint of live objects. */ - public final MultiStageTimeSeries used = new MultiStageTimeSeries(Messages._MemoryUsageMonitor_USED(), ColorPalette.RED, 0,0); + public final MultiStageTimeSeries used = new MultiStageTimeSeries(Messages._MemoryUsageMonitor_USED(), ColorPalette.RED, 0, 0); /** * Trend of the maximum memory size, after GCs. */ - public final MultiStageTimeSeries max = new MultiStageTimeSeries(Messages._MemoryUsageMonitor_TOTAL(), ColorPalette.BLUE, 0,0); + public final MultiStageTimeSeries max = new MultiStageTimeSeries(Messages._MemoryUsageMonitor_TOTAL(), ColorPalette.BLUE, 0, 0); private MemoryGroup(List pools, MemoryType type) { for (MemoryPoolMXBean pool : pools) { @@ -76,7 +77,7 @@ private void update() { long max = 0; for (MemoryPoolMXBean pool : pools) { MemoryUsage usage = pool.getCollectionUsage(); - if(usage==null) continue; // not available + if (usage == null) continue; // not available used += usage.getUsed(); max += usage.getMax(); } @@ -94,7 +95,7 @@ private void update() { */ public TrendChart doGraph(@QueryParameter String type) throws IOException { Jenkins.get().checkAnyPermission(Jenkins.SYSTEM_READ, Jenkins.MANAGE); - return MultiStageTimeSeries.createTrendChart(TimeScale.parse(type),used,max); + return MultiStageTimeSeries.createTrendChart(TimeScale.parse(type), used, max); } } diff --git a/core/src/main/java/hudson/diagnosis/NullIdDescriptorMonitor.java b/core/src/main/java/hudson/diagnosis/NullIdDescriptorMonitor.java index ac9ead6692926..43a1505aa606a 100644 --- a/core/src/main/java/hudson/diagnosis/NullIdDescriptorMonitor.java +++ b/core/src/main/java/hudson/diagnosis/NullIdDescriptorMonitor.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.diagnosis; import static hudson.init.InitMilestone.EXTENSIONS_AUGMENTED; @@ -65,7 +66,7 @@ public List getProblems() { return Collections.unmodifiableList(problems); } - @Initializer(after=EXTENSIONS_AUGMENTED) + @Initializer(after = EXTENSIONS_AUGMENTED) public void verify() { Jenkins h = Jenkins.get(); for (Descriptor d : h.getExtensionList(Descriptor.class)) { @@ -74,14 +75,14 @@ public void verify() { try { id = d.getId(); } catch (Throwable t) { - LOGGER.log(Level.SEVERE,MessageFormat.format("Descriptor {0} from plugin {1} with display name {2} reported an exception for ID", - d, p == null ? "???" : p.getLongName(), d.getDisplayName()),t); + LOGGER.log(Level.SEVERE, MessageFormat.format("Descriptor {0} from plugin {1} with display name {2} reported an exception for ID", + d, p == null ? "???" : p.getLongName(), d.getDisplayName()), t); problems.add(d); continue; } - if (id==null) { + if (id == null) { LOGGER.severe(MessageFormat.format("Descriptor {0} from plugin {1} with display name {2} has null ID", - d, p==null?"???":p.getLongName(), d.getDisplayName())); + d, p == null ? "???" : p.getLongName(), d.getDisplayName())); problems.add(d); } } diff --git a/core/src/main/java/hudson/diagnosis/OldDataMonitor.java b/core/src/main/java/hudson/diagnosis/OldDataMonitor.java index 283fe73e48a6d..b29ec1a80fb23 100644 --- a/core/src/main/java/hudson/diagnosis/OldDataMonitor.java +++ b/core/src/main/java/hudson/diagnosis/OldDataMonitor.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.diagnosis; import com.thoughtworks.xstream.converters.UnmarshallingContext; @@ -77,7 +78,7 @@ public class OldDataMonitor extends AdministrativeMonitor { private static final Logger LOGGER = Logger.getLogger(OldDataMonitor.class.getName()); - private ConcurrentMap data = new ConcurrentHashMap<>(); + private ConcurrentMap data = new ConcurrentHashMap<>(); /** * Gets instance of the monitor. @@ -105,9 +106,9 @@ public boolean isActivated() { return !data.isEmpty(); } - public Map getData() { - Map r = new HashMap<>(); - for (Map.Entry entry : this.data.entrySet()) { + public Map getData() { + Map r = new HashMap<>(); + for (Map.Entry entry : this.data.entrySet()) { Saveable s = entry.getKey().get(); if (s != null) { r.put(s, entry.getValue()); @@ -191,6 +192,7 @@ public static void report(UnmarshallingContext context, String version) { private static class ReportException extends Exception { private String version; + private ReportException(String version) { this.version = version; } @@ -206,7 +208,7 @@ public static void report(Saveable obj, Collection errors) { int i = 0; for (Throwable e : errors) { if (e instanceof ReportException) { - report(obj, ((ReportException)e).version); + report(obj, ((ReportException) e).version); } else { if (Main.isUnitTest) { LOGGER.log(Level.INFO, "Trouble loading " + obj, e); @@ -273,7 +275,7 @@ public VersionRange(VersionRange previous, String version, String extra) { @Override public String toString() { - return min==null ? "" : min + (single ? "" : " - " + max.toString()); + return min == null ? "" : min + (single ? "" : " - " + max.toString()); } /** @@ -357,7 +359,7 @@ private void saveAndRemoveEntries(Predicate removed = new ArrayList<>(); - for (Map.Entry entry : data.entrySet()) { + for (Map.Entry entry : data.entrySet()) { if (matchingPredicate.test(entry)) { Saveable s = entry.getKey().get(); if (s != null) { @@ -396,15 +398,19 @@ private static SaveableReference referTo(Saveable s) { private static final class SimpleSaveableReference implements SaveableReference { private final Saveable instance; + SimpleSaveableReference(Saveable instance) { this.instance = instance; } + @Override public Saveable get() { return instance; } + @Override public int hashCode() { return instance.hashCode(); } + @Override public boolean equals(Object obj) { return obj instanceof SimpleSaveableReference && instance.equals(((SimpleSaveableReference) obj).instance); } @@ -414,9 +420,11 @@ private static final class SimpleSaveableReference implements SaveableReference private static final class RunSaveableReference implements SaveableReference { private final String id; - RunSaveableReference(Run r) { + + RunSaveableReference(Run r) { id = r.getExternalizableId(); } + @Override public Saveable get() { try { return Run.fromExternalizableId(id); @@ -426,9 +434,11 @@ private static final class RunSaveableReference implements SaveableReference { return null; } } + @Override public int hashCode() { return id.hashCode(); } + @Override public boolean equals(Object obj) { return obj instanceof RunSaveableReference && id.equals(((RunSaveableReference) obj).id); } @@ -444,7 +454,7 @@ public Category getCategory() { @Override public String getIconFileName() { - return "document.png"; + return "symbol-cube"; } @Override diff --git a/core/src/main/java/hudson/diagnosis/ReverseProxySetupMonitor.java b/core/src/main/java/hudson/diagnosis/ReverseProxySetupMonitor.java index 10c72113ddbea..af7b2579db745 100644 --- a/core/src/main/java/hudson/diagnosis/ReverseProxySetupMonitor.java +++ b/core/src/main/java/hudson/diagnosis/ReverseProxySetupMonitor.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.diagnosis; import hudson.Extension; @@ -115,7 +116,7 @@ public Permission getRequiredPermission() { @RestrictedSince("2.235") @RequirePOST public HttpResponse doAct(@QueryParameter String no) throws IOException { - if(no!=null) { // dismiss + if (no != null) { // dismiss Jenkins.get().checkPermission(Jenkins.ADMINISTER); disable(true); // of course the irony is that this redirect won't work diff --git a/core/src/main/java/hudson/diagnosis/TooManyJobsButNoView.java b/core/src/main/java/hudson/diagnosis/TooManyJobsButNoView.java index ee1e1566c3b70..6412ac63bcb2a 100644 --- a/core/src/main/java/hudson/diagnosis/TooManyJobsButNoView.java +++ b/core/src/main/java/hudson/diagnosis/TooManyJobsButNoView.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.diagnosis; import hudson.Extension; @@ -37,7 +38,7 @@ * If Hudson is run with a lot of jobs but no views, suggest the user that they can create views. * *

      - * I noticed at an user visit that some users didn't notice the '+' icon in the tab bar. + * I noticed at an user visit that some users didn't notice the '+' icon in the tab bar. * * @author Kohsuke Kawaguchi */ @@ -65,11 +66,11 @@ public boolean isActivated() { @RequirePOST public void doAct(StaplerRequest req, StaplerResponse rsp) throws IOException { Jenkins.get().checkPermission(Jenkins.ADMINISTER); - if(req.hasParameter("no")) { + if (req.hasParameter("no")) { disable(true); - rsp.sendRedirect(req.getContextPath()+"/manage"); + rsp.sendRedirect(req.getContextPath() + "/manage"); } else { - rsp.sendRedirect(req.getContextPath()+"/newView"); + rsp.sendRedirect(req.getContextPath() + "/newView"); } } diff --git a/core/src/main/java/hudson/init/InitMilestone.java b/core/src/main/java/hudson/init/InitMilestone.java index 4ee9fa26f418d..5e8c03c3e0554 100644 --- a/core/src/main/java/hudson/init/InitMilestone.java +++ b/core/src/main/java/hudson/init/InitMilestone.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.init; import org.jvnet.hudson.reactor.Executable; @@ -49,7 +50,7 @@ *

    • JOB_CONFIG_ADAPTED
    • *
    • COMPLETED * - * + * * @author Kohsuke Kawaguchi */ public enum InitMilestone implements Milestone { @@ -131,8 +132,8 @@ public enum InitMilestone implements Milestone { public static TaskBuilder ordering() { TaskGraphBuilder b = new TaskGraphBuilder(); InitMilestone[] v = values(); - for (int i=0; i * To register, put {@link MetaInfServices} on your implementation. - * + * * @author Kohsuke Kawaguchi */ public class InitStrategy { @@ -58,10 +58,10 @@ public List listPluginArchives(PluginManager pm) throws IOException { return r; } - + private void listPluginFiles(PluginManager pm, String extension, Collection all) throws IOException { File[] files = pm.rootDir.listFiles(new FilterByExtension(extension)); - if (files==null) + if (files == null) throw new IOException("Jenkins is unable to create " + pm.rootDir + "\nPerhaps its security privilege is insufficient"); all.addAll(Arrays.asList(files)); @@ -99,7 +99,7 @@ protected void getBundledPluginsFromProperty(final List r) { /** * Selectively skip some of the initialization tasks. - * + * * @return * true to skip the execution. */ diff --git a/core/src/main/java/hudson/init/Initializer.java b/core/src/main/java/hudson/init/Initializer.java index 07f328a20eef0..78f4b2b444fd0 100644 --- a/core/src/main/java/hudson/init/Initializer.java +++ b/core/src/main/java/hudson/init/Initializer.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.init; import static hudson.init.InitMilestone.COMPLETED; @@ -37,9 +38,8 @@ /** * Placed on methods to indicate that this method is to be run during the Jenkins start up to perform - * some sort of initialization tasks. + * some sort of initialization tasks, for example: * - *

      Example

      *
          @Initializer(after=JOB_LOADED)
          public static void init() throws IOException {
      @@ -51,7 +51,7 @@ public static void init() throws IOException {
        * The method in question can be either {@code static} or an instance method. When used with instance
        * methods, those methods have to be on a class annotated with {@link Extension} and marked as
        * {@link #after()} {@link InitMilestone#PLUGINS_PREPARED}.
      - * 
      + *
        * @author Kohsuke Kawaguchi
        */
       @Indexed
      @@ -99,7 +99,7 @@ public static void init() throws IOException {
           /**
            * Should the failure in this task prevent Hudson from starting up?
            *
      -     * @see Task#failureIsFatal() 
      +     * @see Task#failureIsFatal()
            */
           boolean fatal() default true;
       }
      diff --git a/core/src/main/java/hudson/init/InitializerFinder.java b/core/src/main/java/hudson/init/InitializerFinder.java
      index 8b11b5740c509..938cbd5d78e39 100644
      --- a/core/src/main/java/hudson/init/InitializerFinder.java
      +++ b/core/src/main/java/hudson/init/InitializerFinder.java
      @@ -21,6 +21,7 @@
        * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        * THE SOFTWARE.
        */
      +
       package hudson.init;
       
       import org.jvnet.hudson.reactor.Milestone;
      @@ -33,7 +34,7 @@
       public class InitializerFinder extends TaskMethodFinder {
       
           public InitializerFinder(ClassLoader cl) {
      -        super(Initializer.class,InitMilestone.class,cl);
      +        super(Initializer.class, InitMilestone.class, cl);
           }
       
           public InitializerFinder() {
      diff --git a/core/src/main/java/hudson/init/TaskMethodFinder.java b/core/src/main/java/hudson/init/TaskMethodFinder.java
      index 9925ca41900f1..b15869ba8831f 100644
      --- a/core/src/main/java/hudson/init/TaskMethodFinder.java
      +++ b/core/src/main/java/hudson/init/TaskMethodFinder.java
      @@ -44,10 +44,15 @@ abstract class TaskMethodFinder extends TaskBuilder {
       
           // working around the restriction that Java doesn't allow annotation types to extend interfaces
           protected abstract String displayNameOf(T i);
      +
           protected abstract String[] requiresOf(T i);
      +
           protected abstract String[] attainsOf(T i);
      +
           protected abstract Milestone afterOf(T i);
      +
           protected abstract Milestone beforeOf(T i);
      +
           protected abstract boolean fatalOf(T i);
       
           @Override
      @@ -57,7 +62,7 @@ public Collection discoverTasks(Reactor session) throws IOException {
                   if (filter(e)) continue;   // already reported once
       
                   T i = e.getAnnotation(type);
      -            if (i==null)        continue; // stale index
      +            if (i == null)        continue; // stale index
       
                   result.add(new TaskImpl(i, e));
               }
      @@ -77,13 +82,13 @@ protected boolean filter(Method e) {
           protected String getDisplayNameOf(Method e, T i) {
               Class c = e.getDeclaringClass();
               String key = displayNameOf(i);
      -        if (key.length()==0)  return c.getSimpleName()+"."+e.getName();
      +        if (key.length() == 0)  return c.getSimpleName() + "." + e.getName();
               try {
                   ResourceBundleHolder rb = ResourceBundleHolder.get(
                           c.getClassLoader().loadClass(c.getPackage().getName() + ".Messages"));
                   return rb.format(key);
               } catch (ClassNotFoundException x) {
      -            LOGGER.log(WARNING, "Failed to load "+x.getMessage()+" for "+ e,x);
      +            LOGGER.log(WARNING, "Failed to load " + x.getMessage() + " for " + e, x);
                   return key;
               } catch (MissingResourceException x) {
                   LOGGER.log(WARNING, "Could not find key '" + key + "' in " + c.getPackage().getName() + ".Messages", x);
      @@ -98,14 +103,14 @@ protected void invoke(Method e) {
               try {
                   Class[] pt = e.getParameterTypes();
                   Object[] args = new Object[pt.length];
      -            for (int i=0; i type) {
               Jenkins j = Jenkins.get();
               assert j != null : "This method is only invoked after the Jenkins singleton instance has been set";
      -        if (type==Jenkins.class || type==Hudson.class)
      +        if (type == Jenkins.class || type == Hudson.class)
                   return j;
               Injector i = j.getInjector();
      -        if (i!=null)
      +        if (i != null)
                   return i.getInstance(type);
      -        throw new IllegalArgumentException("Unable to inject "+type);
      +        throw new IllegalArgumentException("Unable to inject " + type);
           }
       
           /**
      @@ -189,7 +194,7 @@ private Collection toMilestones(String[] tokens, Milestone m) {
                   List r = new ArrayList<>();
                   for (String s : tokens) {
                       try {
      -                    r.add((Milestone)Enum.valueOf(milestoneType,s));
      +                    r.add((Milestone) Enum.valueOf(milestoneType, s));
                       } catch (IllegalArgumentException x) {
                           r.add(new MilestoneImpl(s));
                       }
      diff --git a/core/src/main/java/hudson/init/TermMilestone.java b/core/src/main/java/hudson/init/TermMilestone.java
      index 85efd8d5eab71..5146e2dbb4eb7 100644
      --- a/core/src/main/java/hudson/init/TermMilestone.java
      +++ b/core/src/main/java/hudson/init/TermMilestone.java
      @@ -44,8 +44,8 @@ public enum TermMilestone implements Milestone {
           public static TaskBuilder ordering() {
               TaskGraphBuilder b = new TaskGraphBuilder();
               TermMilestone[] v = values();
      -        for (int i=0; i {
           public TerminatorFinder(ClassLoader cl) {
               super(Terminator.class, TermMilestone.class, cl);
           }
      -    
      +
           @Override
           protected String displayNameOf(Terminator i) {
               return i.displayName();
      diff --git a/core/src/main/java/hudson/init/impl/GroovyInitScript.java b/core/src/main/java/hudson/init/impl/GroovyInitScript.java
      index fb37be78b264e..17f6a4702c940 100644
      --- a/core/src/main/java/hudson/init/impl/GroovyInitScript.java
      +++ b/core/src/main/java/hudson/init/impl/GroovyInitScript.java
      @@ -21,6 +21,7 @@
        * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        * THE SOFTWARE.
        */
      +
       package hudson.init.impl;
       
       import static hudson.init.InitMilestone.JOB_CONFIG_ADAPTED;
      @@ -32,11 +33,11 @@
       /**
        * Run the initialization script, if it exists.
        * It runs strictly after the initialization of other tasks during the last initialization milestone.
      - * 
      + *
        * @author Kohsuke Kawaguchi
        */
       public class GroovyInitScript {
      -    @Initializer(after=JOB_CONFIG_ADAPTED)
      +    @Initializer(after = JOB_CONFIG_ADAPTED)
           public static void init(Jenkins j) {
               new GroovyHookScript("init", j.servletContext, j.getRootDir(), j.getPluginManager().uberClassLoader).run();
           }
      diff --git a/core/src/main/java/hudson/init/impl/InitialUserContent.java b/core/src/main/java/hudson/init/impl/InitialUserContent.java
      index e057ba16a3f79..81cc279eb909e 100644
      --- a/core/src/main/java/hudson/init/impl/InitialUserContent.java
      +++ b/core/src/main/java/hudson/init/impl/InitialUserContent.java
      @@ -21,6 +21,7 @@
        * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        * THE SOFTWARE.
        */
      +
       package hudson.init.impl;
       
       import static hudson.init.InitMilestone.JOB_CONFIG_ADAPTED;
      @@ -39,12 +40,12 @@
        * @author Kohsuke Kawaguchi
        */
       public class InitialUserContent {
      -    @Initializer(after=JOB_CONFIG_ADAPTED)
      +    @Initializer(after = JOB_CONFIG_ADAPTED)
           public static void init(Jenkins h) throws IOException {
               File userContentDir = new File(h.getRootDir(), "userContent");
               if (!Files.isDirectory(Util.fileToPath(userContentDir))) {
      -            Files.createDirectories(Util.fileToPath(userContentDir));
      -            FileUtils.writeStringToFile(new File(userContentDir,"readme.txt"), Messages.Hudson_USER_CONTENT_README() + "\n");
      +            Util.createDirectories(Util.fileToPath(userContentDir));
      +            FileUtils.writeStringToFile(new File(userContentDir, "readme.txt"), Messages.Hudson_USER_CONTENT_README() + "\n");
               }
           }
       }
      diff --git a/core/src/main/java/hudson/init/impl/InstallUncaughtExceptionHandler.java b/core/src/main/java/hudson/init/impl/InstallUncaughtExceptionHandler.java
      index eea0f4eea857a..e09237bef9185 100644
      --- a/core/src/main/java/hudson/init/impl/InstallUncaughtExceptionHandler.java
      +++ b/core/src/main/java/hudson/init/impl/InstallUncaughtExceptionHandler.java
      @@ -53,7 +53,7 @@ private static void handleException(Jenkins j, Throwable e, HttpServletRequest r
               String id = UUID.randomUUID().toString();
               LOGGER.log(isEOFException(e) ? Level.FINE : Level.WARNING, "Caught unhandled exception with ID " + id, e);
               req.setAttribute("jenkins.exception.id", id);
      -        req.setAttribute("javax.servlet.error.exception",e);
      +        req.setAttribute("javax.servlet.error.exception", e);
               rsp.setStatus(code);
               try {
                   WebApp.get(j.servletContext).getSomeStapler().invoke(req, rsp, j, "/oops");
      diff --git a/core/src/main/java/hudson/lifecycle/ExitLifecycle.java b/core/src/main/java/hudson/lifecycle/ExitLifecycle.java
      index 01855e1e225e0..f8fcc3abefbf8 100644
      --- a/core/src/main/java/hudson/lifecycle/ExitLifecycle.java
      +++ b/core/src/main/java/hudson/lifecycle/ExitLifecycle.java
      @@ -21,6 +21,7 @@
        * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        * THE SOFTWARE.
        */
      +
       package hudson.lifecycle;
       
       import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
      diff --git a/core/src/main/java/hudson/lifecycle/Lifecycle.java b/core/src/main/java/hudson/lifecycle/Lifecycle.java
      index 04123c797ef0b..a44e4c39fb83c 100644
      --- a/core/src/main/java/hudson/lifecycle/Lifecycle.java
      +++ b/core/src/main/java/hudson/lifecycle/Lifecycle.java
      @@ -1,18 +1,18 @@
       /*
        * The MIT License
      - * 
      + *
        * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
      - * 
      + *
        * Permission is hereby granted, free of charge, to any person obtaining a copy
        * 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:
      - * 
      + *
        * The above copyright notice and this permission notice shall be included in
        * all copies or substantial portions of the Software.
      - * 
      + *
        * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      @@ -21,8 +21,11 @@
        * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        * THE SOFTWARE.
        */
      +
       package hudson.lifecycle;
       
      +import edu.umd.cs.findbugs.annotations.CheckForNull;
      +import edu.umd.cs.findbugs.annotations.NonNull;
       import hudson.ExtensionPoint;
       import hudson.Functions;
       import hudson.Util;
      @@ -31,6 +34,7 @@
       import java.io.UncheckedIOException;
       import java.lang.reflect.InvocationTargetException;
       import java.nio.file.Files;
      +import java.util.concurrent.TimeUnit;
       import java.util.logging.Level;
       import java.util.logging.Logger;
       import jenkins.model.Jenkins;
      @@ -51,19 +55,32 @@
       public abstract class Lifecycle implements ExtensionPoint {
           private static Lifecycle INSTANCE = null;
       
      +    public Lifecycle() {
      +        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
      +            Jenkins jenkins = Jenkins.getInstanceOrNull();
      +            if (jenkins != null) {
      +                try {
      +                    jenkins.cleanUp();
      +                } catch (Throwable t) {
      +                    LOGGER.log(Level.SEVERE, "Failed to clean up. Shutdown will continue.", t);
      +                }
      +            }
      +        }));
      +    }
      +
           /**
            * Gets the singleton instance.
            *
            * @return never null
            */
           public static synchronized Lifecycle get() {
      -        if(INSTANCE==null) {
      +        if (INSTANCE == null) {
                   Lifecycle instance;
                   String p = SystemProperties.getString("hudson.lifecycle");
      -            if(p!=null) {
      +            if (p != null) {
                       try {
                           ClassLoader cl = Jenkins.get().getPluginManager().uberClassLoader;
      -                    instance = (Lifecycle)cl.loadClass(p).getDeclaredConstructor().newInstance();
      +                    instance = (Lifecycle) cl.loadClass(p).getDeclaredConstructor().newInstance();
                       } catch (NoSuchMethodException e) {
                           NoSuchMethodError x = new NoSuchMethodError(e.getMessage());
                           x.initCause(e);
      @@ -95,7 +112,7 @@ public static synchronized Lifecycle get() {
                           }
                       }
                   } else {
      -                if(Functions.isWindows()) {
      +                if (Functions.isWindows()) {
                           instance = new Lifecycle() {
                               @Override
                               public void verifyRestartable() throws RestartNotSupportedException {
      @@ -103,15 +120,18 @@ public void verifyRestartable() throws RestartNotSupportedException {
                                           "Default Windows lifecycle does not support restart.");
                               }
                           };
      -                } else if (System.getenv("SMF_FMRI")!=null && System.getenv("SMF_RESTARTER")!=null) {
      +                } else if (System.getenv("SMF_FMRI") != null && System.getenv("SMF_RESTARTER") != null) {
                           // when we are run by Solaris SMF, these environment variables are set.
                           instance = new SolarisSMFLifecycle();
      +                } else if (System.getenv("NOTIFY_SOCKET") != null) {
      +                    // When we are running under systemd with Type=notify, this environment variable is set.
      +                    instance = new SystemdLifecycle();
                       } else {
                           // if run on Unix, we can do restart
                           try {
                               instance = new UnixLifecycle();
                           } catch (final IOException e) {
      -                        LOGGER.log(Level.WARNING, "Failed to install embedded lifecycle implementation",e);
      +                        LOGGER.log(Level.WARNING, "Failed to install embedded lifecycle implementation", e);
                               instance = new Lifecycle() {
                                   @Override
                                   public void verifyRestartable() throws RestartNotSupportedException {
      @@ -139,7 +159,7 @@ public void verifyRestartable() throws RestartNotSupportedException {
            */
           public File getHudsonWar() {
               String war = SystemProperties.getString("executable-war");
      -        if(war!=null && new File(war).exists())
      +        if (war != null && new File(war).exists())
                   return new File(war);
               return null;
           }
      @@ -156,7 +176,7 @@ public void rewriteHudsonWar(File by) throws IOException {
               File dest = getHudsonWar();
               // this should be impossible given the canRewriteHudsonWar method,
               // but let's be defensive
      -        if(dest==null)  throw new IOException("jenkins.war location is not known.");
      +        if (dest == null)  throw new IOException("jenkins.war location is not known.");
       
               // backing up the old jenkins.war before it gets lost due to upgrading
               // (newly downloaded jenkins.war and 'backup' (jenkins.war.tmp) are the same files
      @@ -164,7 +184,7 @@ public void rewriteHudsonWar(File by) throws IOException {
               File bak = new File(dest.getPath() + ".bak");
               if (!by.equals(bak))
                   FileUtils.copyFile(dest, bak);
      -       
      +
               FileUtils.copyFile(by, dest);
               // we don't want to keep backup if we are downgrading
               if (by.equals(bak)) {
      @@ -213,7 +233,7 @@ public void restart() throws IOException, InterruptedException {
            */
           public void verifyRestartable() throws RestartNotSupportedException {
               // the rewriteHudsonWar method isn't overridden.
      -        if (!Util.isOverridden(Lifecycle.class,getClass(), "restart"))
      +        if (!Util.isOverridden(Lifecycle.class, getClass(), "restart"))
                   throw new RestartNotSupportedException("Restart is not supported in this running mode (" +
                           getClass().getName() + ").");
           }
      @@ -231,5 +251,74 @@ public boolean canRestart() {
               }
           }
       
      +    /**
      +     * Called when Jenkins startup is finished or when Jenkins has finished reloading its
      +     * configuration.
      +     *
      +     * @since 2.333
      +     */
      +    public void onReady() {
      +        LOGGER.log(Level.INFO, "Jenkins is fully up and running");
      +    }
      +
      +    /**
      +     * Called when Jenkins is reloading its configuration.
      +     *
      +     * 

      Callers must also send an {@link #onReady()} notification when Jenkins has finished + * reloading its configuration. + * + * @since 2.333 + */ + public void onReload(@NonNull String user, @CheckForNull String remoteAddr) { + if (remoteAddr != null) { + LOGGER.log( + Level.INFO, + "Reloading Jenkins as requested by {0} from {1}", + new Object[] {user, remoteAddr}); + } else { + LOGGER.log(Level.INFO, "Reloading Jenkins as requested by {0}", user); + } + } + + /** + * Called when Jenkins is beginning its shutdown. + * + * @since 2.333 + */ + public void onStop(@NonNull String user, @CheckForNull String remoteAddr) { + if (remoteAddr != null) { + LOGGER.log( + Level.INFO, + "Stopping Jenkins as requested by {0} from {1}", + new Object[] {user, remoteAddr}); + } else { + LOGGER.log(Level.INFO, "Stopping Jenkins as requested by {0}", user); + } + } + + /** + * Tell the service manager to extend the startup or shutdown timeout. The value specified is a + * time during which either {@link #onExtendTimeout(long, TimeUnit)} must be called again or + * startup/shutdown must complete. + * + * @param timeout The amount by which to extend the timeout. + * @param unit The time unit of the timeout argument. + * + * @since 2.335 + */ + public void onExtendTimeout(long timeout, @NonNull TimeUnit unit) {} + + /** + * Called when Jenkins service state has changed. + * + * @param status The status string. This is free-form and can be used for various purposes: + * general state feedback, completion percentages, human-readable error message, etc. + * + * @since 2.333 + */ + public void onStatusUpdate(String status) { + LOGGER.log(Level.INFO, status); + } + private static final Logger LOGGER = Logger.getLogger(Lifecycle.class.getName()); } diff --git a/core/src/main/java/hudson/lifecycle/RestartNotSupportedException.java b/core/src/main/java/hudson/lifecycle/RestartNotSupportedException.java index 08bae8291c06a..50f87f4570448 100644 --- a/core/src/main/java/hudson/lifecycle/RestartNotSupportedException.java +++ b/core/src/main/java/hudson/lifecycle/RestartNotSupportedException.java @@ -2,7 +2,7 @@ /** * Indicates that the {@link Lifecycle} doesn't support restart. - * + * * @author Kohsuke Kawaguchi */ public class RestartNotSupportedException extends Exception { diff --git a/core/src/main/java/hudson/lifecycle/SolarisSMFLifecycle.java b/core/src/main/java/hudson/lifecycle/SolarisSMFLifecycle.java index eecc28ea26de4..2dd3629365993 100644 --- a/core/src/main/java/hudson/lifecycle/SolarisSMFLifecycle.java +++ b/core/src/main/java/hudson/lifecycle/SolarisSMFLifecycle.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.lifecycle; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; diff --git a/core/src/main/java/hudson/lifecycle/SystemdLifecycle.java b/core/src/main/java/hudson/lifecycle/SystemdLifecycle.java new file mode 100644 index 0000000000000..8d6b684cfe41c --- /dev/null +++ b/core/src/main/java/hudson/lifecycle/SystemdLifecycle.java @@ -0,0 +1,67 @@ +package hudson.lifecycle; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import edu.umd.cs.findbugs.annotations.CheckForNull; +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.Extension; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +/** + * {@link Lifecycle} that delegates its responsibility to {@code systemd(1)}. + * + * @author Basil Crow + */ +@Restricted(NoExternalUse.class) +@Extension(optional = true) +public class SystemdLifecycle extends ExitLifecycle { + + private static final Logger LOGGER = Logger.getLogger(SystemdLifecycle.class.getName()); + + interface Systemd extends Library { + Systemd INSTANCE = Native.load("systemd", Systemd.class); + + int sd_notify(int unset_environment, String state); + } + + @Override + public void onReady() { + super.onReady(); + notify("READY=1"); + } + + @Override + public void onReload(@NonNull String user, @CheckForNull String remoteAddr) { + super.onReload(user, remoteAddr); + notify("RELOADING=1"); + } + + @Override + public void onStop(@NonNull String user, @CheckForNull String remoteAddr) { + super.onStop(user, remoteAddr); + notify("STOPPING=1"); + } + + @Override + public void onExtendTimeout(long timeout, @NonNull TimeUnit unit) { + super.onExtendTimeout(timeout, unit); + notify(String.format("EXTEND_TIMEOUT_USEC=%d", unit.toMicros(timeout))); + } + + @Override + public void onStatusUpdate(String status) { + super.onStatusUpdate(status); + notify(String.format("STATUS=%s", status)); + } + + private static synchronized void notify(String message) { + int rv = Systemd.INSTANCE.sd_notify(0, message); + if (rv < 0) { + LOGGER.log(Level.WARNING, "sd_notify(3) returned {0}", rv); + } + } +} diff --git a/core/src/main/java/hudson/lifecycle/UnixLifecycle.java b/core/src/main/java/hudson/lifecycle/UnixLifecycle.java index 498db2c0e9845..ca8f50b9f589d 100644 --- a/core/src/main/java/hudson/lifecycle/UnixLifecycle.java +++ b/core/src/main/java/hudson/lifecycle/UnixLifecycle.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.lifecycle; import static hudson.util.jna.GNUCLibrary.FD_CLOEXEC; @@ -74,16 +75,16 @@ public void restart() throws IOException, InterruptedException { // close all files upon exec, except stdin, stdout, and stderr int sz = LIBC.getdtablesize(); - for(int i=3; i' + getHudsonWar().getAbsolutePath() + '\n'); } } @@ -133,20 +137,20 @@ public void restart() throws IOException, InterruptedException { task.getLogger().println("Restarting a service"); String exe = System.getenv("WINSW_EXECUTABLE"); File executable; - if (exe!=null) executable = new File(exe); + if (exe != null) executable = new File(exe); else executable = new File(home, "hudson.exe"); if (!executable.exists()) executable = new File(home, "jenkins.exe"); // use restart! to run hudson/jenkins.exe restart in a separate process, so it doesn't kill itself int r = new LocalLauncher(task).launch().cmds(executable, "restart!") .stdout(task).pwd(home).join(); - if(r!=0) + if (r != 0) throw new IOException(baos.toString()); } - + private static File getBaseDir() { File baseDir; - + String baseEnv = System.getenv("BASE"); if (baseEnv != null) { baseDir = new File(baseEnv); diff --git a/core/src/main/java/hudson/logging/LogRecorder.java b/core/src/main/java/hudson/logging/LogRecorder.java index 4155576a9e9ef..04db695f69242 100644 --- a/core/src/main/java/hudson/logging/LogRecorder.java +++ b/core/src/main/java/hudson/logging/LogRecorder.java @@ -21,10 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.logging; import com.google.common.annotations.VisibleForTesting; import com.thoughtworks.xstream.XStream; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.BulkChange; import hudson.Extension; import hudson.FilePath; @@ -88,7 +90,7 @@ * * TODO: still a work in progress. * - *

      Access Control

      + *

      Access Control: * {@link LogRecorder} is only visible for administrators and system readers, and this access control happens at * {@link jenkins.model.Jenkins#getLog()}, the sole entry point for binding {@link LogRecorder} to URL. * @@ -115,7 +117,7 @@ public LogRecorder(String name) { this.name = name; // register it only once when constructed, and when this object dies // WeakLogHandler will remove it - new WeakLogHandler(handler,Logger.getLogger("")); + new WeakLogHandler(handler, Logger.getLogger("")); } private Object readResolve() { @@ -241,7 +243,7 @@ public static final class Target { private transient /* almost final*/ Logger logger; public Target(String name, Level level) { - this(name,level.intValue()); + this(name, level.intValue()); } public Target(String name, int level) { @@ -251,7 +253,7 @@ public Target(String name, int level) { @DataBoundConstructor public Target(String name, String level) { - this(name,Level.parse(level)); + this(name, Level.parse(level)); } public Level getLevel() { @@ -281,28 +283,29 @@ public int hashCode() { @Deprecated public boolean includes(LogRecord r) { - if(r.getLevel().intValue() < level) + if (r.getLevel().intValue() < level) return false; // below the threshold if (name.length() == 0) { return true; // like root logger, includes everything } String logName = r.getLoggerName(); - if(logName==null || !logName.startsWith(name)) + if (logName == null || !logName.startsWith(name)) return false; // not within this logger String rest = logName.substring(name.length()); - return rest.startsWith(".") || rest.length()==0; + return rest.startsWith(".") || rest.length() == 0; } + @SuppressFBWarnings(value = "NP_BOOLEAN_RETURN_NULL", justification = "converting this to YesNoMaybe would break backward compatibility") public Boolean matches(LogRecord r) { boolean levelSufficient = r.getLevel().intValue() >= level; if (name.length() == 0) { return levelSufficient; // include if level matches } String logName = r.getLoggerName(); - if(logName==null || !logName.startsWith(name)) + if (logName == null || !logName.startsWith(name)) return null; // not in the domain of this logger String rest = logName.substring(name.length()); - if (rest.startsWith(".") || rest.length()==0) { + if (rest.startsWith(".") || rest.length() == 0) { return levelSufficient; // include if level matches } return null; @@ -320,7 +323,7 @@ public Logger getLogger() { */ public void enable() { Logger l = getLogger(); - if(!l.isLoggable(getLevel())) + if (!l.isLoggable(getLevel())) l.setLevel(getLevel()); new SetLevel(name, getLevel()).broadcast(); } @@ -342,21 +345,24 @@ public int compare(Target left, Target right) { } } - private static final class SetLevel extends MasterToSlaveCallable { + private static final class SetLevel extends MasterToSlaveCallable { /** known loggers (kept per agent), to avoid GC */ @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") private static final Set loggers = new HashSet<>(); private final String name; private final Level level; + SetLevel(String name, Level level) { this.name = name; this.level = level; } + @Override public Void call() throws Error { Logger logger = Logger.getLogger(name); loggers.add(logger); logger.setLevel(level); return null; } + void broadcast() { for (Computer c : Jenkins.get().getComputers()) { if (c.getName().length() > 0) { // i.e. not master @@ -405,14 +411,14 @@ public LogRecorderManager getParent() { * Accepts submission from the configuration page. */ @POST - public synchronized void doConfigSubmit( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public synchronized void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { Jenkins.get().checkPermission(Jenkins.ADMINISTER); JSONObject src = req.getSubmittedForm(); String newName = src.getString("name"), redirect = "."; XmlFile oldFile = null; - if(!name.equals(newName)) { + if (!name.equals(newName)) { Jenkins.checkGoodName(newName); oldFile = getConfigFile(); // rename @@ -428,7 +434,7 @@ public synchronized void doConfigSubmit( StaplerRequest req, StaplerResponse rsp setLoggers(newTargets); save(); - if (oldFile!=null) oldFile.delete(); + if (oldFile != null) oldFile.delete(); rsp.sendRedirect2(redirect); } @@ -453,7 +459,7 @@ public synchronized void load() throws IOException { */ @Override public synchronized void save() throws IOException { - if(BulkChange.contains(this)) return; + if (BulkChange.contains(this)) return; handlePluginUpdatingLegacyLogManagerMap(); getConfigFile().write(this); @@ -517,8 +523,8 @@ public synchronized void doDoDelete(StaplerResponse rsp) throws IOException, Ser /** * RSS feed for log entries. */ - public void doRss( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { - LogRecorderManager.doRss(req,rsp,getLogRecords()); + public void doRss(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { + LogRecorderManager.doRss(req, rsp, getLogRecords()); } /** @@ -540,8 +546,8 @@ public List getLogRecords() { * @return a map (sorted by display name) from computer to (nonempty) list of log records * @since 1.519 */ - public Map> getSlaveLogRecords() { - Map> result = new TreeMap<>(new Comparator() { + public Map> getSlaveLogRecords() { + Map> result = new TreeMap<>(new Comparator() { final Collator COLL = Collator.getInstance(); @Override @@ -579,8 +585,8 @@ public int compare(Computer c1, Computer c2) { public static final XStream XSTREAM = new XStream2(); static { - XSTREAM.alias("log",LogRecorder.class); - XSTREAM.alias("target",Target.class); + XSTREAM.alias("log", LogRecorder.class); + XSTREAM.alias("target", Target.class); } /** diff --git a/core/src/main/java/hudson/logging/LogRecorderManager.java b/core/src/main/java/hudson/logging/LogRecorderManager.java index 3d7164a2dcd92..0ea3a58267adf 100644 --- a/core/src/main/java/hudson/logging/LogRecorderManager.java +++ b/core/src/main/java/hudson/logging/LogRecorderManager.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.logging; import static hudson.init.InitMilestone.PLUGINS_PREPARED; @@ -32,6 +33,7 @@ import hudson.RestrictedSince; import hudson.init.Initializer; import hudson.model.AbstractModelObject; +import hudson.model.Failure; import hudson.model.RSS; import hudson.util.CopyOnWriteMap; import java.io.File; @@ -39,12 +41,14 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; +import java.util.Collections; import java.util.GregorianCalendar; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.function.Function; import java.util.logging.Level; +import java.util.logging.LogManager; import java.util.logging.LogRecord; import java.util.logging.Logger; import javax.servlet.ServletException; @@ -80,7 +84,7 @@ public class LogRecorderManager extends AbstractModelObject implements ModelObje @Deprecated @Restricted(NoExternalUse.class) @RestrictedSince("TODO") - public final transient Map logRecorders = new CopyOnWriteMap.Tree<>(); + public final transient Map logRecorders = new CopyOnWriteMap.Tree<>(); private List recorders; @@ -99,7 +103,7 @@ public void setRecorders(List recorders) { Map values = recorders.stream() .collect(toMap(LogRecorder::getName, Function.identity())); - ((CopyOnWriteMap) logRecorders).replaceBy(values); + ((CopyOnWriteMap) logRecorders).replaceBy(values); } @Override @@ -130,11 +134,11 @@ static File configDir() { public void load() throws IOException { recorders.clear(); File dir = configDir(); - File[] files = dir.listFiles((FileFilter)new WildcardFileFilter("*.xml")); - if(files==null) return; + File[] files = dir.listFiles((FileFilter) new WildcardFileFilter("*.xml")); + if (files == null) return; for (File child : files) { String name = child.getName(); - name = name.substring(0,name.length()-4); // cut off ".xml" + name = name.substring(0, name.length() - 4); // cut off ".xml" LogRecorder lr = new LogRecorder(name); lr.load(); recorders.add(lr); @@ -154,13 +158,13 @@ public HttpResponse doNewLogRecorder(@QueryParameter String name) { recorders.add(new LogRecorder(name)); // redirect to the config screen - return new HttpRedirect(name+"/configure"); + return new HttpRedirect(name + "/configure"); } @Override public ContextMenu doChildrenContextMenu(StaplerRequest request, StaplerResponse response) throws Exception { ContextMenu menu = new ContextMenu(); - menu.add("all","All Jenkins Logs"); + menu.add("all", "All Jenkins Logs"); for (LogRecorder lr : recorders) { menu.add(lr.getSearchUrl(), lr.getDisplayName()); } @@ -170,23 +174,32 @@ public ContextMenu doChildrenContextMenu(StaplerRequest request, StaplerResponse /** * Configure the logging level. */ - @SuppressFBWarnings(value = "LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE", justification = "TODO needs triage") @RequirePOST + @SuppressFBWarnings( + value = "LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE", + justification = + "if the logger is known, then we have a reference to it in LogRecorder#loggers") public HttpResponse doConfigLogger(@QueryParameter String name, @QueryParameter String level) { Jenkins.get().checkPermission(Jenkins.ADMINISTER); Level lv; - if(level.equals("inherit")) + if (level.equals("inherit")) lv = null; else lv = Level.parse(level.toUpperCase(Locale.ENGLISH)); - Logger.getLogger(name).setLevel(lv); - return new HttpRedirect("levels"); + Logger target; + if (Collections.list(LogManager.getLogManager().getLoggerNames()).contains(name) + && (target = Logger.getLogger(name)) != null) { + target.setLevel(lv); + return new HttpRedirect("levels"); + } else { + throw new Failure(Messages.LogRecorderManager_LoggerNotFound(name)); + } } /** * RSS feed for log entries. */ - public void doRss( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public void doRss(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { doRss(req, rsp, Jenkins.logRecords); } @@ -197,18 +210,18 @@ public void doRss( StaplerRequest req, StaplerResponse rsp ) throws IOException, // filter log records based on the log level String entryType = "all"; String level = req.getParameter("level"); - if(level!=null) { + if (level != null) { Level threshold = Level.parse(level); List filtered = new ArrayList<>(); for (LogRecord r : logs) { - if(r.getLevel().intValue() >= threshold.intValue()) + if (r.getLevel().intValue() >= threshold.intValue()) filtered.add(r); } logs = filtered; entryType = level; } - RSS.forwardToRss("Jenkins:log (" + entryType + " entries)","", logs, new FeedAdapter() { + RSS.forwardToRss("Jenkins:log (" + entryType + " entries)", "", logs, new FeedAdapter() { @Override public String getEntryTitle(LogRecord entry) { return entry.getMessage(); @@ -240,10 +253,10 @@ public Calendar getEntryTimestamp(LogRecord entry) { public String getEntryAuthor(LogRecord entry) { return JenkinsLocationConfiguration.get().getAdminAddress(); } - },req,rsp); + }, req, rsp); } - @Initializer(before=PLUGINS_PREPARED) + @Initializer(before = PLUGINS_PREPARED) public static void init(Jenkins h) throws IOException { h.getLog().load(); } diff --git a/core/src/main/java/hudson/logging/WeakLogHandler.java b/core/src/main/java/hudson/logging/WeakLogHandler.java index 21fd6bdfe2cc9..bc0cb1c349a47 100644 --- a/core/src/main/java/hudson/logging/WeakLogHandler.java +++ b/core/src/main/java/hudson/logging/WeakLogHandler.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.logging; import java.io.UnsupportedEncodingException; @@ -50,27 +51,27 @@ public WeakLogHandler(Handler target, Logger logger) { @Override public void publish(LogRecord record) { Handler t = resolve(); - if(t!=null) + if (t != null) t.publish(record); } @Override public void flush() { Handler t = resolve(); - if(t!=null) + if (t != null) t.flush(); } @Override public void close() throws SecurityException { Handler t = resolve(); - if(t!=null) + if (t != null) t.close(); } private Handler resolve() { Handler r = target.get(); - if(r==null) + if (r == null) logger.removeHandler(this); return r; } @@ -79,7 +80,7 @@ private Handler resolve() { public void setFormatter(Formatter newFormatter) throws SecurityException { super.setFormatter(newFormatter); Handler t = resolve(); - if(t!=null) + if (t != null) t.setFormatter(newFormatter); } @@ -87,7 +88,7 @@ public void setFormatter(Formatter newFormatter) throws SecurityException { public void setEncoding(String encoding) throws SecurityException, UnsupportedEncodingException { super.setEncoding(encoding); Handler t = resolve(); - if(t!=null) + if (t != null) t.setEncoding(encoding); } @@ -95,7 +96,7 @@ public void setEncoding(String encoding) throws SecurityException, UnsupportedEn public void setFilter(Filter newFilter) throws SecurityException { super.setFilter(newFilter); Handler t = resolve(); - if(t!=null) + if (t != null) t.setFilter(newFilter); } @@ -103,7 +104,7 @@ public void setFilter(Filter newFilter) throws SecurityException { public void setErrorManager(ErrorManager em) { super.setErrorManager(em); Handler t = resolve(); - if(t!=null) + if (t != null) t.setErrorManager(em); } @@ -111,14 +112,14 @@ public void setErrorManager(ErrorManager em) { public void setLevel(Level newLevel) throws SecurityException { super.setLevel(newLevel); Handler t = resolve(); - if(t!=null) + if (t != null) t.setLevel(newLevel); } @Override public boolean isLoggable(LogRecord record) { Handler t = resolve(); - if(t!=null) + if (t != null) return t.isLoggable(record); else return super.isLoggable(record); diff --git a/core/src/main/java/hudson/markup/EscapedMarkupFormatter.java b/core/src/main/java/hudson/markup/EscapedMarkupFormatter.java index 338eea2652fe7..de83afabce6ce 100644 --- a/core/src/main/java/hudson/markup/EscapedMarkupFormatter.java +++ b/core/src/main/java/hudson/markup/EscapedMarkupFormatter.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.markup; import hudson.Extension; diff --git a/core/src/main/java/hudson/markup/MarkupFormatter.java b/core/src/main/java/hudson/markup/MarkupFormatter.java index 14a293790e3a7..e588e0cfcc8e7 100644 --- a/core/src/main/java/hudson/markup/MarkupFormatter.java +++ b/core/src/main/java/hudson/markup/MarkupFormatter.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.markup; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -62,7 +63,7 @@ * Implement the following methods to enable and control CodeMirror syntax highlighting * public String getCodeMirrorMode() // return null to disable CodeMirror dynamically * public String getCodeMirrorConfig() - * + * *

      Views

      *

      * This extension point must have a valid {@code config.jelly} that feeds the constructor. @@ -92,7 +93,7 @@ public abstract class MarkupFormatter extends AbstractDescribableImpl all() { + public static DescriptorExtensionList all() { return Jenkins.get(). getDescriptorList(MarkupFormatter.class); } diff --git a/core/src/main/java/hudson/model/AbstractBuild.java b/core/src/main/java/hudson/model/AbstractBuild.java index 0a7f1cb683237..4c02e525904d5 100644 --- a/core/src/main/java/hudson/model/AbstractBuild.java +++ b/core/src/main/java/hudson/model/AbstractBuild.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static java.util.logging.Level.WARNING; @@ -65,6 +66,7 @@ import java.io.IOException; import java.io.InterruptedIOException; import java.lang.ref.WeakReference; +import java.nio.channels.ClosedByInterruptException; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; @@ -101,7 +103,7 @@ * @author Kohsuke Kawaguchi * @see AbstractProject */ -public abstract class AbstractBuild

      ,R extends AbstractBuild> extends Run implements Queue.Executable, LazyBuildMixIn.LazyLoadingRun, RunWithSCM { +public abstract class AbstractBuild

      , R extends AbstractBuild> extends Run implements Queue.Executable, LazyBuildMixIn.LazyLoadingRun, RunWithSCM { /** * Set if we want the blame information to flow from upstream to downstream build. @@ -156,7 +158,7 @@ public abstract class AbstractBuild

      ,R extends Abs */ protected transient List buildEnvironments; - private final transient LazyBuildMixIn.RunMixIn runMixIn = new LazyBuildMixIn.RunMixIn() { + private final transient LazyBuildMixIn.RunMixIn runMixIn = new LazyBuildMixIn.RunMixIn() { @Override protected R asRun() { return _this(); } @@ -178,7 +180,7 @@ public final P getProject() { return getParent(); } - @Override public final LazyBuildMixIn.RunMixIn getRunMixIn() { + @Override public final LazyBuildMixIn.RunMixIn getRunMixIn() { return runMixIn; } @@ -207,7 +209,7 @@ public R getNextBuild() { * null, for example if the agent that this build run no longer exists. */ public @CheckForNull Node getBuiltOn() { - if (builtOn==null || builtOn.equals("")) + if (builtOn == null || builtOn.equals("")) return Jenkins.get(); else return Jenkins.get().getNode(builtOn); @@ -217,7 +219,7 @@ public R getNextBuild() { * Returns the name of the agent it was built on; null or "" if built by the built-in node. * (null happens when we read old record that didn't have this information.) */ - @Exported(name="builtOn") + @Exported(name = "builtOn") public String getBuiltOnStr() { return builtOn; } @@ -229,7 +231,7 @@ public String getBuiltOnStr() { * * @since 1.429 */ - protected void setBuiltOnStr( String builtOn ) { + protected void setBuiltOnStr(String builtOn) { this.builtOn = builtOn; } @@ -247,7 +249,7 @@ protected void setBuiltOnStr( String builtOn ) { * @since 1.421 * @see AbstractProject#getRootProject() */ - public AbstractBuild getRootBuild() { + public AbstractBuild getRootBuild() { return this; } @@ -270,7 +272,7 @@ public Queue.Executable getParentExecutable() { * {@link #getDisplayName()}. */ public String getUpUrl() { - return Functions.getNearestAncestorUrl(Stapler.getCurrentRequest(),getParent())+'/'; + return Functions.getNearestAncestorUrl(Stapler.getCurrentRequest(), getParent()) + '/'; } /** @@ -287,9 +289,9 @@ public String getUpUrl() { * @since 1.319 */ public final @CheckForNull FilePath getWorkspace() { - if (workspace==null) return null; + if (workspace == null) return null; Node n = getBuiltOn(); - if (n==null) return null; + if (n == null) return null; return n.createPath(workspace); } @@ -309,7 +311,7 @@ protected void setWorkspace(@NonNull FilePath ws) { */ public final FilePath getModuleRoot() { FilePath ws = getWorkspace(); - if (ws==null) return null; + if (ws == null) return null; return getParent().getScm().getModuleRoot(ws, this); } @@ -322,7 +324,7 @@ public final FilePath getModuleRoot() { */ public FilePath[] getModuleRoots() { FilePath ws = getWorkspace(); - if (ws==null) return null; + if (ws == null) return null; return getParent().getScm().getModuleRoots(ws, this); } @@ -347,7 +349,7 @@ public boolean shouldCalculateCulprits() { public Set calculateCulprits() { Set c = RunWithSCM.super.calculateCulprits(); - AbstractBuild p = getPreviousCompletedBuild(); + AbstractBuild p = getPreviousCompletedBuild(); if (upstreamCulprits) { // If we have dependencies since the last successful build, add their authors to our list if (p != null && p.getPreviousNotFailedBuild() != null) { @@ -461,8 +463,8 @@ protected Lease decideWorkspace(@NonNull Node n, WorkspaceList wsl) throws Inter @Override public Result run(@NonNull BuildListener listener) throws Exception { final Node node = getCurrentNode(); - - assert builtOn==null; + + assert builtOn == null; builtOn = node.getNodeName(); hudsonVersion = Jenkins.VERSION; this.listener = listener; @@ -501,7 +503,7 @@ public Result run(@NonNull BuildListener listener) throws Exception { } else { listener.getLogger().print(Messages.AbstractBuild_Building()); } - + lease = decideWorkspace(node, Computer.currentComputer().getWorkspaceList()); workspace = lease.path.getRemote(); @@ -514,7 +516,7 @@ public Result run(@NonNull BuildListener listener) throws Exception { getProject().getScmCheckoutStrategy().preCheckout(AbstractBuild.this, launcher, this.listener); getProject().getScmCheckoutStrategy().checkout(this); - if (!preBuild(listener,project.getProperties())) + if (!preBuild(listener, project.getProperties())) return Result.FAILURE; result = doRun(listener); @@ -534,8 +536,8 @@ public Result run(@NonNull BuildListener listener) throws Exception { // this is ugly, but for historical reason, if non-null value is returned // it should become the final result. - if (result==null) result = getResult(); - if (result==null) result = Result.SUCCESS; + if (result == null) result = getResult(); + if (result == null) result = Result.SUCCESS; return result; } @@ -573,7 +575,7 @@ private Result tearDownBuildEnvironments(@NonNull BuildListener listener) throws } } catch (IOException | RuntimeException e) { // exceptions are only logged, to give a chance to all environments to tear down - if(e instanceof IOException) { + if (e instanceof IOException) { // similar to Run#handleFatalBuildProblem(BuildListener, Throwable) Util.displayIOException((IOException) e, listener); } @@ -604,24 +606,24 @@ protected Launcher createLauncher(@NonNull BuildListener listener) throws IOExce if (project instanceof BuildableItemWithBuildWrappers) { BuildableItemWithBuildWrappers biwbw = (BuildableItemWithBuildWrappers) project; for (BuildWrapper bw : biwbw.getBuildWrappersList()) - l = bw.decorateLauncher(AbstractBuild.this,l,listener); + l = bw.decorateLauncher(AbstractBuild.this, l, listener); } - for (RunListener rl: RunListener.all()) { + for (RunListener rl : RunListener.all()) { Environment environment = rl.setUpEnvironment(AbstractBuild.this, l, listener); if (environment != null) { buildEnvironments.add(environment); } } - for (NodeProperty nodeProperty: Jenkins.get().getGlobalNodeProperties()) { + for (NodeProperty nodeProperty : Jenkins.get().getGlobalNodeProperties()) { Environment environment = nodeProperty.setUp(AbstractBuild.this, l, listener); if (environment != null) { buildEnvironments.add(environment); } } - for (NodeProperty nodeProperty: currentNode.getNodeProperties()) { + for (NodeProperty nodeProperty : currentNode.getNodeProperties()) { Environment environment = nodeProperty.setUp(AbstractBuild.this, l, listener); if (environment != null) { buildEnvironments.add(environment); @@ -632,15 +634,15 @@ protected Launcher createLauncher(@NonNull BuildListener listener) throws IOExce } public void defaultCheckout() throws IOException, InterruptedException { - AbstractBuild build = AbstractBuild.this; + AbstractBuild build = AbstractBuild.this; AbstractProject project = build.getProject(); - for (int retryCount=project.getScmCheckoutRetryCount(); ; retryCount--) { + for (int retryCount = project.getScmCheckoutRetryCount(); ; retryCount--) { build.scm = NullChangeLogParser.INSTANCE; try { File changeLogFile = new File(build.getRootDir(), "changelog.xml"); - if (project.checkout(build, launcher,listener, changeLogFile)) { + if (project.checkout(build, launcher, listener, changeLogFile)) { // check out succeeded SCM scm = project.getScm(); for (SCMListener l : SCMListener.all()) { @@ -656,20 +658,20 @@ public void defaultCheckout() throws IOException, InterruptedException { for (SCMListener l : SCMListener.all()) try { - l.onChangeLogParsed(build,listener,build.getChangeSet()); + l.onChangeLogParsed(build, listener, build.getChangeSet()); } catch (Exception e) { - throw new IOException("Failed to parse changelog",e); + throw new IOException("Failed to parse changelog", e); } // Get a chance to do something after checkout and changelog is done - scm.postCheckout( build, launcher, build.getWorkspace(), listener ); + scm.postCheckout(build, launcher, build.getWorkspace(), listener); return; } } catch (AbortException e) { listener.error(e.getMessage()); - } catch (InterruptedIOException e) { - throw (InterruptedException)new InterruptedException().initCause(e); + } catch (ClosedByInterruptException | InterruptedIOException e) { + throw (InterruptedException) new InterruptedException().initCause(e); } catch (IOException e) { // checkout error not yet reported Functions.printStackTrace(e, listener.getLogger()); @@ -692,7 +694,7 @@ public void defaultCheckout() throws IOException, InterruptedException { * itself run successfully) * Return a non-null value to abort the build right there with the specified result code. */ - protected abstract Result doRun(BuildListener listener) throws Exception, RunnerAbortedException; + protected abstract Result doRun(BuildListener listener) throws Exception; /** * @see #post(BuildListener) @@ -715,7 +717,7 @@ public final void post(BuildListener listener) throws Exception { @Override public void cleanUp(BuildListener listener) throws Exception { - if (lease!=null) { + if (lease != null) { lease.release(); lease = null; } @@ -728,12 +730,12 @@ public void cleanUp(BuildListener listener) throws Exception { * Use {@link #performAllBuildSteps(BuildListener, Map, boolean)} */ @Deprecated - protected final void performAllBuildStep(BuildListener listener, Map buildSteps, boolean phase) throws InterruptedException, IOException { - performAllBuildSteps(listener,buildSteps.values(),phase); + protected final void performAllBuildStep(BuildListener listener, Map buildSteps, boolean phase) throws InterruptedException, IOException { + performAllBuildSteps(listener, buildSteps.values(), phase); } - protected final boolean performAllBuildSteps(BuildListener listener, Map buildSteps, boolean phase) throws InterruptedException, IOException { - return performAllBuildSteps(listener,buildSteps.values(),phase); + protected final boolean performAllBuildSteps(BuildListener listener, Map buildSteps, boolean phase) throws InterruptedException, IOException { + return performAllBuildSteps(listener, buildSteps.values(), phase); } /** @@ -742,7 +744,7 @@ protected final boolean performAllBuildSteps(BuildListener listener, Map buildSteps, boolean phase) throws InterruptedException, IOException { - performAllBuildSteps(listener,buildSteps,phase); + performAllBuildSteps(listener, buildSteps, phase); } /** @@ -756,9 +758,9 @@ protected final void performAllBuildStep(BuildListener listener, Iterable buildSteps, boolean phase) throws InterruptedException, IOException { boolean r = true; for (BuildStep bs : buildSteps) { - if ((bs instanceof Publisher && ((Publisher)bs).needsToRunAfterFinalized()) ^ phase) + if ((bs instanceof Publisher && ((Publisher) bs).needsToRunAfterFinalized()) ^ phase) try { - if (!perform(bs,listener)) { + if (!perform(bs, listener)) { LOGGER.log(Level.FINE, "{0} : {1} failed", new Object[] {AbstractBuild.this, bs}); r = false; if (phase) { @@ -850,17 +852,17 @@ private String getBuildStepName(BuildStep bs) { } } - protected final boolean preBuild(BuildListener listener,Map steps) { - return preBuild(listener,steps.values()); + protected final boolean preBuild(BuildListener listener, Map steps) { + return preBuild(listener, steps.values()); } - protected final boolean preBuild(BuildListener listener,Collection steps) { - return preBuild(listener,(Iterable)steps); + protected final boolean preBuild(BuildListener listener, Collection steps) { + return preBuild(listener, (Iterable) steps); } - protected final boolean preBuild(BuildListener listener,Iterable steps) { + protected final boolean preBuild(BuildListener listener, Iterable steps) { for (BuildStep bs : steps) - if (!bs.prebuild(AbstractBuild.this,listener)) { + if (!bs.prebuild(AbstractBuild.this, listener)) { LOGGER.log(Level.FINE, "{0} : {1} failed", new Object[] {AbstractBuild.this, bs}); return false; } @@ -875,6 +877,7 @@ protected final boolean preBuild(BuildListener listener,Iterable getChangeSet() { synchronized (changeSetLock) { - if (scm==null) { - scm = NullChangeLogParser.INSTANCE; + if (scm == null) { + scm = NullChangeLogParser.INSTANCE; } } ChangeLogSet cs = null; - if (changeSet!=null) + if (changeSet != null) cs = changeSet.get(); - if (cs==null) + if (cs == null) cs = calcChangeSet(); // defensive check. if the calculation fails (such as through an exception), // set a dummy value so that it'll work the next time. the exception will // be still reported, giving the plugin developer an opportunity to fix it. - if (cs==null) + if (cs == null) cs = ChangeLogSet.createEmpty(this); changeSet = new WeakReference<>(cs); @@ -937,9 +940,9 @@ private ChangeLogSet calcChangeSet() { return ChangeLogSet.createEmpty(this); try { - return scm.parse(this,changelogFile); + return scm.parse(this, changelogFile); } catch (IOException | SAXException e) { - LOGGER.log(WARNING, "Failed to parse "+changelogFile,e); + LOGGER.log(WARNING, "Failed to parse " + changelogFile, e); } return ChangeLogSet.createEmpty(this); } @@ -956,14 +959,14 @@ public EnvVars getEnvironment(TaskListener log) throws IOException, InterruptedE } } - project.getScm().buildEnvVars(this,env); + project.getScm().buildEnvVars(this, env); - if (buildEnvironments!=null) + if (buildEnvironments != null) for (Environment e : buildEnvironments) e.buildEnvVars(env); for (EnvironmentContributingAction a : getActions(EnvironmentContributingAction.class)) - a.buildEnvVars(this,env); + a.buildEnvVars(this, env); EnvVars.resolve(env); @@ -972,24 +975,24 @@ public EnvVars getEnvironment(TaskListener log) throws IOException, InterruptedE /** * During the build, expose the environments contributed by {@link BuildWrapper}s and others. - * + * *

      * Since 1.444, executor thread that's doing the build can access mutable underlying list, * which allows the caller to add/remove environments. The recommended way of adding * environment is through {@link BuildWrapper}, but this might be handy for build steps * who wants to expose additional environment variables to the rest of the build. - * + * * @return can be empty list, but never null. Immutable. * @since 1.437 */ public EnvironmentList getEnvironments() { Executor e = Executor.currentExecutor(); - if (e!=null && e.getCurrentExecutable()==this) { - if (buildEnvironments==null) buildEnvironments = new ArrayList<>(); - return new EnvironmentList(buildEnvironments); + if (e != null && e.getCurrentExecutable() == this) { + if (buildEnvironments == null) buildEnvironments = new ArrayList<>(); + return new EnvironmentList(buildEnvironments); } - - return new EnvironmentList(buildEnvironments==null ? Collections.emptyList() : Collections.unmodifiableList(new ArrayList<>(buildEnvironments))); + + return new EnvironmentList(buildEnvironments == null ? Collections.emptyList() : Collections.unmodifiableList(new ArrayList<>(buildEnvironments))); } public Calendar due() { @@ -1003,9 +1006,9 @@ public Calendar due() { @Override public void addAction(Action a) { super.addAction(a); } - + @SuppressWarnings("deprecation") - public List getPersistentActions(){ + public List getPersistentActions() { return super.getActions(); } @@ -1035,7 +1038,7 @@ public Set getSensitiveBuildVariables() { bw.makeSensitiveBuildVariables(this, s); } } - + return s; } @@ -1054,26 +1057,26 @@ public Set getSensitiveBuildVariables() { * @return * The returned map is mutable so that subtypes can put more values. */ - public Map getBuildVariables() { - Map r = new HashMap<>(); + public Map getBuildVariables() { + Map r = new HashMap<>(); ParametersAction parameters = getAction(ParametersAction.class); - if (parameters!=null) { + if (parameters != null) { // this is a rather round about way of doing this... for (ParameterValue p : parameters) { String v = p.createVariableResolver(this).resolve(p.getName()); - if (v!=null) r.put(p.getName(),v); + if (v != null) r.put(p.getName(), v); } } // allow the BuildWrappers to contribute additional build variables if (project instanceof BuildableItemWithBuildWrappers) { for (BuildWrapper bw : ((BuildableItemWithBuildWrappers) project).getBuildWrappersList()) - bw.makeBuildVariables(this,r); + bw.makeBuildVariables(this, r); } for (BuildVariableContributor bvc : BuildVariableContributor.all()) - bvc.buildVariablesFor(this,r); + bvc.buildVariablesFor(this, r); return r; } @@ -1126,22 +1129,22 @@ public String getWhyKeepLog() { // if any of the downstream project is configured with 'keep dependency component', // we need to keep this log OUTER: - for (AbstractProject p : getParent().getDownstreamProjects()) { + for (AbstractProject p : getParent().getDownstreamProjects()) { if (!p.isKeepDependencies()) continue; - AbstractBuild fb = p.getFirstBuild(); - if (fb==null) continue; // no active record + AbstractBuild fb = p.getFirstBuild(); + if (fb == null) continue; // no active record // is there any active build that depends on us? for (int i : getDownstreamRelationship(p).listNumbersReverse()) { // TODO: this is essentially a "find intersection between two sparse sequences" // and we should be able to do much better. - if (i b = p.getBuildByNumber(i); - if (b!=null) + AbstractBuild b = p.getBuildByNumber(i); + if (b != null) return Messages.AbstractBuild_KeptBecause(p.hasPermission(Item.READ) ? b.toString() : "?"); } } @@ -1161,7 +1164,7 @@ public RangeSet getDownstreamRelationship(AbstractProject that) { RangeSet rs = new RangeSet(); FingerprintAction f = getAction(FingerprintAction.class); - if (f==null) return rs; + if (f == null) return rs; // look for fingerprints that point to this build as the source, and merge them all for (Fingerprint e : f.getFingerprints().values()) { @@ -1172,7 +1175,7 @@ public RangeSet getDownstreamRelationship(AbstractProject that) { rs.add(e.getRangeSet(that)); } else { BuildPtr o = e.getOriginal(); - if (o!=null && o.is(this)) + if (o != null && o.is(this)) rs.add(e.getRangeSet(that)); } } @@ -1185,14 +1188,14 @@ public RangeSet getDownstreamRelationship(AbstractProject that) { * the actual build objects, in ascending order. * @since 1.150 */ - public Iterable> getDownstreamBuilds(final AbstractProject that) { + public Iterable> getDownstreamBuilds(final AbstractProject that) { final Iterable nums = getDownstreamRelationship(that).listNumbers(); return new Iterable>() { @Override public Iterator> iterator() { return Iterators.removeNull( - new AdaptedIterator>(nums) { + new AdaptedIterator>(nums) { @Override protected AbstractBuild adapt(Integer item) { return that.getBuildByNumber(item); @@ -1212,7 +1215,7 @@ public Iterable> getDownstreamBuilds(final AbstractProject getUpstreamRelationshipBuild(AbstractProject that) { + public AbstractBuild getUpstreamRelationshipBuild(AbstractProject that) { int n = getUpstreamRelationship(that); - if (n==-1) return null; + if (n == -1) return null; return that.getBuildByNumber(n); } @@ -1257,11 +1260,11 @@ public AbstractBuild getUpstreamRelationshipBuild(AbstractProject that * For each project with fingerprinting enabled, returns the range * of builds (which can be empty if no build uses the artifact from this build or downstream is not {@link AbstractProject#isFingerprintConfigured}.) */ - public Map getDownstreamBuilds() { - Map r = new HashMap<>(); + public Map getDownstreamBuilds() { + Map r = new HashMap<>(); for (AbstractProject p : getParent().getDownstreamProjects()) { if (p.isFingerprintConfigured()) - r.put(p,getDownstreamRelationship(p)); + r.put(p, getDownstreamRelationship(p)); } return r; } @@ -1272,7 +1275,7 @@ public Map getDownstreamBuilds() { * @return empty if there is no {@link FingerprintAction} (even if there is an {@link Cause.UpstreamCause}) * @see #getTransitiveUpstreamBuilds() */ - public Map getUpstreamBuilds() { + public Map getUpstreamBuilds() { return _getUpstreamBuilds(getParent().getUpstreamProjects()); } @@ -1280,16 +1283,16 @@ public Map getUpstreamBuilds() { * Works like {@link #getUpstreamBuilds()} but also includes all the transitive * dependencies as well. */ - public Map getTransitiveUpstreamBuilds() { + public Map getTransitiveUpstreamBuilds() { return _getUpstreamBuilds(getParent().getTransitiveUpstreamProjects()); } private Map _getUpstreamBuilds(Collection projects) { - Map r = new HashMap<>(); + Map r = new HashMap<>(); for (AbstractProject p : projects) { int n = getUpstreamRelationship(p); - if (n>=0) - r.put(p,n); + if (n >= 0) + r.put(p, n); } return r; } @@ -1298,23 +1301,23 @@ private Map _getUpstreamBuilds(Collection getDependencyChanges(AbstractBuild from) { - if (from==null) return Collections.emptyMap(); // make it easy to call this from views + public Map getDependencyChanges(AbstractBuild from) { + if (from == null) return Collections.emptyMap(); // make it easy to call this from views FingerprintAction n = this.getAction(FingerprintAction.class); FingerprintAction o = from.getAction(FingerprintAction.class); - if (n==null || o==null) return Collections.emptyMap(); + if (n == null || o == null) return Collections.emptyMap(); - Map ndep = n.getDependencies(true); - Map odep = o.getDependencies(true); + Map ndep = n.getDependencies(true); + Map odep = o.getDependencies(true); - Map r = new HashMap<>(); + Map r = new HashMap<>(); - for (Map.Entry entry : odep.entrySet()) { + for (Map.Entry entry : odep.entrySet()) { AbstractProject p = entry.getKey(); Integer oldNumber = entry.getValue(); Integer newNumber = ndep.get(p); - if (newNumber!=null && oldNumber.compareTo(newNumber)<0) { - r.put(p,new DependencyChange(p,oldNumber,newNumber)); + if (newNumber != null && oldNumber.compareTo(newNumber) < 0) { + r.put(p, new DependencyChange(p, oldNumber, newNumber)); } } @@ -1344,7 +1347,7 @@ public static final class DependencyChange { public final AbstractBuild to; - public DependencyChange(AbstractProject project, int fromId, int toId) { + public DependencyChange(AbstractProject project, int fromId, int toId) { this.project = project; this.fromId = fromId; this.toId = toId; @@ -1361,11 +1364,11 @@ public DependencyChange(AbstractProject project, int fromId, int toId) { public List getBuilds() { List r = new ArrayList<>(); - AbstractBuild b = project.getNearestBuild(fromId); - if (b!=null && b.getNumber()==fromId) + AbstractBuild b = project.getNearestBuild(fromId); + if (b != null && b.getNumber() == fromId) b = b.getNextBuild(); // fromId exclusive - while (b!=null && b.getNumber()<=toId) { + while (b != null && b.getNumber() <= toId) { r.add(b); b = b.getNextBuild(); } @@ -1385,7 +1388,7 @@ public List getBuilds() { @Deprecated @RequirePOST // #doStop() should be preferred, but better to be safe public void doStop(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { - doStop().generateResponse(req,rsp,this); + doStop().generateResponse(req, rsp, this); } /** @@ -1393,15 +1396,15 @@ public void doStop(StaplerRequest req, StaplerResponse rsp) throws IOException, * * If we use this/executor/stop URL, it causes 404 if the build is already killed, * as {@link #getExecutor()} returns null. - * + * * @since 1.489 */ @RequirePOST public synchronized HttpResponse doStop() throws IOException, ServletException { Executor e = getExecutor(); - if (e==null) + if (e == null) e = getOneOffExecutor(); - if (e!=null) + if (e != null) return e.doStop(); else // nothing is building diff --git a/core/src/main/java/hudson/model/AbstractCIBase.java b/core/src/main/java/hudson/model/AbstractCIBase.java index 13fb0b563580f..cb2332cbb0a32 100644 --- a/core/src/main/java/hudson/model/AbstractCIBase.java +++ b/core/src/main/java/hudson/model/AbstractCIBase.java @@ -86,6 +86,7 @@ protected void resetLabel(Label l) { protected void setViewOwner(View v) { v.owner = this; } + protected void interruptReloadThread() { ViewJob.interruptReloadThread(); } @@ -101,7 +102,7 @@ protected void killComputer(Computer c) { * * @since 2.230 */ - public Set getDisabledAdministrativeMonitors(){ + public Set getDisabledAdministrativeMonitors() { synchronized (this.disabledAdministrativeMonitors) { return new HashSet<>(disabledAdministrativeMonitors); } @@ -131,15 +132,15 @@ public void setDisabledAdministrativeMonitors(Set disabledAdministrative public abstract Queue getQueue(); - protected abstract Map getComputerMap(); + protected abstract Map getComputerMap(); /* ================================================================================================================= * Computer API uses package protection heavily * ============================================================================================================== */ - private void updateComputer(Node n, Map byNameMap, Set used, boolean automaticAgentLaunch) { + private void updateComputer(Node n, Map byNameMap, Set used, boolean automaticAgentLaunch) { Computer c = byNameMap.get(n.getNodeName()); - if (c!=null) { + if (c != null) { try { c.setNode(n); // reuse used.add(c); @@ -157,12 +158,12 @@ private void updateComputer(Node n, Map byNameMap, Set computers = getComputerMap(); + Map computers = getComputerMap(); // we always need Computer for the built-in node as a fallback in case there's no other Computer. - if(n.getNumExecutors()>0 || n==Jenkins.get()) { + if (n.getNumExecutors() > 0 || n == Jenkins.get()) { try { c = n.createComputer(); - } catch(RuntimeException ex) { // Just in case there is a bogus extension + } catch (RuntimeException ex) { // Just in case there is a bogus extension LOGGER.log(Level.WARNING, "Error retrieving computer for node " + n.getNodeName() + ", continuing", ex); } if (c == null) { @@ -194,7 +195,7 @@ private Computer createNewComputerForNode(Node n, boolean automaticAgentLaunch) Queue.withLock(new Runnable() { @Override public void run() { - Map computers = getComputerMap(); + Map computers = getComputerMap(); for (Map.Entry e : computers.entrySet()) { if (e.getValue() == computer) { computers.remove(e.getKey()); @@ -207,7 +208,7 @@ public void run() { } /*package*/ @CheckForNull Computer getComputer(Node n) { - Map computers = getComputerMap(); + Map computers = getComputerMap(); return computers.get(n); } @@ -231,18 +232,18 @@ protected void updateNewComputer(final Node n, boolean automaticAgentLaunch) { * so that we won't upset {@link Executor}s running in it. */ protected void updateComputerList(final boolean automaticAgentLaunch) { - final Map computers = getComputerMap(); + final Map computers = getComputerMap(); final Set old = new HashSet<>(computers.size()); Queue.withLock(new Runnable() { @Override public void run() { - Map byName = new HashMap<>(); + Map byName = new HashMap<>(); for (Computer c : computers.values()) { old.add(c); Node node = c.getNode(); if (node == null) continue; // this computer is gone - byName.put(node.getNodeName(),c); + byName.put(node.getNodeName(), c); } Set used = new HashSet<>(old.size()); diff --git a/core/src/main/java/hudson/model/AbstractDescribableImpl.java b/core/src/main/java/hudson/model/AbstractDescribableImpl.java index b1ac6dd8477f2..2e339875b940d 100644 --- a/core/src/main/java/hudson/model/AbstractDescribableImpl.java +++ b/core/src/main/java/hudson/model/AbstractDescribableImpl.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.Extension; diff --git a/core/src/main/java/hudson/model/AbstractItem.java b/core/src/main/java/hudson/model/AbstractItem.java index 08f77310104ae..948daf12b40ab 100644 --- a/core/src/main/java/hudson/model/AbstractItem.java +++ b/core/src/main/java/hudson/model/AbstractItem.java @@ -1,19 +1,19 @@ /* * The MIT License - * + * * Copyright (c) 2004-2011, Sun Microsystems, Inc., Kohsuke Kawaguchi, * Daniel Dyer, Tom Huybrechts, Yahoo!, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static hudson.model.queue.Executables.getParentOf; @@ -127,7 +128,7 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet protected volatile String description; private transient ItemGroup parent; - + protected String displayName; protected AbstractItem(ItemGroup parent, String name) { @@ -136,7 +137,7 @@ protected AbstractItem(ItemGroup parent, String name) { } @Override - @Exported(visibility=999) + @Exported(visibility = 999) public String getName() { return name; } @@ -165,13 +166,13 @@ public String getTaskNoun() { @Override @Exported public String getDisplayName() { - if(null!=displayName) { + if (null != displayName) { return displayName; } // if the displayName is not set, then return the name as we use to do return getName(); } - + /** * This is intended to be used by the Job configuration pages where * we want to return null if the display name is not set. @@ -182,21 +183,21 @@ public String getDisplayName() { public String getDisplayNameOrNull() { return displayName; } - + /** - * This method exists so that the Job configuration pages can use + * This method exists so that the Job configuration pages can use * getDisplayNameOrNull so that nothing is shown in the display name text * box if the display name is not set. */ public void setDisplayNameOrNull(String displayName) throws IOException { setDisplayName(displayName); } - + public void setDisplayName(String displayName) throws IOException { this.displayName = Util.fixEmptyAndTrim(displayName); save(); } - + @Override public File getRootDir() { return getParent().getRootDirFor(this); @@ -205,7 +206,7 @@ public File getRootDir() { /** * This bridge method is to maintain binary compatibility with {@link TopLevelItem#getParent()}. */ - @WithBridgeMethods(value=Jenkins.class,castRequired=true) + @WithBridgeMethods(value = Jenkins.class, castRequired = true) @Override public @NonNull ItemGroup getParent() { if (parent == null) { throw new IllegalStateException("no parent set on " + getClass().getName() + "[" + name + "]"); @@ -284,7 +285,7 @@ public HttpResponse doConfirmRename(@QueryParameter String newName) throws IOExc // TODO: Create an Item.RENAME permission to use here, see JENKINS-18649. if (!hasPermission(Item.CONFIGURE)) { if (parent instanceof AccessControlled) { - ((AccessControlled)parent).checkPermission(Item.CREATE); + ((AccessControlled) parent).checkPermission(Item.CREATE); } checkPermission(Item.DELETE); } @@ -321,17 +322,17 @@ private void checkIfNameIsUsed(@NonNull String newName) throws Failure { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "Unable to rename the job {0}: name {1} is already in use. " + "User {2} has no {3} permission for existing job with the same name", - new Object[] {this.getFullName(), newName, ctx.getPreviousContext2().getAuthentication().getName(), Item.DISCOVER.name} ); + new Object[] {this.getFullName(), newName, ctx.getPreviousContext2().getAuthentication().getName(), Item.DISCOVER.name}); } // Don't explicitly mention that there is another item with the same name. throw new Failure(Messages.Jenkins_NotAllowedName(newName)); } } - } catch(AccessDeniedException ex) { + } catch (AccessDeniedException ex) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "Unable to rename the job {0}: name {1} is already in use. " + "User {2} has {3} permission, but no {4} for existing job with the same name", - new Object[] {this.getFullName(), newName, User.current(), Item.DISCOVER.name, Item.READ.name} ); + new Object[] {this.getFullName(), newName, User.current(), Item.DISCOVER.name, Item.READ.name}); } throw new Failure(Messages.AbstractItem_NewNameInUse(newName)); } @@ -356,6 +357,7 @@ protected void checkRename(@NonNull String newName) throws Failure { * Not all the Items need to support this operation, but if you decide to do so, * you can use this method. */ + @SuppressFBWarnings(value = "SWL_SLEEP_WITH_LOCK_HELD", justification = "no big deal") protected void renameTo(final String newName) throws IOException { if (!isNameEditable()) { @@ -388,7 +390,7 @@ protected void renameTo(final String newName) throws IOException { boolean success = false; - try {// rename data files + try { // rename data files boolean interrupted = false; boolean renamed = false; @@ -479,18 +481,18 @@ public void movedTo(DirectlyModifiableTopLevelItemGroup destination, AbstractIte @Exported public final String getFullName() { String n = getParent().getFullName(); - if(n.length()==0) return getName(); - else return n+'/'+getName(); + if (n.length() == 0) return getName(); + else return n + '/' + getName(); } @Override @Exported public final String getFullDisplayName() { String n = getParent().getFullDisplayName(); - if(n.length()==0) return getDisplayName(); - else return n+" » "+getDisplayName(); + if (n.length() == 0) return getDisplayName(); + else return n + " » " + getDisplayName(); } - + /** * Gets the display name of the current item relative to the given group. * @@ -502,7 +504,7 @@ public final String getFullDisplayName() { public String getRelativeDisplayNameFrom(ItemGroup p) { return Functions.getRelativeDisplayNameFrom(this, p); } - + /** * This method only exists to disambiguate {@link #getRelativeNameFrom(ItemGroup)} and {@link #getRelativeNameFrom(Item)} * @since 1.512 @@ -528,9 +530,6 @@ public void onLoad(ItemGroup parent, String name) throws IOExcep * then it will be loaded, then this method will be invoked * to perform any implementation-specific work. * - *

      - * - * * @param src * Item from which it's copied from. The same type as {@code this}. Never null. */ @@ -545,11 +544,11 @@ public final String getUrl() { String shortUrl = getShortUrl(); String uri = req == null ? null : req.getRequestURI(); if (req != null) { - String seed = Functions.getNearestAncestorUrl(req,this); + String seed = Functions.getNearestAncestorUrl(req, this); LOGGER.log(Level.FINER, "seed={0} for {1} from {2}", new Object[] {seed, this, uri}); - if(seed!=null) { + if (seed != null) { // trim off the context path portion and leading '/', but add trailing '/' - return seed.substring(req.getContextPath().length()+1)+'/'; + return seed.substring(req.getContextPath().length() + 1) + '/'; } List ancestors = req.getAncestors(); if (!ancestors.isEmpty()) { @@ -607,7 +606,7 @@ public Icon getSearchItemIcon() { } @Override - @Exported(visibility=999,name="url") + @Exported(visibility = 999, name = "url") public final String getAbsoluteUrl() { return Item.super.getAbsoluteUrl(); } @@ -632,7 +631,7 @@ public ACL getACL() { */ @Override public synchronized void save() throws IOException { - if(BulkChange.contains(this)) return; + if (BulkChange.contains(this)) return; getConfigFile().write(this); SaveableListener.fireOnChange(this, getConfigFile()); } @@ -644,11 +643,14 @@ public final XmlFile getConfigFile() { protected Object writeReplace() { return XmlFile.replaceIfNotAtTopLevel(this, () -> new Replacer(this)); } + private static class Replacer { private final String fullName; + Replacer(AbstractItem i) { fullName = i.getFullName(); } + private Object readResolve() { Jenkins j = Jenkins.getInstanceOrNull(); if (j == null) { @@ -663,7 +665,7 @@ private Object readResolve() { * Accepts the new description. */ @RequirePOST - public synchronized void doSubmitDescription( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public synchronized void doSubmitDescription(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { checkPermission(CONFIGURE); setDescription(req.getParameter("description")); @@ -677,7 +679,7 @@ public synchronized void doSubmitDescription( StaplerRequest req, StaplerRespons * which should now be unused by core but is left in case plugins are still using it. */ @RequirePOST - public void doDoDelete( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, InterruptedException { + public void doDoDelete(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, InterruptedException { delete(); if (req == null || rsp == null) { // CLI return; @@ -699,7 +701,7 @@ public void doDoDelete( StaplerRequest req, StaplerResponse rsp ) throws IOExcep } @Override - public void delete( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public void delete(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { try { delete(); rsp.setStatus(204); @@ -757,8 +759,8 @@ public void delete() throws IOException, InterruptedException { final WorkUnit workUnit = e.getCurrentWorkUnit(); final Executable executable = workUnit != null ? workUnit.getExecutable() : null; final SubTask subtask = executable != null ? getParentOf(executable) : null; - - if (subtask != null) { + + if (subtask != null) { Item item = Tasks.getItemOf(subtask); while (item != null) { if (item == this) { @@ -842,7 +844,7 @@ public void doConfigDotXml(StaplerRequest req, StaplerResponse rsp) } if (req.getMethod().equals("POST")) { // submission - updateByXml((Source)new StreamSource(req.getReader())); + updateByXml((Source) new StreamSource(req.getReader())); return; } @@ -856,6 +858,7 @@ public void doConfigDotXml(StaplerRequest req, StaplerResponse rsp) * The user must have at least {@link #EXTENDED_READ}. * If he lacks {@link #CONFIGURE}, then any {@link Secret}s detected will be masked out. */ + @Restricted(NoExternalUse.class) public void writeConfigDotXml(OutputStream os) throws IOException { checkPermission(EXTENDED_READ); @@ -883,7 +886,7 @@ public void writeConfigDotXml(OutputStream os) throws IOException { */ @Deprecated public void updateByXml(StreamSource source) throws IOException { - updateByXml((Source)source); + updateByXml((Source) source); } /** @@ -907,13 +910,13 @@ public void updateByXml(Source source) throws IOException { // try to reflect the changes by reloading Object o = new XmlFile(Items.XSTREAM, out.getTemporaryFile()).unmarshalNullingOut(this); - if (o!=this) { + if (o != this) { // ensure that we've got the same job type. extending this code to support updating // to different job type requires destroying & creating a new job type - throw new IOException("Expecting "+this.getClass()+" but got "+o.getClass()+" instead"); + throw new IOException("Expecting " + this.getClass() + " but got " + o.getClass() + " instead"); } - Items.whileUpdatingByXml(new NotReallyRoleSensitiveCallable() { + Items.whileUpdatingByXml(new NotReallyRoleSensitiveCallable() { @Override public Void call() throws IOException { onLoad(getParent(), getRootDir().getName()); return null; @@ -994,10 +997,10 @@ public Object getTarget() { */ @CLIResolver public static AbstractItem resolveForCLI( - @Argument(required=true,metaVar="NAME",usage="Item name") String name) throws CmdLineException { + @Argument(required = true, metaVar = "NAME", usage = "Item name") String name) throws CmdLineException { // TODO can this (and its pseudo-override in AbstractProject) share code with GenericItemOptionHandler, used for explicit CLICommand’s rather than CLIMethod’s? AbstractItem item = Jenkins.get().getItemByFullName(name, AbstractItem.class); - if (item==null) { + if (item == null) { AbstractItem project = Items.findNearest(AbstractItem.class, name, Jenkins.get()); throw new CmdLineException(null, project == null ? Messages.AbstractItem_NoSuchJobExistsWithoutSuggestion(name) : Messages.AbstractItem_NoSuchJobExists(name, project.getFullName())); diff --git a/core/src/main/java/hudson/model/AbstractModelObject.java b/core/src/main/java/hudson/model/AbstractModelObject.java index 0d1d6982db800..f6c7104f8e428 100644 --- a/core/src/main/java/hudson/model/AbstractModelObject.java +++ b/core/src/main/java/hudson/model/AbstractModelObject.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.search.Search; @@ -37,7 +38,7 @@ /** * {@link ModelObject} with some convenience methods. - * + * * @author Kohsuke Kawaguchi */ public abstract class AbstractModelObject implements SearchableModelObject { @@ -46,16 +47,16 @@ public abstract class AbstractModelObject implements SearchableModelObject { */ protected final void sendError(Exception e, StaplerRequest req, StaplerResponse rsp) throws ServletException, IOException { req.setAttribute("exception", e); - sendError(e.getMessage(),req,rsp); + sendError(e.getMessage(), req, rsp); } protected final void sendError(Exception e) throws ServletException, IOException { - sendError(e,Stapler.getCurrentRequest(),Stapler.getCurrentResponse()); + sendError(e, Stapler.getCurrentRequest(), Stapler.getCurrentResponse()); } protected final void sendError(String message, StaplerRequest req, StaplerResponse rsp) throws ServletException, IOException { - req.setAttribute("message",message); - rsp.forward(this,"error",req); + req.setAttribute("message", message); + rsp.forward(this, "error", req); } /** @@ -63,29 +64,29 @@ protected final void sendError(String message, StaplerRequest req, StaplerRespon * If true, the message is put in a PRE tag. */ protected final void sendError(String message, StaplerRequest req, StaplerResponse rsp, boolean pre) throws ServletException, IOException { - req.setAttribute("message",message); - if(pre) - req.setAttribute("pre",true); - rsp.forward(this,"error",req); + req.setAttribute("message", message); + if (pre) + req.setAttribute("pre", true); + rsp.forward(this, "error", req); } protected final void sendError(String message) throws ServletException, IOException { - sendError(message,Stapler.getCurrentRequest(),Stapler.getCurrentResponse()); + sendError(message, Stapler.getCurrentRequest(), Stapler.getCurrentResponse()); } /** * Convenience method to verify that the current request is a POST request. - * - * @deprecated + * + * @deprecated * Use {@link RequirePOST} on your method. */ @Deprecated protected final void requirePOST() throws ServletException { StaplerRequest req = Stapler.getCurrentRequest(); - if (req==null) return; // invoked outside the context of servlet + if (req == null) return; // invoked outside the context of servlet String method = req.getMethod(); - if(!method.equalsIgnoreCase("POST")) - throw new ServletException("Must be POST, Can't be "+method); + if (!method.equalsIgnoreCase("POST")) + throw new ServletException("Must be POST, Can't be " + method); } /** @@ -104,7 +105,7 @@ public final SearchIndex getSearchIndex() { public Search getSearch() { for (SearchFactory sf : SearchFactory.all()) { Search s = sf.createFor(this); - if (s!=null) + if (s != null) return s; } return new Search(); diff --git a/core/src/main/java/hudson/model/AbstractProject.java b/core/src/main/java/hudson/model/AbstractProject.java index 48666d0bad248..9dfaf72e21d75 100644 --- a/core/src/main/java/hudson/model/AbstractProject.java +++ b/core/src/main/java/hudson/model/AbstractProject.java @@ -25,6 +25,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static hudson.scm.PollingResult.BUILD_NOW; @@ -135,7 +136,7 @@ * @see AbstractBuild */ @SuppressWarnings("rawtypes") -public abstract class AbstractProject

      ,R extends AbstractBuild> extends Job implements BuildableItem, LazyBuildMixIn.LazyLoadingJob, ParameterizedJobMixIn.ParameterizedJob { +public abstract class AbstractProject

      , R extends AbstractBuild> extends Job implements BuildableItem, LazyBuildMixIn.LazyLoadingJob, ParameterizedJobMixIn.ParameterizedJob { /** * {@link SCM} associated with the project. @@ -154,7 +155,7 @@ public abstract class AbstractProject

      ,R extends A */ private transient volatile SCMRevisionState pollingBaseline = null; - private transient LazyBuildMixIn buildMixIn; + private transient LazyBuildMixIn buildMixIn; /** * All the builds keyed by their build number. @@ -230,9 +231,9 @@ public abstract class AbstractProject

      ,R extends A /** * List of all {@link Trigger}s for this project. */ - protected volatile DescribableList,TriggerDescriptor> triggers = new DescribableList<>(this); - private static final AtomicReferenceFieldUpdater triggersUpdater - = AtomicReferenceFieldUpdater.newUpdater(AbstractProject.class,DescribableList.class,"triggers"); + protected volatile DescribableList, TriggerDescriptor> triggers = new DescribableList<>(this); + private static final AtomicReferenceFieldUpdater triggersUpdater + = AtomicReferenceFieldUpdater.newUpdater(AbstractProject.class, DescribableList.class, "triggers"); /** * {@link Action}s contributed from subsidiary objects associated with @@ -254,7 +255,7 @@ public abstract class AbstractProject

      ,R extends A private String customWorkspace; protected AbstractProject(ItemGroup parent, String name) { - super(parent,name); + super(parent, name); buildMixIn = createBuildMixIn(); builds = buildMixIn.getRunMap(); @@ -266,19 +267,20 @@ protected AbstractProject(ItemGroup parent, String name) { } } - private LazyBuildMixIn createBuildMixIn() { - return new LazyBuildMixIn() { + private LazyBuildMixIn createBuildMixIn() { + return new LazyBuildMixIn() { @SuppressWarnings("unchecked") // untypable @Override protected P asJob() { return (P) AbstractProject.this; } + @Override protected Class getBuildClass() { return AbstractProject.this.getBuildClass(); } }; } - @Override public LazyBuildMixIn getLazyBuildMixIn() { + @Override public LazyBuildMixIn getLazyBuildMixIn() { return buildMixIn; } @@ -313,18 +315,18 @@ public void onLoad(ItemGroup parent, String name) throws IOExcep LOGGER.log(Level.WARNING, "could not start trigger while loading project '" + getFullName() + "'", e); } } - if(scm==null) + if (scm == null) scm = new NullSCM(); // perhaps it was pointing to a plugin that no longer exists. - if(transientActions==null) + if (transientActions == null) transientActions = new Vector<>(); // happens when loaded from disk updateTransientActions(); } @WithBridgeMethods(List.class) - protected DescribableList,TriggerDescriptor> triggers() { + protected DescribableList, TriggerDescriptor> triggers() { if (triggers == null) { - triggersUpdater.compareAndSet(this,null,new DescribableList,TriggerDescriptor>(this)); + triggersUpdater.compareAndSet(this, null, new DescribableList, TriggerDescriptor>(this)); } return triggers; } @@ -351,7 +353,7 @@ protected void performDelete() throws IOException, InterruptedException { // prevent a new build while a delete operation is in progress makeDisabled(true); FilePath ws = getWorkspace(); - if(ws!=null) { + if (ws != null) { Node on = getLastBuiltOn(); getScm().processWorkspaceBeforeDeletion(this, ws, on); } @@ -379,10 +381,10 @@ public void setConcurrentBuild(boolean b) throws IOException { */ @Override public @CheckForNull Label getAssignedLabel() { - if(canRoam) + if (canRoam) return null; - if(assignedNode==null) + if (assignedNode == null) return Jenkins.get().getSelfLabel(); return Jenkins.get().getLabel(assignedNode); } @@ -405,9 +407,9 @@ public Set

      * If just a file name (like "abc.gif") is returned, it will be * interpreted as a file name inside {@code /images/24x24}. * This is useful for using one of the stock images. *

      * If an absolute file name that starts from '/' is returned (like - * "/plugin/foo/abc.gif'), then it will be interpreted as a path + * "/plugin/foo/abc.gif"), then it will be interpreted as a path * from the context root of Jenkins. This is useful to pick up * image files from a plugin. *

      @@ -93,6 +97,7 @@ public interface Action extends ModelObject { * but this can be used for actions that only contribute {@code floatBox.jelly} * and no task list item. The other case where this is useful is * to avoid showing links that require a privilege when the user is anonymous. + * @see Jenkins Symbols * @see Functions#isAnonymous() * @see Functions#getIconFilePath(Action) */ diff --git a/core/src/main/java/hudson/model/Actionable.java b/core/src/main/java/hudson/model/Actionable.java index ff1456c9c7414..6fcb173fc6ad5 100644 --- a/core/src/main/java/hudson/model/Actionable.java +++ b/core/src/main/java/hudson/model/Actionable.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Stephen Connolly - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.NonNull; @@ -90,7 +91,7 @@ public List getActions() { * @return an unmodifiable, possible empty list * @since 1.548 */ - @Exported(name="actions") + @Exported(name = "actions") @NonNull public final List getAllActions() { List _actions = getActions(); @@ -147,7 +148,7 @@ public List getActions(Class type) { */ @SuppressWarnings("ConstantConditions") public void addAction(@NonNull Action a) { - if(a==null) { + if (a == null) { throw new IllegalArgumentException("Action must be non-null"); } getActions().add(a); @@ -306,7 +307,7 @@ public boolean replaceActions(@NonNull Class clazz, @NonNull A /** @deprecated No clear purpose, since subclasses may have overridden {@link #getActions}, and does not consider {@link TransientActionFactory}. */ @Deprecated public Action getAction(int index) { - if(actions==null) return null; + if (actions == null) return null; return actions.get(index); } @@ -336,19 +337,19 @@ public T getAction(Class type) { public Object getDynamic(String token, StaplerRequest req, StaplerResponse rsp) { for (Action a : getAllActions()) { - if(a==null) + if (a == null) continue; // be defensive String urlName = a.getUrlName(); - if(urlName==null) + if (urlName == null) continue; - if(urlName.equals(token)) + if (urlName.equals(token)) return a; } return null; } @Override public ContextMenu doContextMenu(StaplerRequest request, StaplerResponse response) throws Exception { - return new ContextMenu().from(this,request,response); + return new ContextMenu().from(this, request, response); } private static final Logger LOGGER = Logger.getLogger(Actionable.class.getName()); diff --git a/core/src/main/java/hudson/model/AdministrativeMonitor.java b/core/src/main/java/hudson/model/AdministrativeMonitor.java index 0f163ac5b6ed3..3c70207ff892e 100644 --- a/core/src/main/java/hudson/model/AdministrativeMonitor.java +++ b/core/src/main/java/hudson/model/AdministrativeMonitor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.Extension; @@ -108,7 +109,7 @@ protected AdministrativeMonitor() { * Returns the URL of this monitor, relative to the context path, like "administrativeMonitor/foobar". */ public String getUrl() { - return "administrativeMonitor/"+id; + return "administrativeMonitor/" + id; } @Override @@ -175,7 +176,7 @@ public boolean isSecurity() { public void doDisable(StaplerRequest req, StaplerResponse rsp) throws IOException { Jenkins.get().checkPermission(Jenkins.ADMINISTER); disable(true); - rsp.sendRedirect2(req.getContextPath()+"/manage"); + rsp.sendRedirect2(req.getContextPath() + "/manage"); } /** diff --git a/core/src/main/java/hudson/model/AllView.java b/core/src/main/java/hudson/model/AllView.java index cd154206a422e..f92773678e039 100644 --- a/core/src/main/java/hudson/model/AllView.java +++ b/core/src/main/java/hudson/model/AllView.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.NonNull; @@ -30,11 +31,11 @@ import java.util.Collection; import java.util.List; import java.util.Locale; +import java.util.Objects; import java.util.logging.Level; import java.util.logging.Logger; import javax.servlet.ServletException; import jenkins.util.SystemProperties; -import org.apache.commons.lang.StringUtils; import org.jenkinsci.Symbol; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.StaplerRequest; @@ -72,7 +73,7 @@ public AllView(String name, ViewGroup owner) { this(name); this.owner = owner; } - + @Override public boolean isEditable() { return false; @@ -94,13 +95,13 @@ public Item doCreateItem(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { ItemGroup ig = getOwner().getItemGroup(); if (ig instanceof ModifiableItemGroup) - return ((ModifiableItemGroup)ig).doCreateItem(req, rsp); + return ((ModifiableItemGroup) ig).doCreateItem(req, rsp); return null; } @Override public Collection getItems() { - return (Collection)getOwner().getItemGroup().getItems(); + return (Collection) getOwner().getItemGroup().getItems(); } @Override @@ -138,14 +139,14 @@ public static String migrateLegacyPrimaryAllViewLocalizedName(@NonNull List * This class is similar to {@link PeriodicWork}. The main difference is in re-evaluating delay interval every time. * See {@link PeriodicWork} for details. Analog of {@link AsyncPeriodicWork} is {@link AsyncAperiodicWork}. - * + * * @author vjuranek * @since 1.410 */ -@SuppressFBWarnings(value="PREDICTABLE_RANDOM", justification = "The random is just used for an initial delay.") +@SuppressFBWarnings(value = "PREDICTABLE_RANDOM", justification = "The random is just used for an initial delay.") public abstract class AperiodicWork extends SafeTimerTask implements ExtensionPoint { - - protected final Logger logger = Logger.getLogger(getClass().getName()); - + + protected final Logger logger = Logger.getLogger(getClass().getName()); + /** * Gets the number of milliseconds between successive executions. * *

      - * Jenkins calls this method every time the timer task is scheduled. + * Jenkins calls this method every time the timer task is scheduled. * */ public abstract long getRecurrencePeriod(); /** - * Gets new instance of task to be executed. Method should return new instance each time, as there no check, if previously + * Gets new instance of task to be executed. Method should return new instance each time, as there no check, if previously * scheduled task already finished. Returning same instance could lead to throwing {@link IllegalStateException} (especially * in case of {@link AsyncAperiodicWork}) and therefore scheduling of next tasks will be broken. - * + * * @return AperiodicWork - timer task instance to be executed */ public abstract AperiodicWork getNewInstance(); - + /** * Gets the number of milliseconds till the first execution. * @@ -81,18 +82,18 @@ public abstract class AperiodicWork extends SafeTimerTask implements ExtensionPo public long getInitialDelay() { long l = RANDOM.nextLong(); // Math.abs(Long.MIN_VALUE)==Long.MIN_VALUE! - if (l==Long.MIN_VALUE) + if (l == Long.MIN_VALUE) l++; - return Math.abs(l)%getRecurrencePeriod(); + return Math.abs(l) % getRecurrencePeriod(); } @Override - public final void doRun() throws Exception{ - doAperiodicRun(); + public final void doRun() throws Exception { + doAperiodicRun(); Timer.get().schedule(getNewInstance(), getRecurrencePeriod(), TimeUnit.MILLISECONDS); } - @Initializer(after= JOB_CONFIG_ADAPTED) + @Initializer(after = JOB_CONFIG_ADAPTED) public static void init() { // start all AperidocWorks ExtensionList extensionList = all(); @@ -107,7 +108,7 @@ private static void scheduleAperiodWork(AperiodicWork ap) { } protected abstract void doAperiodicRun(); - + /** * Returns all the registered {@link AperiodicWork}s. */ diff --git a/core/src/main/java/hudson/model/Api.java b/core/src/main/java/hudson/model/Api.java index bb2658d7cc9e4..11db76c3581d4 100644 --- a/core/src/main/java/hudson/model/Api.java +++ b/core/src/main/java/hudson/model/Api.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.ExtensionList; @@ -104,9 +105,9 @@ public void doXml(StaplerRequest req, StaplerResponse rsp, String[] excludes = req.getParameterValues("exclude"); - if(xpath==null && excludes==null) { + if (xpath == null && excludes == null) { // serve the whole thing - rsp.serveExposedBean(req,bean,Flavor.XML); + rsp.serveExposedBean(req, bean, Flavor.XML); return; } @@ -115,7 +116,7 @@ public void doXml(StaplerRequest req, StaplerResponse rsp, // first write to String Model p = MODEL_BUILDER.get(bean.getClass()); TreePruner pruner = tree != null ? new NamedPathPruner(tree) : new ByDepth(1 - depth); - p.writeTo(bean,pruner,Flavor.XML.createDataWriter(bean,sw)); + p.writeTo(bean, pruner, Flavor.XML.createDataWriter(bean, sw)); // apply XPath FilteredFunctionContext functionContext = new FilteredFunctionContext(); @@ -123,33 +124,33 @@ public void doXml(StaplerRequest req, StaplerResponse rsp, try { Document dom = new SAXReader().read(new StringReader(sw.toString())); // apply exclusions - if (excludes!=null) { + if (excludes != null) { for (String exclude : excludes) { XPath xExclude = dom.createXPath(exclude); xExclude.setFunctionContext(functionContext); List list = xExclude.selectNodes(dom); for (org.dom4j.Node n : list) { Element parent = n.getParent(); - if(parent!=null) + if (parent != null) parent.remove(n); } } } - - if(xpath==null) { - result = dom; + + if (xpath == null) { + result = dom; } else { XPath comp = dom.createXPath(xpath); comp.setFunctionContext(functionContext); List list = comp.selectNodes(dom); - if (wrapper!=null) { + if (wrapper != null) { // check if the wrapper is a valid entity name // First position: letter or underscore // Other positions: \w (letter, number, underscore), dash or dot String validNameRE = "^[a-zA-Z_][\\w-\\.]*$"; - if(!wrapper.matches(validNameRE)) { + if (!wrapper.matches(validNameRE)) { rsp.setStatus(HttpServletResponse.SC_BAD_REQUEST); rsp.getWriter().print(Messages.Api_WrapperParamInvalid()); return; @@ -160,7 +161,7 @@ public void doXml(StaplerRequest req, StaplerResponse rsp, if (o instanceof String) { root.addText(o.toString()); } else { - root.add(((org.dom4j.Node)o).detach()); + root.add(((org.dom4j.Node) o).detach()); } } result = root; @@ -170,7 +171,7 @@ public void doXml(StaplerRequest req, StaplerResponse rsp, return; } else if (list.size() > 1) { rsp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - rsp.getWriter().print(Messages.Api_MultipleMatch(xpath,list.size())); + rsp.getWriter().print(Messages.Api_MultipleMatch(xpath, list.size())); return; } else { result = list.get(0); @@ -178,8 +179,8 @@ public void doXml(StaplerRequest req, StaplerResponse rsp, } } catch (DocumentException e) { - LOGGER.log(Level.FINER, "Failed to do XPath/wrapper handling. XML is as follows:"+sw, e); - throw new IOException("Failed to do XPath/wrapper handling. Turn on FINER logging to view XML.",e); + LOGGER.log(Level.FINER, "Failed to do XPath/wrapper handling. XML is as follows:" + sw, e); + throw new IOException("Failed to do XPath/wrapper handling. Turn on FINER logging to view XML.", e); } @@ -226,7 +227,7 @@ public void doSchema(StaplerRequest req, StaplerResponse rsp) throws IOException public void doJson(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { if (req.getParameter("jsonp") == null || permit(req)) { setHeaders(rsp); - rsp.serveExposedBean(req,bean, req.getParameter("jsonp") == null ? Flavor.JSON : Flavor.JSONP); + rsp.serveExposedBean(req, bean, req.getParameter("jsonp") == null ? Flavor.JSON : Flavor.JSONP); } else { rsp.sendError(HttpURLConnection.HTTP_FORBIDDEN, "jsonp forbidden; implement jenkins.security.SecureRequester"); } @@ -237,7 +238,7 @@ public void doJson(StaplerRequest req, StaplerResponse rsp) throws IOException, */ public void doPython(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { setHeaders(rsp); - rsp.serveExposedBean(req,bean, Flavor.PYTHON); + rsp.serveExposedBean(req, bean, Flavor.PYTHON); } private boolean permit(StaplerRequest req) { diff --git a/core/src/main/java/hudson/model/AsyncAperiodicWork.java b/core/src/main/java/hudson/model/AsyncAperiodicWork.java index b5ad5b07d44f4..294b471f990fe 100644 --- a/core/src/main/java/hudson/model/AsyncAperiodicWork.java +++ b/core/src/main/java/hudson/model/AsyncAperiodicWork.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.Functions; @@ -37,8 +38,8 @@ /** * {@link AperiodicWork} that takes a long time to run. Similar to {@link AsyncPeriodicWork}, see {@link AsyncPeriodicWork} for - * details and {@link AperiodicWork} for differences between {@link AperiodicWork} and {@link PeriodicWork}. - * + * details and {@link AperiodicWork} for differences between {@link AperiodicWork} and {@link PeriodicWork}. + * * @author vjuranek * @since 1.410 */ @@ -94,8 +95,8 @@ public abstract class AsyncAperiodicWork extends AperiodicWork { protected AsyncAperiodicWork(String name) { this.name = name; this.logRotateMillis = TimeUnit.MINUTES.toMillis( - SystemProperties.getLong(getClass().getName()+".logRotateMinutes", LOG_ROTATE_MINUTES)); - this.logRotateSize = SystemProperties.getLong(getClass().getName() +".logRotateSize", LOG_ROTATE_SIZE); + SystemProperties.getLong(getClass().getName() + ".logRotateMinutes", LOG_ROTATE_MINUTES)); + this.logRotateSize = SystemProperties.getLong(getClass().getName() + ".logRotateSize", LOG_ROTATE_SIZE); } /** @@ -104,7 +105,7 @@ protected AsyncAperiodicWork(String name) { @Override public final void doAperiodicRun() { try { - if(thread!=null && thread.isAlive()) { + if (thread != null && thread.isAlive()) { logger.log(getSlowLoggingLevel(), "{0} thread is still running. Execution aborted.", name); return; } @@ -127,10 +128,10 @@ public final void doAperiodicRun() { logger.log(getNormalLoggingLevel(), "Finished {0}. {1,number} ms", new Object[]{name, stopTime - startTime}); - },name+" thread"); - thread.start(); + }, name + " thread"); + thread.start(); } catch (Throwable t) { - logger.log(Level.SEVERE, name+" thread failed with error", t); + logger.log(Level.SEVERE, name + " thread failed with error", t); } } diff --git a/core/src/main/java/hudson/model/AsyncPeriodicWork.java b/core/src/main/java/hudson/model/AsyncPeriodicWork.java index 1a6ce7cadaf3b..3b75984454f25 100644 --- a/core/src/main/java/hudson/model/AsyncPeriodicWork.java +++ b/core/src/main/java/hudson/model/AsyncPeriodicWork.java @@ -87,7 +87,7 @@ protected AsyncPeriodicWork(String name) { @SuppressWarnings("deprecation") // in this case we really want to use PeriodicWork.logger since it reports the impl class public final void doRun() { try { - if(thread!=null && thread.isAlive()) { + if (thread != null && thread.isAlive()) { logger.log(this.getSlowLoggingLevel(), "{0} thread is still running. Execution aborted.", name); return; } @@ -112,7 +112,7 @@ public final void doRun() { logger.log(getNormalLoggingLevel(), "Finished {0}. {1,number} ms", new Object[]{name, stopTime - startTime}); - },name+" thread"); + }, name + " thread"); thread.start(); } catch (Throwable t) { LogRecord lr = new LogRecord(this.getErrorLoggingLevel(), "{0} thread failed with error"); @@ -214,11 +214,11 @@ protected StreamTaskListener createListener() { protected File getLogFile() { return new File(getLogsRoot(), "/tasks/" + name + ".log"); } - + /** * Returns the logging level at which normal messages are displayed. - * - * @return + * + * @return * The logging level as @Level. * * @since 1.551 @@ -226,7 +226,7 @@ protected File getLogFile() { protected Level getNormalLoggingLevel() { return Level.INFO; } - + /** * Returns the logging level at which previous task still executing messages is displayed. * @@ -241,8 +241,8 @@ protected Level getSlowLoggingLevel() { /** * Returns the logging level at which error messages are displayed. - * - * @return + * + * @return * The logging level as @Level. * * @since 1.551 @@ -250,7 +250,7 @@ protected Level getSlowLoggingLevel() { protected Level getErrorLoggingLevel() { return Level.SEVERE; } - + /** * Executes the task. * diff --git a/core/src/main/java/hudson/model/AutoCompletionCandidates.java b/core/src/main/java/hudson/model/AutoCompletionCandidates.java index 824915477b97b..dbc3f6ea1c186 100644 --- a/core/src/main/java/hudson/model/AutoCompletionCandidates.java +++ b/core/src/main/java/hudson/model/AutoCompletionCandidates.java @@ -25,6 +25,7 @@ package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.search.Search; import hudson.search.UserSearchProperty; import java.io.IOException; @@ -73,7 +74,7 @@ public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object o) for (String value : values) { r.suggestions.add(new hudson.search.Search.Item(value)); } - rsp.serveExposedBean(req,r, Flavor.JSON); + rsp.serveExposedBean(req, r, Flavor.JSON); } /** @@ -91,7 +92,7 @@ public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object o) * @since 1.489 */ public static AutoCompletionCandidates ofJobNames(final Class type, final String value, @CheckForNull Item self, ItemGroup container) { - if (self==container) + if (self == container) container = self.getParent(); return ofJobNames(type, value, container); } @@ -108,6 +109,7 @@ public static AutoCompletionCandidates ofJobNames(final Class AutoCompletionCandidates ofJobNames(final Class type, final String value, ItemGroup container) { final AutoCompletionCandidates candidates = new AutoCompletionCandidates(); class Visitor extends ItemVisitor { @@ -120,7 +122,7 @@ class Visitor extends ItemVisitor { @Override public void onItem(Item i) { String itemName = contextualNameOf(i); - + //Check user's setting on whether to do case sensitive comparison, configured in user -> configure //This is the same setting that is used by the global search field, should be consistent throughout //the whole application. @@ -129,7 +131,7 @@ public void onItem(Item i) { if ((startsWithImpl(itemName, value, caseInsensitive) || startsWithImpl(value, itemName, caseInsensitive)) // 'foobar' is a valid candidate if the current value is 'foo'. // Also, we need to visit 'foo' if the current value is 'foo/bar' - && (value.length()> itemName.length() || !itemName.substring(value.length()).contains("/")) + && (value.length() > itemName.length() || !itemName.substring(value.length()).contains("/")) // but 'foobar/zot' isn't if the current value is 'foo' // we'll first show 'foobar' and then wait for the user to type '/' to show the rest && i.hasPermission(Item.READ) @@ -147,22 +149,22 @@ public void onItem(Item i) { } private String contextualNameOf(Item i) { - if (prefix.endsWith("/") || prefix.length()==0) - return prefix+i.getName(); + if (prefix.endsWith("/") || prefix.length() == 0) + return prefix + i.getName(); else - return prefix+'/'+i.getName(); + return prefix + '/' + i.getName(); } } - if (container==null || container==Jenkins.get()) { + if (container == null || container == Jenkins.get()) { new Visitor("").onItemGroup(Jenkins.get()); } else { new Visitor("").onItemGroup(container); if (value.startsWith("/")) new Visitor("/").onItemGroup(Jenkins.get()); - for ( String p="../"; value.startsWith(p); p+="../") { - container = ((Item)container).getParent(); + for (String p = "../"; value.startsWith(p); p += "../") { + container = ((Item) container).getParent(); new Visitor(p).onItemGroup(container); } } diff --git a/core/src/main/java/hudson/model/BallColor.java b/core/src/main/java/hudson/model/BallColor.java index bbaa6cda6d449..5913f59466f93 100644 --- a/core/src/main/java/hudson/model/BallColor.java +++ b/core/src/main/java/hudson/model/BallColor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Simon Wiest - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.util.ColorPalette; @@ -37,7 +38,7 @@ * *

      * There are four basic colors, plus their animated "bouncy" versions. - * {@link #ordinal()} is the sort order. + * {@link #ordinal()} is the sort order. * *

      * Note that multiple {@link BallColor} instances may map to the same @@ -53,22 +54,22 @@ * @author Kohsuke Kawaguchi */ public enum BallColor implements StatusIcon { - RED("red",Messages._BallColor_Failed(), ColorPalette.RED), - RED_ANIME("red_anime",Messages._BallColor_InProgress(), ColorPalette.RED), - YELLOW("yellow",Messages._BallColor_Unstable(), ColorPalette.YELLOW), - YELLOW_ANIME("yellow_anime",Messages._BallColor_InProgress(), ColorPalette.YELLOW), - BLUE("blue",Messages._BallColor_Success(), ColorPalette.BLUE), - BLUE_ANIME("blue_anime",Messages._BallColor_InProgress(), ColorPalette.BLUE), + RED("red", Messages._BallColor_Failed(), ColorPalette.RED), + RED_ANIME("red_anime", Messages._BallColor_InProgress(), ColorPalette.RED), + YELLOW("yellow", Messages._BallColor_Unstable(), ColorPalette.YELLOW), + YELLOW_ANIME("yellow_anime", Messages._BallColor_InProgress(), ColorPalette.YELLOW), + BLUE("blue", Messages._BallColor_Success(), ColorPalette.BLUE), + BLUE_ANIME("blue_anime", Messages._BallColor_InProgress(), ColorPalette.BLUE), // for historical reasons they are called grey. - GREY("grey",Messages._BallColor_Disabled(), ColorPalette.GREY), - GREY_ANIME("grey_anime",Messages._BallColor_InProgress(), ColorPalette.GREY), - - DISABLED("disabled",Messages._BallColor_Disabled(), ColorPalette.GREY), - DISABLED_ANIME("disabled_anime",Messages._BallColor_InProgress(), ColorPalette.GREY), - ABORTED("aborted",Messages._BallColor_Aborted(), ColorPalette.DARK_GREY), - ABORTED_ANIME("aborted_anime",Messages._BallColor_InProgress(), ColorPalette.DARK_GREY), - NOTBUILT("nobuilt",Messages._BallColor_NotBuilt(), ColorPalette.LIGHT_GREY), - NOTBUILT_ANIME("nobuilt_anime",Messages._BallColor_InProgress(), ColorPalette.LIGHT_GREY) + GREY("grey", Messages._BallColor_Disabled(), ColorPalette.GREY), + GREY_ANIME("grey_anime", Messages._BallColor_InProgress(), ColorPalette.GREY), + + DISABLED("disabled", Messages._BallColor_Disabled(), ColorPalette.GREY), + DISABLED_ANIME("disabled_anime", Messages._BallColor_InProgress(), ColorPalette.GREY), + ABORTED("aborted", Messages._BallColor_Aborted(), ColorPalette.DARK_GREY), + ABORTED_ANIME("aborted_anime", Messages._BallColor_InProgress(), ColorPalette.DARK_GREY), + NOTBUILT("nobuilt", Messages._BallColor_NotBuilt(), ColorPalette.LIGHT_GREY), + NOTBUILT_ANIME("nobuilt_anime", Messages._BallColor_InProgress(), ColorPalette.LIGHT_GREY) ; private final Localizable description; @@ -83,7 +84,7 @@ public enum BallColor implements StatusIcon { this.baseColor = baseColor; // name() is not usable in the constructor, so I have to repeat the name twice // in the constants definition. - this.image = image+ (image.endsWith("_anime")?".gif":".png"); + this.image = image + (image.endsWith("_anime") ? ".gif" : ".png"); this.description = description; } @@ -112,7 +113,7 @@ public String getImage() { @Override public String getImageOf(String size) { - return Stapler.getCurrentRequest().getContextPath()+ Jenkins.RESOURCE_PATH+"/images/"+size+'/'+image; + return Stapler.getCurrentRequest().getContextPath() + Jenkins.RESOURCE_PATH + "/images/" + size + '/' + image; } /** @@ -149,15 +150,15 @@ public String toString() { * Gets the animated version. */ public BallColor anime() { - if(isAnimated()) return this; - else return valueOf(name()+"_ANIME"); + if (isAnimated()) return this; + else return valueOf(name() + "_ANIME"); } /** * Gets the unanimated version. */ public BallColor noAnime() { - if(isAnimated()) return valueOf(name().substring(0,name().length()-"_ANIME".length())); + if (isAnimated()) return valueOf(name().substring(0, name().length() - "_ANIME".length())); else return this; } diff --git a/core/src/main/java/hudson/model/BooleanParameterDefinition.java b/core/src/main/java/hudson/model/BooleanParameterDefinition.java index 2c1cd6279110c..d4958d9ea297c 100644 --- a/core/src/main/java/hudson/model/BooleanParameterDefinition.java +++ b/core/src/main/java/hudson/model/BooleanParameterDefinition.java @@ -21,10 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import java.util.Objects; import net.sf.json.JSONObject; @@ -86,7 +88,7 @@ public ParameterValue createValue(StaplerRequest req, JSONObject jo) { @Override public ParameterValue createValue(String value) { - return new BooleanParameterValue(getName(),Boolean.parseBoolean(value),getDescription()); + return new BooleanParameterValue(getName(), Boolean.parseBoolean(value), getDescription()); } @Override @@ -103,6 +105,7 @@ public int hashCode() { } @Override + @SuppressFBWarnings(value = "EQ_GETCLASS_AND_CLASS_CONSTANT", justification = "ParameterDefinitionTest tests that subclasses are not equal to their parent classes, so the behavior appears to be intentional") public boolean equals(Object obj) { if (BooleanParameterDefinition.class != getClass()) return super.equals(obj); diff --git a/core/src/main/java/hudson/model/BooleanParameterValue.java b/core/src/main/java/hudson/model/BooleanParameterValue.java index c48cad87a69e0..d449623301cc9 100644 --- a/core/src/main/java/hudson/model/BooleanParameterValue.java +++ b/core/src/main/java/hudson/model/BooleanParameterValue.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Luca Domenico Milanesio, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.EnvVars; @@ -33,7 +34,7 @@ * {@link ParameterValue} created from {@link BooleanParameterDefinition}. */ public class BooleanParameterValue extends ParameterValue { - @Exported(visibility=4) + @Exported(visibility = 4) public final boolean value; @DataBoundConstructor @@ -55,9 +56,9 @@ public Boolean getValue() { * Exposes the name/value as an environment variable. */ @Override - public void buildEnvironment(Run build, EnvVars env) { - env.put(name,Boolean.toString(value)); - env.put(name.toUpperCase(Locale.ENGLISH),Boolean.toString(value)); // backward compatibility pre 1.345 + public void buildEnvironment(Run build, EnvVars env) { + env.put(name, Boolean.toString(value)); + env.put(name.toUpperCase(Locale.ENGLISH), Boolean.toString(value)); // backward compatibility pre 1.345 } @Override @@ -85,7 +86,7 @@ public int hashCode() { @Override public String toString() { - return "(BooleanParameterValue) " + getName() + "='" + value + "'"; + return "(BooleanParameterValue) " + getName() + "='" + value + "'"; } @Override public String getShortDescription() { diff --git a/core/src/main/java/hudson/model/Build.java b/core/src/main/java/hudson/model/Build.java index 1e82fc04618aa..49d126b8e8481 100644 --- a/core/src/main/java/hudson/model/Build.java +++ b/core/src/main/java/hudson/model/Build.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Martin Eigenbrodt - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static hudson.model.Result.FAILURE; @@ -78,12 +79,12 @@ * *

      * And beyond that, the build is considered complete, and from then on {@link Build} object is there to - * keep the record of what happened in this build. + * keep the record of what happened in this build. * * @author Kohsuke Kawaguchi */ -public abstract class Build

      ,B extends Build> - extends AbstractBuild { +public abstract class Build

      , B extends Build> + extends AbstractBuild { /** * Creates a new build. @@ -100,7 +101,7 @@ protected Build(P job, Calendar timestamp) { * Loads a build from a log file. */ protected Build(P project, File buildDir) throws IOException { - super(project,buildDir); + super(project, buildDir); } // @@ -140,27 +141,27 @@ deprecated class here. @Override protected Result doRun(@NonNull BuildListener listener) throws Exception { - if(!preBuild(listener,project.getBuilders())) + if (!preBuild(listener, project.getBuilders())) return FAILURE; - if(!preBuild(listener,project.getPublishersList())) + if (!preBuild(listener, project.getPublishersList())) return FAILURE; Result r = null; try { List wrappers = new ArrayList<>(project.getBuildWrappers().values()); - + ParametersAction parameters = getAction(ParametersAction.class); if (parameters != null) - parameters.createBuildWrappers(Build.this,wrappers); + parameters.createBuildWrappers(Build.this, wrappers); - for( BuildWrapper w : wrappers ) { - Environment e = w.setUp((AbstractBuild)Build.this, launcher, listener); - if(e==null) + for (BuildWrapper w : wrappers) { + Environment e = w.setUp((AbstractBuild) Build.this, launcher, listener); + if (e == null) return r = FAILURE; buildEnvironments.add(e); } - if(!build(listener,project.getBuilders())) + if (!build(listener, project.getBuilders())) r = FAILURE; } catch (InterruptedException e) { r = Executor.currentExecutor().abortResult(); @@ -194,12 +195,12 @@ public void cleanUp(@NonNull BuildListener listener) throws Exception { } private boolean build(@NonNull BuildListener listener, @NonNull Collection steps) throws IOException, InterruptedException { - for( BuildStep bs : steps ) { - if(!perform(bs,listener)) { + for (BuildStep bs : steps) { + if (!perform(bs, listener)) { LOGGER.log(Level.FINE, "{0} : {1} failed", new Object[] {Build.this, bs}); return false; } - + Executor executor = getExecutor(); if (executor != null && executor.isInterrupted()) { // someone asked build interruption, let stop the build before trying to run another build step diff --git a/core/src/main/java/hudson/model/BuildAuthorizationToken.java b/core/src/main/java/hudson/model/BuildAuthorizationToken.java index 43563b6f4611f..f101eb3d6e746 100644 --- a/core/src/main/java/hudson/model/BuildAuthorizationToken.java +++ b/core/src/main/java/hudson/model/BuildAuthorizationToken.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter; @@ -28,7 +29,6 @@ import hudson.security.ACL; import java.io.IOException; import javax.servlet.http.HttpServletResponse; -import jenkins.model.Jenkins; import jenkins.security.ApiTokenProperty; import org.kohsuke.stapler.HttpResponses; import org.kohsuke.stapler.StaplerRequest; @@ -55,22 +55,19 @@ public BuildAuthorizationToken(String token) { public static BuildAuthorizationToken create(StaplerRequest req) { if (req.getParameter("pseudoRemoteTrigger") != null) { String token = Util.fixEmpty(req.getParameter("authToken")); - if(token!=null) + if (token != null) return new BuildAuthorizationToken(token); } - + return null; } - @Deprecated public static void checkPermission(AbstractProject project, BuildAuthorizationToken token, StaplerRequest req, StaplerResponse rsp) throws IOException { - checkPermission((Job) project, token, req, rsp); + @Deprecated public static void checkPermission(AbstractProject project, BuildAuthorizationToken token, StaplerRequest req, StaplerResponse rsp) throws IOException { + checkPermission((Job) project, token, req, rsp); } - public static void checkPermission(Job project, BuildAuthorizationToken token, StaplerRequest req, StaplerResponse rsp) throws IOException { - if (!Jenkins.get().isUseSecurity()) - return; // everyone is authorized - - if(token!=null && token.token != null) { + public static void checkPermission(Job project, BuildAuthorizationToken token, StaplerRequest req, StaplerResponse rsp) throws IOException { + if (token != null && token.token != null) { //check the provided token String providedToken = req.getParameter("token"); if (providedToken != null && providedToken.equals(token.token)) @@ -101,7 +98,7 @@ public String getToken() { public static final class ConverterImpl extends AbstractSingleValueConverter { @Override public boolean canConvert(Class type) { - return type== BuildAuthorizationToken.class; + return type == BuildAuthorizationToken.class; } @Override @@ -111,7 +108,7 @@ public Object fromString(String str) { @Override public String toString(Object obj) { - return ((BuildAuthorizationToken)obj).token; + return ((BuildAuthorizationToken) obj).token; } } } diff --git a/core/src/main/java/hudson/model/BuildBadgeAction.java b/core/src/main/java/hudson/model/BuildBadgeAction.java index 3a673f9558352..da848424eeafa 100644 --- a/core/src/main/java/hudson/model/BuildBadgeAction.java +++ b/core/src/main/java/hudson/model/BuildBadgeAction.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; /** @@ -29,7 +30,7 @@ * *

      * This can be implemented by {@link Action}s that associate themselves - * with {@link Run}. + * with {@link Run}. * *

      * Actions with this marker should have a view {@code badge.jelly}, diff --git a/core/src/main/java/hudson/model/BuildListener.java b/core/src/main/java/hudson/model/BuildListener.java index 10043b633b22c..0f8fc060f27e5 100644 --- a/core/src/main/java/hudson/model/BuildListener.java +++ b/core/src/main/java/hudson/model/BuildListener.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import java.io.PrintStream; diff --git a/core/src/main/java/hudson/model/BuildTimelineWidget.java b/core/src/main/java/hudson/model/BuildTimelineWidget.java index 43a37a082a014..563f8a18823a5 100644 --- a/core/src/main/java/hudson/model/BuildTimelineWidget.java +++ b/core/src/main/java/hudson/model/BuildTimelineWidget.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.Util; @@ -60,17 +61,17 @@ public BuildTimelineWidget(RunList builds) { public TimelineEventList doData(StaplerRequest req, @QueryParameter long min, @QueryParameter long max) throws IOException { TimelineEventList result = new TimelineEventList(); - for (Run r : builds.byTimestamp(min,max)) { + for (Run r : builds.byTimestamp(min, max)) { Event e = new Event(); e.start = new Date(r.getStartTimeInMillis()); - e.end = new Date(r.getStartTimeInMillis()+r.getDuration()); + e.end = new Date(r.getStartTimeInMillis() + r.getDuration()); // due to SimileAjax.HTML.deEntify (in simile-ajax-bundle.js), "<" are transformed back to "<", but not the "<"; // to protect against XSS e.title = Util.escape(r.getFullDisplayName()).replace("<", "<"); - e.link = req.getContextPath()+'/'+r.getUrl(); + e.link = req.getContextPath() + '/' + r.getUrl(); BallColor c = r.getIconColor(); - e.color = String.format("#%06X",c.getBaseColor().darker().getRGB()&0xFFFFFF); - e.classname = "event-"+c.noAnime().toString()+" " + (c.isAnimated()?"animated":""); + e.color = String.format("#%06X", c.getBaseColor().darker().getRGB() & 0xFFFFFF); + e.classname = "event-" + c.noAnime().toString() + " " + (c.isAnimated() ? "animated" : ""); result.add(e); } return result; diff --git a/core/src/main/java/hudson/model/BuildVariableContributor.java b/core/src/main/java/hudson/model/BuildVariableContributor.java index 67cdc4d965e09..5054e10f48cd1 100644 --- a/core/src/main/java/hudson/model/BuildVariableContributor.java +++ b/core/src/main/java/hudson/model/BuildVariableContributor.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.ExtensionList; @@ -62,7 +63,7 @@ public abstract class BuildVariableContributor implements ExtensionPoint { * Partially built variable map. Implementation of this method is expected to * add additional variables here. Never null. */ - public abstract void buildVariablesFor(AbstractBuild build, Map variables); + public abstract void buildVariablesFor(AbstractBuild build, Map variables); /** * Returns all the registered {@link BuildVariableContributor}s. diff --git a/core/src/main/java/hudson/model/BuildableItem.java b/core/src/main/java/hudson/model/BuildableItem.java index 0d65214e43785..52fbeb97df782 100644 --- a/core/src/main/java/hudson/model/BuildableItem.java +++ b/core/src/main/java/hudson/model/BuildableItem.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.model.Queue.Task; @@ -35,24 +36,25 @@ * @author Kohsuke Kawaguchi */ public interface BuildableItem extends Item, Task { - /** - * @deprecated - * Use {@link #scheduleBuild(Cause)}. Since 1.283 - */ + /** + * @deprecated + * Use {@link #scheduleBuild(Cause)}. Since 1.283 + */ @Deprecated default boolean scheduleBuild() { - return scheduleBuild(new Cause.LegacyCodeCause()); - } + return scheduleBuild(new Cause.LegacyCodeCause()); + } + + boolean scheduleBuild(Cause c); + /** + * @deprecated + * Use {@link #scheduleBuild(int, Cause)}. Since 1.283 + */ - boolean scheduleBuild(Cause c); - /** - * @deprecated - * Use {@link #scheduleBuild(int, Cause)}. Since 1.283 - */ @Deprecated - default boolean scheduleBuild(int quietPeriod) { - return scheduleBuild(quietPeriod, new Cause.LegacyCodeCause()); - } + default boolean scheduleBuild(int quietPeriod) { + return scheduleBuild(quietPeriod, new Cause.LegacyCodeCause()); + } - boolean scheduleBuild(int quietPeriod, Cause c); + boolean scheduleBuild(int quietPeriod, Cause c); } diff --git a/core/src/main/java/hudson/model/BuildableItemWithBuildWrappers.java b/core/src/main/java/hudson/model/BuildableItemWithBuildWrappers.java index c79daa2ca2350..74f39b2928aa3 100644 --- a/core/src/main/java/hudson/model/BuildableItemWithBuildWrappers.java +++ b/core/src/main/java/hudson/model/BuildableItemWithBuildWrappers.java @@ -18,7 +18,7 @@ public interface BuildableItemWithBuildWrappers extends BuildableItem { * This method must be always implemented as {@code (AbstractProject)this}, but * defining this method emphasizes the fact that this cast must be doable. */ - AbstractProject asProject(); + AbstractProject asProject(); /** * {@link BuildWrapper}s associated with this {@link AbstractProject}. @@ -27,5 +27,5 @@ public interface BuildableItemWithBuildWrappers extends BuildableItem { * can be empty but never null. This list is live, and changes to it will be reflected * to the project configuration. */ - DescribableList> getBuildWrappersList(); + DescribableList> getBuildWrappersList(); } diff --git a/core/src/main/java/hudson/model/Cause.java b/core/src/main/java/hudson/model/Cause.java index 256fbb24eb3c7..6990dd2b39e08 100644 --- a/core/src/main/java/hudson/model/Cause.java +++ b/core/src/main/java/hudson/model/Cause.java @@ -21,11 +21,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import com.thoughtworks.xstream.converters.UnmarshallingContext; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Util; import hudson.console.ModelHyperlinkNote; import hudson.diagnosis.OldDataMonitor; @@ -69,7 +71,7 @@ public abstract class Cause { * To have rich HTML output on the UI, provide a custom {@code description.jelly} view for your subclass. * See the documentation. */ - @Exported(visibility=3) + @Exported(visibility = 3) public abstract String getShortDescription(); /** @@ -95,21 +97,21 @@ public void onAddedTo(AbstractBuild build) { * this ought to be {@code transient}. * @since 1.568 */ - public void onLoad(@NonNull Run build) { + public void onLoad(@NonNull Run build) { if (build instanceof AbstractBuild) { onLoad((AbstractBuild) build); } } - void onLoad(@NonNull Job job, int buildNumber) { - Run build = job.getBuildByNumber(buildNumber); + void onLoad(@NonNull Job job, int buildNumber) { + Run build = job.getBuildByNumber(buildNumber); if (build != null) { onLoad(build); } } @Deprecated - public void onLoad(AbstractBuild build) { + public void onLoad(AbstractBuild build) { if (Util.isOverridden(Cause.class, getClass(), "onLoad", Run.class)) { onLoad((Run) build); } @@ -129,7 +131,9 @@ public void print(TaskListener listener) { */ @Deprecated public static class LegacyCodeCause extends Cause { + @SuppressFBWarnings(value = "URF_UNREAD_FIELD", justification = "for backward compatibility") private StackTraceElement [] stackTrace; + public LegacyCodeCause() { stackTrace = new Exception().getStackTrace(); } @@ -167,8 +171,8 @@ public static class UpstreamCause extends Cause { */ // for backward bytecode compatibility @Deprecated - public UpstreamCause(AbstractBuild up) { - this((Run)up); + public UpstreamCause(AbstractBuild up) { + this((Run) up); } public UpstreamCause(Run up) { @@ -190,14 +194,14 @@ private UpstreamCause(String upstreamProject, int upstreamBuild, String upstream } @Override - public void onLoad(@NonNull Job _job, int _buildNumber) { + public void onLoad(@NonNull Job _job, int _buildNumber) { Item i = Jenkins.get().getItemByFullName(this.upstreamProject); if (!(i instanceof Job)) { // cannot initialize upstream causes return; } - Job j = (Job)i; + Job j = (Job) i; for (Cause c : this.upstreamCauses) { c.onLoad(j, upstreamBuild); } @@ -250,23 +254,23 @@ public int hashCode() { /** * Returns true if this cause points to a build in the specified job. */ - public boolean pointsTo(Job j) { + public boolean pointsTo(Job j) { return j.getFullName().equals(upstreamProject); } /** * Returns true if this cause points to the specified build. */ - public boolean pointsTo(Run r) { - return r.getNumber()==upstreamBuild && pointsTo(r.getParent()); + public boolean pointsTo(Run r) { + return r.getNumber() == upstreamBuild && pointsTo(r.getParent()); } - @Exported(visibility=3) + @Exported(visibility = 3) public String getUpstreamProject() { return upstreamProject; } - @Exported(visibility=3) + @Exported(visibility = 3) public int getUpstreamBuild() { return upstreamBuild; } @@ -274,12 +278,12 @@ public int getUpstreamBuild() { /** * @since 1.505 */ - public @CheckForNull Run getUpstreamRun() { - Job job = Jenkins.get().getItemByFullName(upstreamProject, Job.class); + public @CheckForNull Run getUpstreamRun() { + Job job = Jenkins.get().getItemByFullName(upstreamProject, Job.class); return job != null ? job.getBuildByNumber(upstreamBuild) : null; } - @Exported(visibility=3) + @Exported(visibility = 3) public String getUpstreamUrl() { return upstreamUrl; } @@ -287,7 +291,7 @@ public String getUpstreamUrl() { public List getUpstreamCauses() { return upstreamCauses; } - + @Override public String getShortDescription() { return Messages.Cause_UpstreamCause_ShortDescription(upstreamProject, upstreamBuild); @@ -309,7 +313,7 @@ private void print(TaskListener listener, int depth) { listener.getLogger().println( Messages.Cause_UpstreamCause_ShortDescription( ModelHyperlinkNote.encodeTo('/' + upstreamUrl, upstreamProject), - ModelHyperlinkNote.encodeTo('/'+upstreamUrl+upstreamBuild, Integer.toString(upstreamBuild))) + ModelHyperlinkNote.encodeTo('/' + upstreamUrl + upstreamBuild, Integer.toString(upstreamBuild))) ); if (upstreamCauses != null && !upstreamCauses.isEmpty()) { indent(listener, depth); @@ -331,6 +335,7 @@ private void print(TaskListener listener, int depth) { public static class ConverterImpl extends XStream2.PassthruConverter { public ConverterImpl(XStream2 xstream) { super(xstream); } + @Override protected void callback(UpstreamCause uc, UnmarshallingContext context) { if (uc.upstreamCause != null) { uc.upstreamCauses.add(uc.upstreamCause); @@ -344,10 +349,12 @@ public static class DeeplyNestedUpstreamCause extends Cause { @Override public String getShortDescription() { return "(deeply nested causes)"; } + @Override public String toString() { return "JENKINS-14814"; } - @Override public void onLoad(@NonNull Job _job, int _buildNumber) {} + + @Override public void onLoad(@NonNull Job _job, int _buildNumber) {} } } @@ -361,6 +368,7 @@ public static class DeeplyNestedUpstreamCause extends Cause { @Deprecated public static class UserCause extends Cause { private String authenticationName; + public UserCause() { this.authenticationName = Jenkins.getAuthentication2().getName(); } @@ -370,10 +378,10 @@ public UserCause() { * @return User display name. * If the User does not exist, returns its ID. */ - @Exported(visibility=3) + @Exported(visibility = 3) public String getUserName() { - final User user = User.getById(authenticationName, false); - return user != null ? user.getDisplayName() : authenticationName; + final User user = User.getById(authenticationName, false); + return user != null ? user.getDisplayName() : authenticationName; } @Override @@ -384,7 +392,7 @@ public String getShortDescription() { @Override public boolean equals(Object o) { return o instanceof UserCause && Arrays.equals(new Object[] {authenticationName}, - new Object[] {((UserCause)o).authenticationName}); + new Object[] {((UserCause) o).authenticationName}); } @Override @@ -425,7 +433,7 @@ public UserIdCause(@CheckForNull String userId) { public String getUserId() { return userId; } - + @NonNull private String getUserIdOrUnknown() { return userId != null ? userId : User.getUnknown().getId(); @@ -483,17 +491,17 @@ public RemoteCause(String host, String note) { @Override public String getShortDescription() { - if(note != null) { + if (note != null) { return Messages.Cause_RemoteCause_ShortDescriptionWithNote(addr, note); } return Messages.Cause_RemoteCause_ShortDescription(addr); } - + @Exported(visibility = 3) public String getAddr() { return addr; } - + @Exported(visibility = 3) public String getNote() { return note; diff --git a/core/src/main/java/hudson/model/CauseAction.java b/core/src/main/java/hudson/model/CauseAction.java index fc225f3140af3..eca42ffb69994 100644 --- a/core/src/main/java/hudson/model/CauseAction.java +++ b/core/src/main/java/hudson/model/CauseAction.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import com.thoughtworks.xstream.converters.UnmarshallingContext; @@ -52,7 +53,7 @@ public class CauseAction implements FoldableAction, RunAction2 { @Deprecated private transient List causes; - private Map causeBag = new LinkedHashMap<>(); + private Map causeBag = new LinkedHashMap<>(); public CauseAction(Cause c) { this.causeBag.put(c, 1); @@ -64,6 +65,7 @@ private void addCause(Cause c) { causeBag.put(c, cnt == null ? 1 : cnt + 1); } } + private void addCauses(Collection causes) { for (Cause cause : causes) { addCause(cause); @@ -90,10 +92,10 @@ public CauseAction(CauseAction ca) { * to create an action with multiple causes use either of the constructors that support this; * to append causes retroactively to a build you must create a new {@link CauseAction} and replace the old */ - @Exported(visibility=2) + @Exported(visibility = 2) public List getCauses() { List r = new ArrayList<>(); - for (Map.Entry entry : causeBag.entrySet()) { + for (Map.Entry entry : causeBag.entrySet()) { r.addAll(Collections.nCopies(entry.getValue(), entry.getKey())); } return Collections.unmodifiableList(r); @@ -129,7 +131,7 @@ public String getUrlName() { * Get list of causes with duplicates combined into counters. * @return Map of Cause to number of occurrences of that Cause */ - public Map getCauseCounts() { + public Map getCauseCounts() { return Collections.unmodifiableMap(causeBag); } @@ -145,7 +147,7 @@ public String getShortDescription() { return causeBag.keySet().iterator().next().getShortDescription(); } - @Override public void onLoad(Run owner) { + @Override public void onLoad(Run owner) { for (Cause c : causeBag.keySet()) { if (c != null) { c.onLoad(owner); @@ -156,7 +158,7 @@ public String getShortDescription() { /** * When hooked up to build, notify {@link Cause}s. */ - @Override public void onAttached(Run owner) { + @Override public void onAttached(Run owner) { for (Cause c : causeBag.keySet()) { if (c != null) { c.onAddedTo(owner); @@ -167,7 +169,7 @@ public String getShortDescription() { @Override public void foldIntoExisting(hudson.model.Queue.Item item, Task owner, List otherActions) { CauseAction existing = item.getAction(CauseAction.class); - if (existing!=null) { + if (existing != null) { existing.addCauses(getCauses()); return; } @@ -177,6 +179,7 @@ public void foldIntoExisting(hudson.model.Queue.Item item, Task owner, List { public ConverterImpl(XStream2 xstream) { super(xstream); } + @Override protected void callback(CauseAction ca, UnmarshallingContext context) { // if we are being read in from an older version if (ca.cause != null) { diff --git a/core/src/main/java/hudson/model/CheckPoint.java b/core/src/main/java/hudson/model/CheckPoint.java index 773421a17eb83..b7a7fdb9da905 100644 --- a/core/src/main/java/hudson/model/CheckPoint.java +++ b/core/src/main/java/hudson/model/CheckPoint.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.NonNull; @@ -60,7 +61,7 @@ * depend on its earlier result. * * @author Kohsuke Kawaguchi - * @see BuildStep#getRequiredMonitorService() + * @see BuildStep#getRequiredMonitorService() * @since 1.319 */ public final class CheckPoint { @@ -87,7 +88,7 @@ public CheckPoint(String internalName) { @Override public boolean equals(Object that) { if (that == null || getClass() != that.getClass()) return false; - return identity== ((CheckPoint) that).identity; + return identity == ((CheckPoint) that).identity; } @Override @@ -97,7 +98,7 @@ public int hashCode() { @Override public String toString() { - return "Check point "+internalName; + return "Check point " + internalName; } /** @@ -140,7 +141,7 @@ public void report() { * This method can be only called from an {@link Executor} thread. * * @throws InterruptedException - * If the build (represented by the calling executor thread) is aborted while it's waiting. + * If the build (represented by the calling executor thread) is aborted while it's waiting. */ public void block() throws InterruptedException { Run.waitForCheckpoint(this, null, null); diff --git a/core/src/main/java/hudson/model/ChoiceParameterDefinition.java b/core/src/main/java/hudson/model/ChoiceParameterDefinition.java index c83d27de63b19..615bd84e8bba9 100644 --- a/core/src/main/java/hudson/model/ChoiceParameterDefinition.java +++ b/core/src/main/java/hudson/model/ChoiceParameterDefinition.java @@ -3,6 +3,7 @@ import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import hudson.Util; import hudson.util.FormValidation; @@ -13,7 +14,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import net.sf.json.JSONObject; -import org.apache.commons.lang.StringUtils; import org.jenkinsci.Symbol; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; @@ -38,7 +38,7 @@ public class ChoiceParameterDefinition extends SimpleParameterDefinition { public static boolean areValidChoices(@NonNull String choices) { String strippedChoices = choices.trim(); - return !StringUtils.isEmpty(strippedChoices) && strippedChoices.split(CHOICES_DELIMITER).length > 0; + return strippedChoices != null && !strippedChoices.isEmpty() && strippedChoices.split(CHOICES_DELIMITER).length > 0; } public ChoiceParameterDefinition(@NonNull String name, @NonNull String choices, @CheckForNull String description) { @@ -181,6 +181,7 @@ public int hashCode() { } @Override + @SuppressFBWarnings(value = "EQ_GETCLASS_AND_CLASS_CONSTANT", justification = "ParameterDefinitionTest tests that subclasses are not equal to their parent classes, so the behavior appears to be intentional") public boolean equals(Object obj) { if (ChoiceParameterDefinition.class != getClass()) return super.equals(obj); @@ -200,7 +201,7 @@ public boolean equals(Object obj) { return Objects.equals(defaultValue, other.defaultValue); } - @Extension @Symbol({"choice","choiceParam"}) + @Extension @Symbol({"choice", "choiceParam"}) public static class DescriptorImpl extends ParameterDescriptor { @Override public String getDisplayName() { diff --git a/core/src/main/java/hudson/model/Computer.java b/core/src/main/java/hudson/model/Computer.java index c0f49ce5dcee2..dd6abb37ef279 100644 --- a/core/src/main/java/hudson/model/Computer.java +++ b/core/src/main/java/hudson/model/Computer.java @@ -23,6 +23,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; @@ -262,7 +263,7 @@ protected Computer(Node node) { /** * Returns list of all boxes {@link ComputerPanelBox}s. */ - public List getComputerPanelBoxs(){ + public List getComputerPanelBoxs() { return ComputerPanelBox.all(this); } @@ -282,7 +283,7 @@ public List getActions() { return Collections.unmodifiableList(result); } - @SuppressWarnings({"ConstantConditions","deprecation"}) + @SuppressWarnings({"ConstantConditions", "deprecation"}) @Override public void addAction(@NonNull Action a) { if (a == null) { @@ -300,7 +301,7 @@ public void addAction(@NonNull Action a) { * @see #relocateOldLogs() */ public @NonNull File getLogFile() { - return new File(getLogDir(),"slave.log"); + return new File(getLogDir(), "slave.log"); } /** @@ -311,7 +312,7 @@ public void addAction(@NonNull Action a) { * @since 1.613 */ protected @NonNull File getLogDir() { - File dir = new File(Jenkins.get().getRootDir(),"logs/slaves/"+nodeName); + File dir = new File(Jenkins.get().getRootDir(), "logs/slaves/" + nodeName); synchronized (logDirLock) { try { IOUtils.mkdirs(dir); @@ -374,7 +375,7 @@ public String getOfflineCauseReason() { return ""; } // fetch the localized string for "Disconnected By" - String gsub_base = hudson.slaves.Messages.SlaveComputer_DisconnectedBy("",""); + String gsub_base = hudson.slaves.Messages.SlaveComputer_DisconnectedBy("", ""); // regex to remove commented reason base string String gsub1 = "^" + gsub_base + "[\\w\\W]* \\: "; // regex to remove non-commented reason base string @@ -408,7 +409,7 @@ public String getOfflineCauseReason() { /** * If {@link #getChannel()}==null, attempts to relaunch the agent. */ - public abstract void doLaunchSlaveAgent( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException; + public abstract void doLaunchSlaveAgent(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException; /** * @deprecated since 2009-01-06. Use {@link #connect(boolean)} @@ -503,10 +504,10 @@ public final long getConnectTime() { public Future disconnect(OfflineCause cause) { recordTermination(); offlineCause = cause; - if (Util.isOverridden(Computer.class,getClass(),"disconnect")) + if (Util.isOverridden(Computer.class, getClass(), "disconnect")) return disconnect(); // legacy subtypes that extend disconnect(). - connectTime=0; + connectTime = 0; return Futures.precomputed(null); } @@ -519,11 +520,11 @@ public Future disconnect(OfflineCause cause) { @Deprecated public Future disconnect() { recordTermination(); - if (Util.isOverridden(Computer.class,getClass(),"disconnect",OfflineCause.class)) + if (Util.isOverridden(Computer.class, getClass(), "disconnect", OfflineCause.class)) // if the subtype already derives disconnect(OfflineCause), delegate to it return disconnect(null); - connectTime=0; + connectTime = 0; return Futures.precomputed(null); } @@ -619,7 +620,7 @@ public BuildTimelineWidget getTimeline() { @Exported public boolean isOffline() { - return temporarilyOffline || getChannel()==null; + return temporarilyOffline || getChannel() == null; } public final boolean isOnline() { @@ -689,7 +690,7 @@ public boolean isTemporarilyOffline() { */ @Deprecated public void setTemporarilyOffline(boolean temporarilyOffline) { - setTemporarilyOffline(temporarilyOffline,null); + setTemporarilyOffline(temporarilyOffline, null); } /** @@ -727,10 +728,10 @@ public void setTemporarilyOffline(boolean temporarilyOffline, OfflineCause cause @Exported public String getIcon() { // The machine was taken offline by someone - if (isTemporarilyOffline() && getOfflineCause() instanceof OfflineCause.UserCause) return "computer-user-offline.png"; + if (isTemporarilyOffline() && getOfflineCause() instanceof OfflineCause.UserCause) return "symbol-computer-disconnected"; // There is a "technical" reason the computer will not accept new builds - if (isOffline() || !isAcceptingTasks()) return "computer-x.png"; - return "computer.png"; + if (isOffline() || !isAcceptingTasks()) return "symbol-computer-offline"; + return "symbol-computer"; } /** @@ -747,10 +748,10 @@ public String getIcon() { @Exported public String getIconClassName() { // The machine was taken offline by someone - if (isTemporarilyOffline() && getOfflineCause() instanceof OfflineCause.UserCause) return "icon-computer-user-offline"; + if (isTemporarilyOffline() && getOfflineCause() instanceof OfflineCause.UserCause) return "symbol-computer-disconnected"; // There is a "technical" reason the computer will not accept new builds - if (isOffline() || !isAcceptingTasks()) return "icon-computer-x"; - return "icon-computer"; + if (isOffline() || !isAcceptingTasks()) return "symbol-computer-offline"; + return "symbol-computer"; } public String getIconAltText() { @@ -789,7 +790,7 @@ public List getTiedJobs() { } public RunList getBuilds() { - return RunList.fromJobs((Iterable)Jenkins.get().allItems(Job.class)).node(getNode()); + return RunList.fromJobs((Iterable) Jenkins.get().allItems(Job.class)).node(getNode()); } /** @@ -797,8 +798,8 @@ public RunList getBuilds() { * configuration is updated. */ protected void setNode(Node node) { - assert node!=null; - if(node instanceof Slave) + assert node != null; + if (node instanceof Slave) this.nodeName = node.getNodeName(); else this.nodeName = null; @@ -880,9 +881,9 @@ protected void onRemoved(){ @GuardedBy("hudson.model.Queue.lock") private void setNumExecutors(int n) { this.numExecutors = n; - final int diff = executors.size()-n; + final int diff = executors.size() - n; - if (diff>0) { + if (diff > 0) { // we have too many executors // send signal to all idle executors to potentially kill them off // need the Queue maintenance lock held to prevent concurrent job assignment on the idle executors @@ -895,7 +896,7 @@ private void setNumExecutors(int n) { }); } - if (diff<0) { + if (diff < 0) { // if the number is increased, add new ones addNewExecutorIfNecessary(); } @@ -931,7 +932,7 @@ Extra executors will call removeExecutor(...) and that public int countIdle() { int n = 0; for (Executor e : executors) { - if(e.isIdle()) + if (e.isIdle()) n++; } return n; @@ -941,7 +942,7 @@ public int countIdle() { * Returns the number of {@link Executor}s that are doing some work right now. */ public final int countBusy() { - return countExecutors()-countIdle(); + return countExecutors() - countIdle(); } /** @@ -995,14 +996,14 @@ public List getDisplayExecutors() { // The size may change while we are populating, but let's start with a reasonable guess to minimize resizing List result = new ArrayList<>(executors.size() + oneOffExecutors.size()); int index = 0; - for (Executor e: executors) { + for (Executor e : executors) { if (e.isDisplayCell()) { result.add(new DisplayExecutor(Integer.toString(index + 1), String.format("executors/%d", index), e)); } index++; } index = 0; - for (OneOffExecutor e: oneOffExecutors) { + for (OneOffExecutor e : oneOffExecutors) { if (e.isDisplayCell()) { result.add(new DisplayExecutor("", String.format("oneOffExecutors/%d", index), e)); } @@ -1019,7 +1020,7 @@ public final boolean isIdle() { if (!oneOffExecutors.isEmpty()) return false; for (Executor e : executors) - if(!e.isIdle()) + if (!e.isIdle()) return false; return true; } @@ -1029,7 +1030,7 @@ public final boolean isIdle() { */ public final boolean isPartiallyIdle() { for (Executor e : executors) - if(e.isIdle()) + if (e.isIdle()) return true; return false; } @@ -1152,9 +1153,9 @@ public hudson.search.Icon getSearchItemIcon() { /** * Expose monitoring data for the remote API. */ - @Exported(inline=true) - public Map getMonitorData() { - Map r = new HashMap<>(); + @Exported(inline = true) + public Map getMonitorData() { + Map r = new HashMap<>(); if (hasPermission(CONNECT)) { for (NodeMonitor monitor : NodeMonitor.getAll()) r.put(monitor.getClass().getName(), monitor.data(this)); @@ -1166,7 +1167,7 @@ public hudson.search.Icon getSearchItemIcon() { * Gets the system properties of the JVM on this computer. * If this is the master, it returns the system property of the master computer. */ - public Map getSystemProperties() throws IOException, InterruptedException { + public Map getSystemProperties() throws IOException, InterruptedException { return RemotingDiagnostics.getSystemProperties(getChannel()); } @@ -1175,7 +1176,7 @@ public Map getSystemProperties() throws IOException, InterruptedE * Use {@link #getEnvironment()} instead. */ @Deprecated - public Map getEnvVars() throws IOException, InterruptedException { + public Map getEnvVars() throws IOException, InterruptedException { return getEnvironment(); } @@ -1204,19 +1205,19 @@ public EnvVars getEnvironment() throws IOException, InterruptedException { EnvVars env = new EnvVars(); Node node = getNode(); - if (node==null) return env; // bail out + if (node == null) return env; // bail out - for (NodeProperty nodeProperty: Jenkins.get().getGlobalNodeProperties()) { - nodeProperty.buildEnvVars(env,listener); + for (NodeProperty nodeProperty : Jenkins.get().getGlobalNodeProperties()) { + nodeProperty.buildEnvVars(env, listener); } - for (NodeProperty nodeProperty: node.getNodeProperties()) { - nodeProperty.buildEnvVars(env,listener); + for (NodeProperty nodeProperty : node.getNodeProperties()) { + nodeProperty.buildEnvVars(env, listener); } // TODO: hmm, they don't really belong String rootUrl = Jenkins.get().getRootUrl(); - if(rootUrl!=null) { + if (rootUrl != null) { env.put("HUDSON_URL", rootUrl); // Legacy. env.put("JENKINS_URL", rootUrl); } @@ -1229,7 +1230,7 @@ public EnvVars getEnvironment() throws IOException, InterruptedException { * @return * key is the thread name, and the value is the pre-formatted dump. */ - public Map getThreadDump() throws IOException, InterruptedException { + public Map getThreadDump() throws IOException, InterruptedException { return RemotingDiagnostics.getThreadDump(getChannel()); } @@ -1237,7 +1238,7 @@ public Map getThreadDump() throws IOException, InterruptedExcepti * Obtains the heap dump. */ public HeapDump getHeapDump() throws IOException { - return new HeapDump(this,getChannel()); + return new HeapDump(this, getChannel()); } /** @@ -1263,21 +1264,21 @@ public HeapDump getHeapDump() throws IOException { * because the agent is behind the firewall, etc.) */ public String getHostName() throws IOException, InterruptedException { - if(hostNameCached) + if (hostNameCached) // in the worst case we end up having multiple threads computing the host name simultaneously, but that's not harmful, just wasteful. return cachedHostName; VirtualChannel channel = getChannel(); - if(channel==null) return null; // can't compute right now + if (channel == null) return null; // can't compute right now - for( String address : channel.call(new ListPossibleNames())) { + for (String address : channel.call(new ListPossibleNames())) { try { InetAddress ia = InetAddress.getByName(address); - if(!(ia instanceof Inet4Address)) { + if (!(ia instanceof Inet4Address)) { LOGGER.log(Level.FINE, "{0} is not an IPv4 address", address); continue; } - if(!ComputerPinger.checkIsReachable(ia, 3)) { + if (!ComputerPinger.checkIsReachable(ia, 3)) { LOGGER.log(Level.FINE, "{0} didn't respond to ping", address); continue; } @@ -1312,7 +1313,7 @@ public String getHostName() throws IOException, InterruptedException { oneOffExecutors.remove(e); } - private static class ListPossibleNames extends MasterToSlaveCallable,IOException> { + private static class ListPossibleNames extends MasterToSlaveCallable, IOException> { /** * In the normal case we would use {@link Computer} as the logger's name, however to * do that we would have to send the {@link Computer} class over to the remote classloader @@ -1335,12 +1336,12 @@ public List call() throws IOException { Enumeration e = ni.getInetAddresses(); while (e.hasMoreElements()) { InetAddress ia = e.nextElement(); - if(ia.isLoopbackAddress()) { + if (ia.isLoopbackAddress()) { LOGGER.log(Level.FINE, "{0} is a loopback address", ia); continue; } - if(!(ia instanceof Inet4Address)) { + if (!(ia instanceof Inet4Address)) { LOGGER.log(Level.FINE, "{0} is not an IPv4 address", ia); continue; } @@ -1351,14 +1352,16 @@ public List call() throws IOException { } return names; } + private static final long serialVersionUID = 1L; } - private static class GetFallbackName extends MasterToSlaveCallable { + private static class GetFallbackName extends MasterToSlaveCallable { @Override public String call() throws IOException { return SystemProperties.getString("host.name"); } + private static final long serialVersionUID = 1L; } @@ -1375,12 +1378,12 @@ public String call() throws IOException { // // @Restricted(DoNotUse.class) - public void doRssAll( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public void doRssAll(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { RSS.rss(req, rsp, "Jenkins:" + getDisplayName() + " (all builds)", getUrl(), getBuilds()); } @Restricted(DoNotUse.class) - public void doRssFailed(StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public void doRssFailed(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { RSS.rss(req, rsp, "Jenkins:" + getDisplayName() + " (failed builds)", getUrl(), getBuilds().failureOnly()); } @@ -1391,7 +1394,7 @@ public void doRssFailed(StaplerRequest req, StaplerResponse rsp ) throws IOExcep * @since 2.215 */ @Restricted(DoNotUse.class) - public void doRssLatest( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public void doRssLatest(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { final List lastBuilds = new ArrayList<>(); for (AbstractProject p : Jenkins.get().allItems(AbstractProject.class)) { if (p.getLastBuild() != null) { @@ -1408,14 +1411,14 @@ public void doRssLatest( StaplerRequest req, StaplerResponse rsp ) throws IOExce @RequirePOST public HttpResponse doToggleOffline(@QueryParameter String offlineMessage) throws IOException, ServletException { - if(!temporarilyOffline) { + if (!temporarilyOffline) { checkPermission(DISCONNECT); offlineMessage = Util.fixEmptyAndTrim(offlineMessage); setTemporarilyOffline(!temporarilyOffline, new OfflineCause.UserCause(User.current(), offlineMessage)); } else { checkPermission(CONNECT); - setTemporarilyOffline(!temporarilyOffline,null); + setTemporarilyOffline(!temporarilyOffline, null); } return HttpResponses.redirectToDot(); } @@ -1436,7 +1439,7 @@ public Api getApi() { /** * Dumps the contents of the export table. */ - public void doDumpExportTable( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, InterruptedException { + public void doDumpExportTable(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, InterruptedException { // this is a debug probe and may expose sensitive information checkPermission(Jenkins.ADMINISTER); @@ -1456,7 +1459,7 @@ public void doDumpExportTable( StaplerRequest req, StaplerResponse rsp ) throws } } - private static final class DumpExportTableTask extends MasterToSlaveCallable { + private static final class DumpExportTableTask extends MasterToSlaveCallable { @Override public String call() throws IOException { final Channel ch = getChannelOrFail(); @@ -1491,7 +1494,7 @@ protected void _doScript(StaplerRequest req, StaplerResponse rsp, String view) t * Accepts the update to the node configuration. */ @POST - public void doConfigSubmit( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, FormException { + public void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException { checkPermission(CONFIGURE); String proposedName = Util.fixEmptyAndTrim(req.getSubmittedForm().getString("name")); @@ -1508,7 +1511,7 @@ public void doConfigSubmit( StaplerRequest req, StaplerResponse rsp ) throws IOE } String nExecutors = req.getSubmittedForm().getString("numExecutors"); - if (StringUtils.isBlank(nExecutors) || Integer.parseInt(nExecutors)<=0) { + if (StringUtils.isBlank(nExecutors) || Integer.parseInt(nExecutors) <= 0) { throw new FormException(Messages.Slave_InvalidConfig_Executors(nodeName), "numExecutors"); } @@ -1558,7 +1561,7 @@ public void updateByXml(final InputStream source) throws IOException, ServletExc if (previous == null) { throw HttpResponses.notFound(); } - Node result = (Node)Jenkins.XSTREAM2.fromXML(source); + Node result = (Node) Jenkins.XSTREAM2.fromXML(source); if (previous.getClass() != result.getClass()) { // ensure node type doesn't change throw HttpResponses.errorWithoutStack(SC_BAD_REQUEST, "Node types do not match"); @@ -1602,7 +1605,7 @@ public void waitUntilOffline() throws InterruptedException { /** * Handles incremental log. */ - public void doProgressiveLog( StaplerRequest req, StaplerResponse rsp) throws IOException { + public void doProgressiveLog(StaplerRequest req, StaplerResponse rsp) throws IOException { getLogText().doProgressText(req, rsp); } @@ -1652,10 +1655,10 @@ public boolean isAcceptingTasks() { */ @CLIResolver public static Computer resolveForCLI( - @Argument(required=true,metaVar="NAME",usage="Agent name, or empty string for built-in node") String name) throws CmdLineException { + @Argument(required = true, metaVar = "NAME", usage = "Agent name, or empty string for built-in node") String name) throws CmdLineException { Jenkins h = Jenkins.get(); Computer item = h.getComputer(name); - if (item==null) { + if (item == null) { List names = ComputerSet.getComputerNames(); String adv = EditDistance.findNearest(name, names); throw new IllegalArgumentException(adv == null ? @@ -1682,16 +1685,16 @@ public static void relocateOldLogs() { /*package*/ static void relocateOldLogs(File dir) { final Pattern logfile = Pattern.compile("slave-(.*)\\.log(\\.[0-9]+)?"); File[] logfiles = dir.listFiles((dir1, name) -> logfile.matcher(name).matches()); - if (logfiles==null) return; + if (logfiles == null) return; for (File f : logfiles) { Matcher m = logfile.matcher(f.getName()); if (m.matches()) { File newLocation = new File(dir, "logs/slaves/" + m.group(1) + "/slave.log" + Util.fixNull(m.group(2))); try { - Files.createDirectories(newLocation.getParentFile().toPath()); + Util.createDirectories(newLocation.getParentFile().toPath()); Files.move(f.toPath(), newLocation.toPath(), StandardCopyOption.REPLACE_EXISTING); - LOGGER.log(Level.INFO, "Relocated log file {0} to {1}",new Object[] {f.getPath(),newLocation.getPath()}); + LOGGER.log(Level.INFO, "Relocated log file {0} to {1}", new Object[] {f.getPath(), newLocation.getPath()}); } catch (IOException | InvalidPathException e) { LOGGER.log(Level.WARNING, e, () -> "Cannot relocate log file " + f.getPath() + " to " + newLocation.getPath()); } @@ -1784,6 +1787,7 @@ public int hashCode() { */ public static class TerminationRequest extends RuntimeException { private final long when; + public TerminationRequest(String message) { super(message); this.when = System.currentTimeMillis(); @@ -1800,7 +1804,7 @@ public long getWhen() { } } - public static final PermissionGroup PERMISSIONS = new PermissionGroup(Computer.class,Messages._Computer_Permissions_Title()); + public static final PermissionGroup PERMISSIONS = new PermissionGroup(Computer.class, Messages._Computer_Permissions_Title()); public static final Permission CONFIGURE = new Permission( PERMISSIONS, diff --git a/core/src/main/java/hudson/model/ComputerPanelBox.java b/core/src/main/java/hudson/model/ComputerPanelBox.java index d5e7e45cba50e..f75fde52d79e4 100644 --- a/core/src/main/java/hudson/model/ComputerPanelBox.java +++ b/core/src/main/java/hudson/model/ComputerPanelBox.java @@ -15,19 +15,19 @@ * @see hudson.model.Computer#getComputerPanelBoxs() */ -public abstract class ComputerPanelBox implements ExtensionPoint{ - +public abstract class ComputerPanelBox implements ExtensionPoint { + private Computer computer; - - - public void setComputer(Computer computer){ + + + public void setComputer(Computer computer) { this.computer = computer; } - - public Computer getComputer(){ + + public Computer getComputer() { return computer; } - + /** * Create boxes for the given computer in its page. * @@ -38,7 +38,7 @@ public Computer getComputer(){ */ public static List all(Computer computer) { List boxs = new ArrayList<>(); - for(ComputerPanelBox box: ExtensionList.lookup(ComputerPanelBox.class)){ + for (ComputerPanelBox box : ExtensionList.lookup(ComputerPanelBox.class)) { box.setComputer(computer); boxs.add(box); } diff --git a/core/src/main/java/hudson/model/ComputerPinger.java b/core/src/main/java/hudson/model/ComputerPinger.java index 38894a2d5edc2..8aaf47a843eaf 100644 --- a/core/src/main/java/hudson/model/ComputerPinger.java +++ b/core/src/main/java/hudson/model/ComputerPinger.java @@ -48,7 +48,7 @@ public static boolean checkIsReachable(InetAddress ia, int timeout) throws IOExc return false; } - + /** * Default pinger - use Java built-in functionality. This doesn't always work, * a host may be reachable even if this returns false. @@ -57,7 +57,7 @@ public static boolean checkIsReachable(InetAddress ia, int timeout) throws IOExc public static class BuiltInComputerPinger extends ComputerPinger { @Override public boolean isReachable(InetAddress ia, int timeout) throws IOException { - return ia.isReachable((int)TimeUnit.SECONDS.toMillis(timeout)); + return ia.isReachable((int) TimeUnit.SECONDS.toMillis(timeout)); } } diff --git a/core/src/main/java/hudson/model/ComputerSet.java b/core/src/main/java/hudson/model/ComputerSet.java index db4292989e49b..ecef09a90fc30 100644 --- a/core/src/main/java/hudson/model/ComputerSet.java +++ b/core/src/main/java/hudson/model/ComputerSet.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Stephen Connolly, Thomas J. Black - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static hudson.init.InitMilestone.JOB_CONFIG_ADAPTED; @@ -86,7 +87,7 @@ public void save() throws IOException { } }; - private static final DescribableList> monitors + private static final DescribableList> monitors = new DescribableList<>(MONITORS_OWNER); @Override @@ -104,7 +105,7 @@ public static List get_monitors() { return monitors.toList(); } - @Exported(name="computer",inline=true) + @Exported(name = "computer", inline = true) public Computer[] get_all() { return Jenkins.get().getComputers(); } @@ -121,22 +122,22 @@ public ContextMenu doChildrenContextMenu(StaplerRequest request, StaplerResponse /** * Exposing {@link NodeMonitor#all()} for Jelly binding. */ - public DescriptorExtensionList> getNodeMonitorDescriptors() { + public DescriptorExtensionList> getNodeMonitorDescriptors() { return NodeMonitor.all(); } - public static DescribableList> getMonitors() { + public static DescribableList> getMonitors() { return monitors; } /** * Returns a subset pf {@link #getMonitors()} that are {@linkplain NodeMonitor#isIgnored() not ignored}. */ - public static Map,NodeMonitor> getNonIgnoredMonitors() { - Map,NodeMonitor> r = new HashMap<>(); + public static Map, NodeMonitor> getNonIgnoredMonitors() { + Map, NodeMonitor> r = new HashMap<>(); for (NodeMonitor m : monitors) { - if(!m.isIgnored()) - r.put(m.getDescriptor(),m); + if (!m.isIgnored()) + r.put(m.getDescriptor(), m); } return r; } @@ -167,9 +168,9 @@ public int size() { */ @Exported public int getTotalExecutors() { - int r=0; + int r = 0; for (Computer c : get_all()) { - if(c.isOnline()) + if (c.isOnline()) r += c.countExecutors(); } return r; @@ -180,9 +181,9 @@ public int getTotalExecutors() { */ @Exported public int getBusyExecutors() { - int r=0; + int r = 0; for (Computer c : get_all()) { - if(c.isOnline()) + if (c.isOnline()) r += c.countBusy(); } return r; @@ -192,9 +193,9 @@ public int getBusyExecutors() { * {@code getTotalExecutors()-getBusyExecutors()}, plus executors that are being brought online. */ public int getIdleExecutors() { - int r=0; + int r = 0; for (Computer c : get_all()) - if((c.isOnline() || c.isConnecting()) && c.isAcceptingTasks()) + if ((c.isOnline() || c.isConnecting()) && c.isAcceptingTasks()) r += c.countIdle(); return r; } @@ -212,8 +213,8 @@ public Computer getDynamic(String token, StaplerRequest req, StaplerResponse rsp public void do_launchAll(StaplerRequest req, StaplerResponse rsp) throws IOException { Jenkins.get().checkPermission(Jenkins.ADMINISTER); - for(Computer c : get_all()) { - if(c.isLaunchSupported()) + for (Computer c : get_all()) { + if (c.isLaunchSupported()) c.connect(true); } rsp.sendRedirect("."); @@ -225,9 +226,9 @@ public void do_launchAll(StaplerRequest req, StaplerResponse rsp) throws IOExcep * TODO: ajax on the client side to wait until the update completion might be nice. */ @RequirePOST - public void doUpdateNow( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public void doUpdateNow(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { Jenkins.get().checkPermission(Jenkins.MANAGE); - + for (NodeMonitor nodeMonitor : NodeMonitor.getAll()) { Thread t = nodeMonitor.triggerUpdate(); String columnCaption = nodeMonitor.getColumnCaption(); @@ -242,17 +243,17 @@ public void doUpdateNow( StaplerRequest req, StaplerResponse rsp ) throws IOExce * First check point in creating a new agent. */ @RequirePOST - public synchronized void doCreateItem( StaplerRequest req, StaplerResponse rsp, + public synchronized void doCreateItem(StaplerRequest req, StaplerResponse rsp, @QueryParameter String name, @QueryParameter String mode, - @QueryParameter String from ) throws IOException, ServletException { + @QueryParameter String from) throws IOException, ServletException { final Jenkins app = Jenkins.get(); app.checkPermission(Computer.CREATE); - if(mode!=null && mode.equals("copy")) { + if (mode != null && mode.equals("copy")) { name = checkName(name); Node src = app.getNode(from); - if(src==null) { + if (src == null) { if (Util.fixEmpty(from) == null) { throw new Failure(Messages.ComputerSet_SpecifySlaveToCopy()); } else { @@ -269,7 +270,7 @@ public synchronized void doCreateItem( StaplerRequest req, StaplerResponse rsp, app.addNode(result); // send the browser to the config page - rsp.sendRedirect2(result.getNodeName()+"/configure"); + rsp.sendRedirect2(result.getNodeName() + "/configure"); } else { // proceed to step 2 if (mode == null) { @@ -280,7 +281,7 @@ public synchronized void doCreateItem( StaplerRequest req, StaplerResponse rsp, if (d == null) { throw new Failure("No node type ‘" + mode + "’ is known"); } - d.handleNewNodePage(this,name,req,rsp); + d.handleNewNodePage(this, name, req, rsp); } } @@ -288,9 +289,9 @@ public synchronized void doCreateItem( StaplerRequest req, StaplerResponse rsp, * Really creates a new agent. */ @POST - public synchronized void doDoCreateItem( StaplerRequest req, StaplerResponse rsp, + public synchronized void doDoCreateItem(StaplerRequest req, StaplerResponse rsp, @QueryParameter String name, - @QueryParameter String type ) throws IOException, ServletException, FormException { + @QueryParameter String type) throws IOException, ServletException, FormException { final Jenkins app = Jenkins.get(); app.checkPermission(Computer.CREATE); String fixedName = Util.fixEmptyAndTrim(name); @@ -298,7 +299,7 @@ public synchronized void doDoCreateItem( StaplerRequest req, StaplerResponse rsp JSONObject formData = req.getSubmittedForm(); formData.put("name", fixedName); - + // TODO type is probably NodeDescriptor.id but confirm Node result = NodeDescriptor.all().find(type).newInstance(req, formData); app.addNode(result); @@ -312,13 +313,13 @@ public synchronized void doDoCreateItem( StaplerRequest req, StaplerResponse rsp * @return trimmed name if valid; throws ParseException if not */ public String checkName(String name) throws Failure { - if(name==null) + if (name == null) throw new Failure("Query parameter 'name' is required"); name = name.trim(); Jenkins.checkGoodName(name); - if(Jenkins.get().getNode(name)!=null) + if (Jenkins.get().getNode(name) != null) throw new Failure(Messages.ComputerSet_SlaveAlreadyExists(name)); // looks good @@ -331,9 +332,9 @@ public String checkName(String name) throws Failure { public FormValidation doCheckName(@QueryParameter String value) throws IOException, ServletException { Jenkins.get().checkPermission(Computer.CREATE); - if(Util.fixEmpty(value)==null) + if (Util.fixEmpty(value) == null) return FormValidation.ok(); - + try { checkName(value); return FormValidation.ok(); @@ -341,22 +342,22 @@ public FormValidation doCheckName(@QueryParameter String value) throws IOExcepti return FormValidation.error(e.getMessage()); } } - + /** * Accepts submission from the configuration page. */ @POST - public synchronized HttpResponse doConfigSubmit( StaplerRequest req) throws IOException, ServletException, FormException { + public synchronized HttpResponse doConfigSubmit(StaplerRequest req) throws IOException, ServletException, FormException { BulkChange bc = new BulkChange(MONITORS_OWNER); try { Jenkins.get().checkPermission(Jenkins.MANAGE); - monitors.rebuild(req,req.getSubmittedForm(),getNodeMonitorDescriptors()); + monitors.rebuild(req, req.getSubmittedForm(), getNodeMonitorDescriptors()); // add in the rest of instances are ignored instances for (Descriptor d : NodeMonitor.all()) - if(monitors.get(d)==null) { + if (monitors.get(d) == null) { NodeMonitor i = createDefaultInstance(d, true); - if(i!=null) + if (i != null) monitors.add(i); } @@ -375,7 +376,7 @@ public synchronized HttpResponse doConfigSubmit( StaplerRequest req) throws IOEx * {@link NodeMonitor}s are persisted in this file. */ private static XmlFile getConfigFile() { - return new XmlFile(new File(Jenkins.get().getRootDir(),"nodeMonitors.xml")); + return new XmlFile(new File(Jenkins.get().getRootDir(), "nodeMonitors.xml")); } public Api getApi() { @@ -409,7 +410,7 @@ public AutoCompletionCandidates doAutoCompleteCopyNewItemFrom(@QueryParameter fi */ public static void initialize() {} - @Initializer(after= JOB_CONFIG_ADAPTED) + @Initializer(after = JOB_CONFIG_ADAPTED) public static void init() { // start monitoring nodes, although there's no hurry. Timer.get().schedule(new SafeTimerTask() { @@ -439,14 +440,14 @@ public static List getComputerNames() { static { try { - DescribableList> r + DescribableList> r = new DescribableList<>(Saveable.NOOP); // load persisted monitors XmlFile xf = getConfigFile(); - if(xf.exists()) { - DescribableList> persisted = - (DescribableList>) xf.read(); + if (xf.exists()) { + DescribableList> persisted = + (DescribableList>) xf.read(); List sanitized = new ArrayList<>(); for (NodeMonitor nm : persisted) { try { @@ -461,9 +462,9 @@ public static List getComputerNames() { // if we have any new monitors, let's add them for (Descriptor d : NodeMonitor.all()) - if(r.get(d)==null) { - NodeMonitor i = createDefaultInstance(d,false); - if(i!=null) + if (r.get(d) == null) { + NodeMonitor i = createDefaultInstance(d, false); + if (i != null) r.add(i); } monitors.replaceBy(r.toList()); @@ -478,7 +479,7 @@ private static NodeMonitor createDefaultInstance(Descriptor d, bool nm.setIgnored(ignored); return nm; } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { - LOGGER.log(Level.SEVERE, "Failed to instantiate "+d.clazz,e); + LOGGER.log(Level.SEVERE, "Failed to instantiate " + d.clazz, e); } return null; } diff --git a/core/src/main/java/hudson/model/DependencyGraph.java b/core/src/main/java/hudson/model/DependencyGraph.java index 79c8ed7fbf9b8..3788e2aefddca 100644 --- a/core/src/main/java/hudson/model/DependencyGraph.java +++ b/core/src/main/java/hudson/model/DependencyGraph.java @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.security.ACL; @@ -72,20 +73,20 @@ public class DependencyGraph implements Comparator { private boolean built; - private Comparator> topologicalOrder; - private List> topologicallySorted; + private Comparator> topologicalOrder; + private List> topologicallySorted; /** * Builds the dependency graph. */ public DependencyGraph() { } - + public void build() { // Set full privileges while computing to avoid missing any projects the current user cannot see. - try (ACLContext ctx = ACL.as2(ACL.SYSTEM2)){ + try (ACLContext ctx = ACL.as2(ACL.SYSTEM2)) { this.computationalData = new HashMap<>(); - for( AbstractProject p : Jenkins.get().allItems(AbstractProject.class) ) + for (AbstractProject p : Jenkins.get().allItems(AbstractProject.class)) p.buildDependencyGraph(this); forward = finalize(forward); @@ -119,12 +120,12 @@ protected Collection forward(AbstractProject node) { List> sccs = g.getStronglyConnectedComponents(); - final Map topoOrder = new HashMap<>(); + final Map topoOrder = new HashMap<>(); topologicallySorted = new ArrayList<>(); - int idx=0; + int idx = 0; for (SCC scc : sccs) { for (AbstractProject n : scc) { - topoOrder.put(n,idx++); + topoOrder.put(n, idx++); topologicallySorted.add(n); } } @@ -167,7 +168,7 @@ public T getComputationalData(Class key) { * can be empty but never null. */ public List getDownstream(AbstractProject p) { - return get(forward,p,false); + return get(forward, p, false); } /** @@ -177,12 +178,12 @@ public List getDownstream(AbstractProject p) { * can be empty but never null. */ public List getUpstream(AbstractProject p) { - return get(backward,p,true); + return get(backward, p, true); } private List get(Map> map, AbstractProject src, boolean up) { List v = map.get(src); - if(v==null) return Collections.emptyList(); + if (v == null) return Collections.emptyList(); List result = new ArrayList<>(v.size()); for (DependencyGroup d : v) result.add(up ? d.getUpstreamProject() : d.getDownstreamProject()); return result; @@ -192,19 +193,19 @@ private List get(Map> ma * @since 1.341 */ public List getDownstreamDependencies(AbstractProject p) { - return get(forward,p); + return get(forward, p); } /** * @since 1.341 */ public List getUpstreamDependencies(AbstractProject p) { - return get(backward,p); + return get(backward, p); } private List get(Map> map, AbstractProject src) { List v = map.get(src); - if(v==null) { + if (v == null) { return Collections.emptyList(); } else { List builder = new ArrayList<>(); @@ -221,16 +222,16 @@ private List get(Map> map, Ab */ @Deprecated public void addDependency(AbstractProject upstream, AbstractProject downstream) { - addDependency(new Dependency(upstream,downstream)); + addDependency(new Dependency(upstream, downstream)); } /** * Called during the dependency graph build phase to add a dependency edge. */ public void addDependency(Dependency dep) { - if(built) + if (built) throw new IllegalStateException(); - add(forward,dep.getUpstreamProject(),dep); + add(forward, dep.getUpstreamProject(), dep); add(backward, dep.getDownstreamProject(), dep); } @@ -240,7 +241,7 @@ public void addDependency(Dependency dep) { @Deprecated public void addDependency(AbstractProject upstream, Collection downstream) { for (AbstractProject p : downstream) - addDependency(upstream,p); + addDependency(upstream, p); } /** @@ -249,7 +250,7 @@ public void addDependency(AbstractProject upstream, Collection upstream, AbstractProject downstream) { for (AbstractProject p : upstream) - addDependency(p,downstream); + addDependency(p, downstream); } /** @@ -259,7 +260,7 @@ public void addDependencyDeclarers(AbstractProject upstream, Collection possi for (Object o : possibleDependecyDeclarers) { if (o instanceof DependencyDeclarer) { DependencyDeclarer dd = (DependencyDeclarer) o; - dd.buildDependencyGraph(upstream,this); + dd.buildDependencyGraph(upstream, this); } } } @@ -277,11 +278,11 @@ public boolean hasIndirectDependencies(AbstractProject src, AbstractProject dst) queue.addAll(getDownstream(src)); queue.remove(dst); - while(!queue.isEmpty()) { + while (!queue.isEmpty()) { AbstractProject p = queue.pop(); - if(p==dst) + if (p == dst) return true; - if(visited.add(p)) + if (visited.add(p)) queue.addAll(getDownstream(p)); } @@ -292,14 +293,14 @@ public boolean hasIndirectDependencies(AbstractProject src, AbstractProject dst) * Gets all the direct and indirect upstream dependencies of the given project. */ public Set getTransitiveUpstream(AbstractProject src) { - return getTransitive(backward,src,true); + return getTransitive(backward, src, true); } /** * Gets all the direct and indirect downstream dependencies of the given project. */ public Set getTransitiveDownstream(AbstractProject src) { - return getTransitive(forward,src,false); + return getTransitive(forward, src, false); } private Set getTransitive(Map> direction, AbstractProject src, boolean up) { @@ -308,11 +309,11 @@ private Set getTransitive(Map> map, AbstractProjec private Map> finalize(Map> m) { for (Map.Entry> e : m.entrySet()) { e.getValue().sort(NAME_COMPARATOR); - e.setValue( Collections.unmodifiableList(e.getValue()) ); + e.setValue(Collections.unmodifiableList(e.getValue())); } return Collections.unmodifiableMap(m); } @@ -356,7 +357,7 @@ public int compare(DependencyGroup lhs, DependencyGroup rhs) { */ @Override public int compare(AbstractProject o1, AbstractProject o2) { - return topologicalOrder.compare(o1,o2); + return topologicalOrder.compare(o1, o2); } /** @@ -367,7 +368,7 @@ public int compare(AbstractProject o1, AbstractProject o2) { * * @since 1.521 */ - public List> getTopologicallySorted() { + public List> getTopologicallySorted() { return topologicallySorted; } @@ -413,7 +414,7 @@ public boolean shouldTriggerBuild(AbstractBuild build, TaskListener listener, * Does this method point to itself? */ public boolean pointsItself() { - return upstream==downstream; + return upstream == downstream; } @Override @@ -446,7 +447,7 @@ private static class DependencyGroup { DependencyGroup(Dependency first) { this.upstream = first.getUpstreamProject(); - this.downstream= first.getDownstreamProject(); + this.downstream = first.getDownstreamProject(); group.add(first); } diff --git a/core/src/main/java/hudson/model/Describable.java b/core/src/main/java/hudson/model/Describable.java index ae8103b3cfd91..d770540072335 100644 --- a/core/src/main/java/hudson/model/Describable.java +++ b/core/src/main/java/hudson/model/Describable.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; /** diff --git a/core/src/main/java/hudson/model/Descriptor.java b/core/src/main/java/hudson/model/Descriptor.java index 5b94ff25b1b4b..22f1451c5204b 100644 --- a/core/src/main/java/hudson/model/Descriptor.java +++ b/core/src/main/java/hudson/model/Descriptor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2011, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static hudson.util.QuotedStringTokenizer.quote; @@ -78,6 +79,7 @@ import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; import org.jvnet.tiger_types.Types; import org.kohsuke.stapler.Ancestor; import org.kohsuke.stapler.BindInterceptor; @@ -90,7 +92,6 @@ import org.kohsuke.stapler.WebApp; import org.kohsuke.stapler.jelly.JellyCompatibleFacet; import org.kohsuke.stapler.lang.Klass; -import org.springframework.util.StringUtils; /** * Metadata about a configurable instance. @@ -136,7 +137,7 @@ * {@link Descriptor} defines addition to the standard Java reflection * and provides reflective information about its corresponding {@link Describable}. * These are primarily used by tag libraries to - * keep the Jelly scripts concise. + * keep the Jelly scripts concise. * * @author Kohsuke Kawaguchi * @see Describable @@ -147,12 +148,12 @@ public abstract class Descriptor> implements Saveable, */ public final transient Class clazz; - private final transient Map checkMethods = new ConcurrentHashMap<>(2); + private final transient Map checkMethods = new ConcurrentHashMap<>(2); /** * Lazily computed list of properties on {@link #clazz} and on the descriptor itself. */ - private transient volatile Map propertyTypes,globalPropertyTypes; + private transient volatile Map propertyTypes, globalPropertyTypes; /** * Represents a readable property on {@link Describable}. @@ -170,35 +171,35 @@ public static final class PropertyType { } PropertyType(Field f) { - this(f.getType(),f.getGenericType(),f.toString()); + this(f.getType(), f.getGenericType(), f.toString()); } PropertyType(Method getter) { - this(getter.getReturnType(),getter.getGenericReturnType(),getter.toString()); + this(getter.getReturnType(), getter.getGenericReturnType(), getter.toString()); } public Enum[] getEnumConstants() { - return (Enum[])clazz.getEnumConstants(); + return (Enum[]) clazz.getEnumConstants(); } /** * If the property is a collection/array type, what is an item type? */ public Class getItemType() { - if(itemType==null) + if (itemType == null) itemType = computeItemType(); return itemType; } private Class computeItemType() { - if(clazz.isArray()) { + if (clazz.isArray()) { return clazz.getComponentType(); } - if(Collection.class.isAssignableFrom(clazz)) { + if (Collection.class.isAssignableFrom(clazz)) { Type col = Types.getBaseClass(type, Collection.class); if (col instanceof ParameterizedType) - return Types.erasure(Types.getTypeArgument(col,0)); + return Types.erasure(Types.getTypeArgument(col, 0)); else return Object.class; } @@ -218,8 +219,8 @@ public Descriptor getItemTypeDescriptorOrDie() { throw new AssertionError(clazz + " is not an array/collection type in " + displayName + ". See https://www.jenkins.io/redirect/developer/class-is-missing-descriptor"); } Descriptor d = Jenkins.get().getDescriptor(it); - if (d==null) - throw new AssertionError(it +" is missing its descriptor in "+displayName+". See https://www.jenkins.io/redirect/developer/class-is-missing-descriptor"); + if (d == null) + throw new AssertionError(it + " is missing its descriptor in " + displayName + ". See https://www.jenkins.io/redirect/developer/class-is-missing-descriptor"); return d; } @@ -241,9 +242,9 @@ public List getApplicableItemDescriptors() { /** * Help file redirect, keyed by the field name to the path. * - * @see #getHelpFile(String) + * @see #getHelpFile(String) */ - private final transient Map helpRedirect = new HashMap<>(2); + private final transient Map helpRedirect = new HashMap<>(2); private static class HelpRedirect { private final Class owner; @@ -267,8 +268,8 @@ private String resolve() { * (this hack is needed since derived types can't call "getClass()" to refer to itself. */ protected Descriptor(Class clazz) { - if (clazz==self()) - clazz = (Class)getClass(); + if (clazz == self()) + clazz = (Class) getClass(); this.clazz = clazz; // doing this turns out to be very error prone, // as field initializers in derived types will override values. @@ -279,13 +280,13 @@ protected Descriptor(Class clazz) { * Infers the type of the corresponding {@link Describable} from the outer class. * This version works when you follow the common convention, where a descriptor * is written as the static nested class of the describable class. - * + * * @since 1.278 */ protected Descriptor() { - this.clazz = (Class)getClass().getEnclosingClass(); - if(clazz==null) - throw new AssertionError(getClass()+" doesn't have an outer class. Use the constructor that takes the Class object explicitly."); + this.clazz = (Class) getClass().getEnclosingClass(); + if (clazz == null) + throw new AssertionError(getClass() + " doesn't have an outer class. Use the constructor that takes the Class object explicitly."); // detect an type error Type bt = Types.getBaseClass(getClass(), Descriptor.class); @@ -293,19 +294,19 @@ protected Descriptor() { ParameterizedType pt = (ParameterizedType) bt; // this 't' is the closest approximation of T of Descriptor. Class t = Types.erasure(pt.getActualTypeArguments()[0]); - if(!t.isAssignableFrom(clazz)) - throw new AssertionError("Outer class "+clazz+" of "+getClass()+" is not assignable to "+t+". Perhaps wrong outer class?"); + if (!t.isAssignableFrom(clazz)) + throw new AssertionError("Outer class " + clazz + " of " + getClass() + " is not assignable to " + t + ". Perhaps wrong outer class?"); } // detect a type error. this Descriptor is supposed to be returned from getDescriptor(), so make sure its type match up. // this prevents a bug like http://www.nabble.com/Creating-a-new-parameter-Type-%3A-Masked-Parameter-td24786554.html try { Method getd = clazz.getMethod("getDescriptor"); - if(!getd.getReturnType().isAssignableFrom(getClass())) { - throw new AssertionError(getClass()+" must be assignable to "+getd.getReturnType()); + if (!getd.getReturnType().isAssignableFrom(getClass())) { + throw new AssertionError(getClass() + " must be assignable to " + getd.getReturnType()); } } catch (NoSuchMethodException e) { - throw new AssertionError(getClass()+" is missing getDescriptor method.", e); + throw new AssertionError(getClass() + " is missing getDescriptor method.", e); } } @@ -335,7 +336,7 @@ public String getDisplayName() { * * @return * Stick to valid Java identifier character, plus '.', which had to be allowed for historical reasons. - * + * * @since 1.391 */ public String getId() { @@ -353,7 +354,7 @@ public String getId() { public Class getT() { Type subTyping = Types.getBaseClass(getClass(), Descriptor.class); if (!(subTyping instanceof ParameterizedType)) { - throw new IllegalStateException(getClass()+" doesn't extend Descriptor with a type parameter."); + throw new IllegalStateException(getClass() + " doesn't extend Descriptor with a type parameter."); } return Types.erasure(Types.getTypeArgument(subTyping, 0)); } @@ -363,7 +364,7 @@ public Class getT() { * Since {@link Jenkins} is a {@link DescriptorByNameOwner}, there's always one such ancestor to any request. */ public String getDescriptorUrl() { - return "descriptorByName/"+getId(); + return "descriptorByName/" + getId(); } /** @@ -371,7 +372,7 @@ public String getDescriptorUrl() { * @since 1.406 */ public final String getDescriptorFullUrl() { - return getCurrentDescriptorByNameUrl()+'/'+getDescriptorUrl(); + return getCurrentDescriptorByNameUrl() + '/' + getDescriptorUrl(); } /** @@ -382,7 +383,7 @@ public static String getCurrentDescriptorByNameUrl() { // this override allows RenderOnDemandClosure to preserve the proper value Object url = req.getAttribute("currentDescriptorByNameUrl"); - if (url!=null) return url.toString(); + if (url != null) return url.toString(); Ancestor a = req.findAncestor(DescriptorByNameOwner.class); return a.getUrl(); @@ -405,9 +406,9 @@ public String getCheckUrl(String fieldName) { */ public CheckMethod getCheckMethod(String fieldName) { CheckMethod method = checkMethods.get(fieldName); - if(method==null) { - method = new CheckMethod(this,fieldName); - checkMethods.put(fieldName,method); + if (method == null) { + method = new CheckMethod(this, fieldName); + checkMethods.put(fieldName, method); } return method; @@ -418,11 +419,11 @@ public CheckMethod getCheckMethod(String fieldName) { * and sets that as the 'fillDependsOn' attribute. Also computes the URL of the doFillXyzItems and * sets that as the 'fillUrl' attribute. */ - public void calcFillSettings(String field, Map attributes) { + public void calcFillSettings(String field, Map attributes) { String capitalizedFieldName = StringUtils.capitalize(field); String methodName = "doFill" + capitalizedFieldName + "Items"; Method method = ReflectionUtils.getPublicMethodNamed(getClass(), methodName); - if(method==null) + if (method == null) throw new IllegalStateException(String.format("%s doesn't have the %s method for filling a drop-down list", getClass(), methodName)); // build query parameter line by figuring out what should be submitted @@ -436,23 +437,23 @@ public void calcFillSettings(String field, Map attributes) { private List buildFillDependencies(Method method, List depends) { for (Parameter p : ReflectionUtils.getParameters(method)) { QueryParameter qp = p.annotation(QueryParameter.class); - if (qp!=null) { + if (qp != null) { String name = qp.value(); - if (name.length()==0) name = p.name(); - if (name==null || name.length()==0) + if (name.length() == 0) name = p.name(); + if (name == null || name.length() == 0) continue; // unknown parameter name. we'll report the error when the form is submitted. RelativePath rp = p.annotation(RelativePath.class); - if (rp!=null) - name = rp.value()+'/'+name; + if (rp != null) + name = rp.value() + '/' + name; depends.add(name); continue; } Method m = ReflectionUtils.getPublicMethodNamed(p.type(), "fromStapler"); - if (m!=null) - buildFillDependencies(m,depends); + if (m != null) + buildFillDependencies(m, depends); } return depends; } @@ -460,11 +461,11 @@ private List buildFillDependencies(Method method, List depends) /** * Computes the auto-completion setting */ - public void calcAutoCompleteSettings(String field, Map attributes) { + public void calcAutoCompleteSettings(String field, Map attributes) { String capitalizedFieldName = StringUtils.capitalize(field); String methodName = "doAutoComplete" + capitalizedFieldName; Method method = ReflectionUtils.getPublicMethodNamed(getClass(), methodName); - if(method==null) + if (method == null) return; // no auto-completion attributes.put("autoCompleteUrl", String.format("%s/%s/autoComplete%s", getCurrentDescriptorByNameUrl(), getDescriptorUrl(), capitalizedFieldName)); @@ -475,7 +476,7 @@ public void calcAutoCompleteSettings(String field, Map attributes */ public @CheckForNull PropertyType getPropertyType(@NonNull Object instance, @NonNull String field) { // in global.jelly, instance==descriptor - return instance==this ? getGlobalPropertyType(field) : getPropertyType(field); + return instance == this ? getGlobalPropertyType(field) : getPropertyType(field); } /** @@ -498,7 +499,7 @@ public void calcAutoCompleteSettings(String field, Map attributes * Obtains the property type of the given field of {@link #clazz} */ public PropertyType getPropertyType(String field) { - if(propertyTypes==null) + if (propertyTypes == null) propertyTypes = buildPropertyTypes(clazz); return propertyTypes.get(field); } @@ -507,7 +508,7 @@ public PropertyType getPropertyType(String field) { * Obtains the property type of the given field of this descriptor. */ public PropertyType getGlobalPropertyType(String field) { - if(globalPropertyTypes==null) + if (globalPropertyTypes == null) globalPropertyTypes = buildPropertyTypes(getClass()); return globalPropertyTypes.get(field); } @@ -518,11 +519,11 @@ public PropertyType getGlobalPropertyType(String field) { private Map buildPropertyTypes(Class clazz) { Map r = new HashMap<>(); for (Field f : clazz.getFields()) - r.put(f.getName(),new PropertyType(f)); + r.put(f.getName(), new PropertyType(f)); for (Method m : clazz.getMethods()) - if(m.getName().startsWith("get")) - r.put(Introspector.decapitalize(m.getName().substring(3)),new PropertyType(m)); + if (m.getName().startsWith("get")) + r.put(Introspector.decapitalize(m.getName().substring(3)), new PropertyType(m)); return r; } @@ -531,17 +532,17 @@ private Map buildPropertyTypes(Class clazz) { * Gets the class name nicely escaped to be usable as a key in the structured form submission. */ public final String getJsonSafeClassName() { - return getId().replace('.','-'); + return getId().replace('.', '-'); } /** * @deprecated * Implement {@link #newInstance(StaplerRequest, JSONObject)} method instead. - * Deprecated as of 1.145. + * Deprecated as of 1.145. */ @Deprecated public T newInstance(StaplerRequest req) throws FormException { - throw new UnsupportedOperationException(getClass()+" should implement newInstance(StaplerRequest,JSONObject)"); + throw new UnsupportedOperationException(getClass() + " should implement newInstance(StaplerRequest,JSONObject)"); } /** @@ -582,12 +583,12 @@ public T newInstance(@Nullable StaplerRequest req, @NonNull JSONObject formData) try { Method m = getClass().getMethod("newInstance", StaplerRequest.class); - if(!Modifier.isAbstract(m.getDeclaringClass().getModifiers())) { + if (!Modifier.isAbstract(m.getDeclaringClass().getModifiers())) { // this class overrides newInstance(StaplerRequest). // maintain the backward compatible behavior return verifyNewInstance(newInstance(req)); } else { - if (req==null) { + if (req == null) { // yes, req is supposed to be always non-null, but see the note above return verifyNewInstance(clazz.getDeclaredConstructor().newInstance()); } @@ -609,7 +610,7 @@ public T newInstance(@Nullable StaplerRequest req, @NonNull JSONObject formData) } } } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException | RuntimeException e) { - throw new LinkageError("Failed to instantiate "+clazz+" from "+RedactSecretJsonInErrorMessageSanitizer.INSTANCE.sanitize(formData),e); + throw new LinkageError("Failed to instantiate " + clazz + " from " + RedactSecretJsonInErrorMessageSanitizer.INSTANCE.sanitize(formData), e); } } @@ -624,7 +625,7 @@ public T newInstance(@Nullable StaplerRequest req, @NonNull JSONObject formData) private static class NewInstanceBindInterceptor extends BindInterceptor { private final BindInterceptor oldInterceptor; - private final IdentityHashMap processed = new IdentityHashMap<>(); + private final IdentityHashMap processed = new IdentityHashMap<>(); NewInstanceBindInterceptor(BindInterceptor oldInterceptor) { LOGGER.log(Level.FINER, "new interceptor delegating to {0}", oldInterceptor); @@ -696,9 +697,9 @@ public Object onConvert(Type targetType, Class targetTypeErasure, Object jsonSou * See http://hudson.361315.n4.nabble.com/Help-Hint-needed-Post-build-action-doesn-t-stay-activated-td2308833.html */ private T verifyNewInstance(T t) { - if (t!=null && t.getDescriptor()!=this) { + if (t != null && t.getDescriptor() != this) { // TODO: should this be a fatal error? - LOGGER.warning("Father of "+ t+" and its getDescriptor() points to two different instances. Probably misplaced @Extension. See http://hudson.361315.n4.nabble.com/Help-Hint-needed-Post-build-action-doesn-t-stay-activated-td2308833.html"); + LOGGER.warning("Father of " + t + " and its getDescriptor() points to two different instances. Probably misplaced @Extension. See http://hudson.361315.n4.nabble.com/Help-Hint-needed-Post-build-action-doesn-t-stay-activated-td2308833.html"); } return t; } @@ -741,48 +742,48 @@ public String getHelpFile() { * locale variations. */ public String getHelpFile(final String fieldName) { - return getHelpFile(getKlass(),fieldName); + return getHelpFile(getKlass(), fieldName); } public String getHelpFile(Klass clazz, String fieldName) { HelpRedirect r = helpRedirect.get(fieldName); - if (r!=null) return r.resolve(); + if (r != null) return r.resolve(); for (Klass c : clazz.getAncestors()) { String page = "/descriptor/" + getId() + "/help"; String suffix; - if(fieldName==null) { - suffix=""; + if (fieldName == null) { + suffix = ""; } else { - page += '/'+fieldName; - suffix='-'+fieldName; + page += '/' + fieldName; + suffix = '-' + fieldName; } try { - if(Stapler.getCurrentRequest().getView(c,"help"+suffix)!=null) + if (Stapler.getCurrentRequest().getView(c, "help" + suffix) != null) return page; } catch (IOException e) { throw new Error(e); } - if(getStaticHelpUrl(c, suffix) !=null) return page; + if (getStaticHelpUrl(c, suffix) != null) return page; } return null; } - + /** * Tells Jenkins that the help file for the field 'fieldName' is defined in the help file for * the 'fieldNameToRedirectTo' in the 'owner' class. * @since 1.425 */ protected void addHelpFileRedirect(String fieldName, Class owner, String fieldNameToRedirectTo) { - helpRedirect.put(fieldName, new HelpRedirect(owner,fieldNameToRedirectTo)); + helpRedirect.put(fieldName, new HelpRedirect(owner, fieldNameToRedirectTo)); } /** * Checks if the given object is created from this {@link Descriptor}. */ - public final boolean isInstance( T instance ) { + public final boolean isInstance(T instance) { return clazz.isInstance(instance); } @@ -798,7 +799,7 @@ public final boolean isSubTypeOf(Class type) { * As of 1.239, use {@link #configure(StaplerRequest, JSONObject)}. */ @Deprecated - public boolean configure( StaplerRequest req ) throws FormException { + public boolean configure(StaplerRequest req) throws FormException { return true; } @@ -813,7 +814,7 @@ public boolean configure( StaplerRequest req ) throws FormException { * @return false * to keep the client in the same config page. */ - public boolean configure( StaplerRequest req, JSONObject json ) throws FormException { + public boolean configure(StaplerRequest req, JSONObject json) throws FormException { // compatibility return configure(req); } @@ -852,15 +853,15 @@ Permission getRequiredGlobalConfigPagePermission() { } private String getViewPage(Class clazz, String pageName, String defaultValue) { - return getViewPage(clazz,Collections.singleton(pageName),defaultValue); + return getViewPage(clazz, Collections.singleton(pageName), defaultValue); } private String getViewPage(Class clazz, Collection pageNames, String defaultValue) { - while(clazz!=Object.class && clazz!=null) { + while (clazz != Object.class && clazz != null) { for (String pageName : pageNames) { String name = clazz.getName().replace('.', '/').replace('$', '/') + "/" + pageName; - if(clazz.getClassLoader().getResource(name)!=null) - return '/'+name; + if (clazz.getClassLoader().getResource(name) != null) + return '/' + name; } clazz = clazz.getSuperclass(); } @@ -873,7 +874,7 @@ protected final String getViewPage(Class clazz, String pageName) { // it doesn't exist. // Or this error is fatal, in which case we want the developer to see what page he's missing. // so we put the page name. - return getViewPage(clazz,pageName,pageName); + return getViewPage(clazz, pageName, pageName); } protected List getPossibleViewNames(String baseName) { @@ -882,7 +883,7 @@ protected List getPossibleViewNames(String baseName) { if (f instanceof JellyCompatibleFacet) { JellyCompatibleFacet jcf = (JellyCompatibleFacet) f; for (String ext : jcf.getScriptExtensions()) - names.add(baseName +ext); + names.add(baseName + ext); } } return names; @@ -894,12 +895,12 @@ protected List getPossibleViewNames(String baseName) { */ @Override public synchronized void save() { - if(BulkChange.contains(this)) return; + if (BulkChange.contains(this)) return; try { getConfigFile().write(this); SaveableListener.fireOnChange(this, getConfigFile()); } catch (IOException e) { - LOGGER.log(Level.WARNING, "Failed to save "+getConfigFile(),e); + LOGGER.log(Level.WARNING, "Failed to save " + getConfigFile(), e); } } @@ -913,18 +914,18 @@ public synchronized void save() { */ public synchronized void load() { XmlFile file = getConfigFile(); - if(!file.exists()) + if (!file.exists()) return; try { file.unmarshal(this); } catch (IOException e) { - LOGGER.log(Level.WARNING, "Failed to load "+file, e); + LOGGER.log(Level.WARNING, "Failed to load " + file, e); } } protected XmlFile getConfigFile() { - return new XmlFile(new File(Jenkins.get().getRootDir(),getId()+".xml")); + return new XmlFile(new File(Jenkins.get().getRootDir(), getId() + ".xml")); } /** @@ -942,32 +943,32 @@ protected PluginWrapper getPlugin() { */ public void doHelp(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { String path = req.getRestOfPath(); - if(path.contains("..")) throw new ServletException("Illegal path: "+path); + if (path.contains("..")) throw new ServletException("Illegal path: " + path); - path = path.replace('/','-'); + path = path.replace('/', '-'); PluginWrapper pw = getPlugin(); - if (pw!=null) { - rsp.setHeader("X-Plugin-Short-Name",pw.getShortName()); - rsp.setHeader("X-Plugin-Long-Name",pw.getLongName()); + if (pw != null) { + rsp.setHeader("X-Plugin-Short-Name", pw.getShortName()); + rsp.setHeader("X-Plugin-Long-Name", pw.getLongName()); rsp.setHeader("X-Plugin-From", Messages.Descriptor_From( - pw.getLongName().replace("Hudson","Jenkins").replace("hudson","jenkins"), pw.getUrl())); + pw.getLongName().replace("Hudson", "Jenkins").replace("hudson", "jenkins"), pw.getUrl())); } - for (Klass c= getKlass(); c!=null; c=c.getSuperClass()) { - RequestDispatcher rd = Stapler.getCurrentRequest().getView(c, "help"+path); - if(rd!=null) {// template based help page - rd.forward(req,rsp); + for (Klass c = getKlass(); c != null; c = c.getSuperClass()) { + RequestDispatcher rd = Stapler.getCurrentRequest().getView(c, "help" + path); + if (rd != null) { // template based help page + rd.forward(req, rsp); return; } URL url = getStaticHelpUrl(c, path); - if(url!=null) { + if (url != null) { // TODO: generalize macro expansion and perhaps even support JEXL rsp.setContentType("text/html;charset=UTF-8"); try (InputStream in = url.openStream()) { String literal = IOUtils.toString(in, StandardCharsets.UTF_8); - rsp.getWriter().println(Util.replaceMacro(literal, Collections.singletonMap("rootURL",req.getContextPath()))); + rsp.getWriter().println(Util.replaceMacro(literal, Collections.singletonMap("rootURL", req.getContextPath()))); } return; } @@ -978,15 +979,15 @@ public void doHelp(StaplerRequest req, StaplerResponse rsp) throws IOException, private URL getStaticHelpUrl(Klass c, String suffix) { Locale locale = Stapler.getCurrentRequest().getLocale(); - String base = "help"+suffix; + String base = "help" + suffix; URL url; url = c.getResource(base + '_' + locale.getLanguage() + '_' + locale.getCountry() + '_' + locale.getVariant() + ".html"); - if(url!=null) return url; + if (url != null) return url; url = c.getResource(base + '_' + locale.getLanguage() + '_' + locale.getCountry() + ".html"); - if(url!=null) return url; + if (url != null) return url; url = c.getResource(base + '_' + locale.getLanguage() + ".html"); - if(url!=null) return url; + if (url != null) return url; // default return c.getResource(base + ".html"); @@ -999,17 +1000,17 @@ private URL getStaticHelpUrl(Klass c, String suffix) { // to work around warning when creating a generic array type - public static T[] toArray( T... values ) { + public static T[] toArray(T... values) { return values; } - public static List toList( T... values ) { + public static List toList(T... values) { return new ArrayList<>(Arrays.asList(values)); } public static > - Map,T> toMap(Iterable describables) { - Map,T> m = new LinkedHashMap<>(); + Map, T> toMap(Iterable describables) { + Map, T> m = new LinkedHashMap<>(); for (T d : describables) { Descriptor descriptor; try { @@ -1041,7 +1042,7 @@ Map,T> toMap(Iterable describables) { List newInstancesFromHeteroList(StaplerRequest req, JSONObject formData, String key, Collection> descriptors) throws FormException { - return newInstancesFromHeteroList(req,formData.get(key),descriptors); + return newInstancesFromHeteroList(req, formData.get(key), descriptors); } public static > @@ -1050,9 +1051,9 @@ List newInstancesFromHeteroList(StaplerRequest req, Object formData, List items = new ArrayList<>(); - if (formData!=null) { + if (formData != null) { for (Object o : JSONArray.fromObject(formData)) { - JSONObject jo = (JSONObject)o; + JSONObject jo = (JSONObject) o; Descriptor d = null; // 'kind' and '$class' are mutually exclusive (see class-entry.jelly), but to be more lenient on the reader side, // we check them both anyway. 'kind' (which maps to ID) is more unique than '$class', which can have multiple matching @@ -1096,7 +1097,7 @@ List newInstancesFromHeteroList(StaplerRequest req, Object formData, */ public static @CheckForNull T findById(Collection list, String id) { for (T d : list) { - if(d.getId().equals(id)) + if (d.getId().equals(id)) return d; } return null; @@ -1108,7 +1109,7 @@ List newInstancesFromHeteroList(StaplerRequest req, Object formData, */ private static @CheckForNull T findByClassName(Collection list, String className) { for (T d : list) { - if(d.getClass().getName().equals(className)) + if (d.getClass().getName().equals(className)) return d; } return null; @@ -1121,7 +1122,7 @@ List newInstancesFromHeteroList(StaplerRequest req, Object formData, */ public static @CheckForNull T findByDescribableClassName(Collection list, String className) { for (T d : list) { - if(d.clazz.getName().equals(className)) + if (d.clazz.getName().equals(className)) return d; } return null; @@ -1145,7 +1146,7 @@ List newInstancesFromHeteroList(StaplerRequest req, Object formData, */ @Deprecated public static @CheckForNull Descriptor find(String className) { - return find(ExtensionList.lookup(Descriptor.class),className); + return find(ExtensionList.lookup(Descriptor.class), className); } public static final class FormException extends Exception implements HttpResponse { @@ -1176,11 +1177,11 @@ public String getFormField() { @Override public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException { if (FormApply.isApply(req)) { - FormApply.applyResponse("notificationBar.show(" + quote(getMessage())+ ",notificationBar.ERROR)") + FormApply.applyResponse("notificationBar.show(" + quote(getMessage()) + ",notificationBar.ERROR)") .generateResponse(req, rsp, node); } else { // for now, we can't really use the field name that caused the problem. - new Failure(getMessage()).generateResponse(req,rsp,node,getCause()); + new Failure(getMessage()).generateResponse(req, rsp, node, getCause()); } } } diff --git a/core/src/main/java/hudson/model/DescriptorByNameOwner.java b/core/src/main/java/hudson/model/DescriptorByNameOwner.java index e36f61df4d003..6dab3573d95a6 100644 --- a/core/src/main/java/hudson/model/DescriptorByNameOwner.java +++ b/core/src/main/java/hudson/model/DescriptorByNameOwner.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import jenkins.model.Jenkins; diff --git a/core/src/main/java/hudson/model/DirectlyModifiableView.java b/core/src/main/java/hudson/model/DirectlyModifiableView.java index ffb0b1b2a7b2e..61362272c248c 100644 --- a/core/src/main/java/hudson/model/DirectlyModifiableView.java +++ b/core/src/main/java/hudson/model/DirectlyModifiableView.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; diff --git a/core/src/main/java/hudson/model/DirectoryBrowserSupport.java b/core/src/main/java/hudson/model/DirectoryBrowserSupport.java index 5ed6f22609058..1df1e1ab69a8a 100644 --- a/core/src/main/java/hudson/model/DirectoryBrowserSupport.java +++ b/core/src/main/java/hudson/model/DirectoryBrowserSupport.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, Erik Ramfelt - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -74,7 +75,7 @@ * *

      * This object can be used in a mix-in style to provide a directory browsing capability - * to a {@link ModelObject}. + * to a {@link ModelObject}. * * @author Kohsuke Kawaguchi */ @@ -84,12 +85,12 @@ public final class DirectoryBrowserSupport implements HttpResponse { public static boolean ALLOW_SYMLINK_ESCAPE = SystemProperties.getBoolean(DirectoryBrowserSupport.class.getName() + ".allowSymlinkEscape"); /** - * Escape hatch for the protection against SECURITY-2481. If enabled, the absolute paths on Windows will be allowed. + * Escape hatch for the protection against SECURITY-2481. If enabled, the absolute paths on Windows will be allowed. */ static final String ALLOW_ABSOLUTE_PATH_PROPERTY_NAME = DirectoryBrowserSupport.class.getName() + ".allowAbsolutePath"; public final ModelObject owner; - + public final String title; private final VirtualFile base; @@ -120,7 +121,7 @@ public DirectoryBrowserSupport(ModelObject owner, String title) { * @param base * The root of the directory that's bound to URL. * @param title - * Used in the HTML caption. + * Used in the HTML caption. * @param icon * The icon file name, like "folder.gif" * @param serveDirIndex @@ -160,9 +161,9 @@ public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object nod } try { - serveFile(req,rsp,base,icon,serveDirIndex); + serveFile(req, rsp, base, icon, serveDirIndex); } catch (InterruptedException e) { - throw new IOException("interrupted",e); + throw new IOException("interrupted", e); } } @@ -195,15 +196,15 @@ public void serveFile(StaplerRequest req, StaplerResponse rsp, FilePath root, St private void serveFile(StaplerRequest req, StaplerResponse rsp, VirtualFile root, String icon, boolean serveDirIndex) throws IOException, ServletException, InterruptedException { // handle form submission String pattern = req.getParameter("pattern"); - if(pattern==null) + if (pattern == null) pattern = req.getParameter("path"); // compatibility with Hudson<1.129 - if(pattern!=null && Util.isSafeToRedirectTo(pattern)) {// avoid open redirect + if (pattern != null && Util.isSafeToRedirectTo(pattern)) { // avoid open redirect rsp.sendRedirect2(pattern); return; } String path = getPath(req); - if(path.replace('\\', '/').contains("/../")) { + if (path.replace('\\', '/').contains("/../")) { // don't serve anything other than files in the artifacts dir rsp.sendError(HttpServletResponse.SC_BAD_REQUEST); return; @@ -213,38 +214,38 @@ private void serveFile(StaplerRequest req, StaplerResponse rsp, VirtualFile root // and the GLOB portion "**/*.xml" (the rest) StringBuilder _base = new StringBuilder(); StringBuilder _rest = new StringBuilder(); - int restSize=-1; // number of ".." needed to go back to the 'base' level. - boolean zip=false; // if we are asked to serve a zip file bundle + int restSize = -1; // number of ".." needed to go back to the 'base' level. + boolean zip = false; // if we are asked to serve a zip file bundle boolean plain = false; // if asked to serve a plain text directory listing { boolean inBase = true; - StringTokenizer pathTokens = new StringTokenizer(path,"/"); - while(pathTokens.hasMoreTokens()) { + StringTokenizer pathTokens = new StringTokenizer(path, "/"); + while (pathTokens.hasMoreTokens()) { String pathElement = pathTokens.nextToken(); // Treat * and ? as wildcard unless they match a literal filename - if((pathElement.contains("?") || pathElement.contains("*")) + if ((pathElement.contains("?") || pathElement.contains("*")) && inBase && !root.child((_base.length() > 0 ? _base + "/" : "") + pathElement).exists()) inBase = false; - if(pathElement.equals("*zip*")) { + if (pathElement.equals("*zip*")) { // the expected syntax is foo/bar/*zip*/bar.zip // the last 'bar.zip' portion is to causes browses to set a good default file name. // so the 'rest' portion ends here. - zip=true; + zip = true; break; } - if(pathElement.equals("*plain*")) { + if (pathElement.equals("*plain*")) { plain = true; break; } - StringBuilder sb = inBase?_base:_rest; - if(sb.length()>0) sb.append('/'); + StringBuilder sb = inBase ? _base : _rest; + if (sb.length() > 0) sb.append('/'); sb.append(pathElement); - if(!inBase) + if (!inBase) restSize++; } } - restSize = Math.max(restSize,0); + restSize = Math.max(restSize, 0); String base = _base.toString(); String rest = _rest.toString(); @@ -268,8 +269,8 @@ private void serveFile(StaplerRequest req, StaplerResponse rsp, VirtualFile root rsp.sendError(HttpServletResponse.SC_NOT_FOUND); return; } - if(baseFile.isDirectory()) { - if(zip) { + if (baseFile.isDirectory()) { + if (zip) { rsp.setContentType("application/zip"); String includes, prefix; if (StringUtils.isBlank(rest)) { @@ -298,10 +299,10 @@ private void serveFile(StaplerRequest req, StaplerResponse rsp, VirtualFile root return; } - if(rest.length()==0) { + if (rest.length() == 0) { // if the target page to be displayed is a directory and the path doesn't end with '/', redirect StringBuffer reqUrl = req.getRequestURL(); - if(reqUrl.charAt(reqUrl.length()-1)!='/') { + if (reqUrl.charAt(reqUrl.length() - 1) != '/') { rsp.sendRedirect2(reqUrl.append('/').toString()); return; } @@ -310,27 +311,27 @@ private void serveFile(StaplerRequest req, StaplerResponse rsp, VirtualFile root List> glob = null; boolean patternUsed = rest.length() > 0; boolean containsSymlink = false; - if(patternUsed) { + if (patternUsed) { // the rest is Ant glob pattern glob = patternScan(baseFile, rest, createBackRef(restSize)); } else - if(serveDirIndex) { + if (serveDirIndex) { // serve directory index glob = baseFile.run(new BuildChildPaths(root, baseFile, req.getLocale())); containsSymlink = baseFile.containsSymLinkChild(getNoFollowLinks()); } - if(glob!=null) { + if (glob != null) { // serve glob req.setAttribute("it", this); - List parentPaths = buildParentPath(base,restSize); - req.setAttribute("parentPath",parentPaths); + List parentPaths = buildParentPath(base, restSize); + req.setAttribute("parentPath", parentPaths); req.setAttribute("backPath", createBackRef(restSize)); - req.setAttribute("topPath", createBackRef(parentPaths.size()+restSize)); + req.setAttribute("topPath", createBackRef(parentPaths.size() + restSize)); req.setAttribute("files", glob); req.setAttribute("icon", icon); req.setAttribute("path", path); - req.setAttribute("pattern",rest); + req.setAttribute("pattern", rest); req.setAttribute("dir", baseFile); req.setAttribute("showSymlinkWarning", containsSymlink); if (ResourceDomainConfiguration.isResourceRequest(req)) { @@ -347,14 +348,14 @@ private void serveFile(StaplerRequest req, StaplerResponse rsp, VirtualFile root } //serve a single file - if(!baseFile.exists()) { + if (!baseFile.exists()) { rsp.sendError(HttpServletResponse.SC_NOT_FOUND); return; } boolean view = rest.equals("*view*"); - if(rest.equals("*fingerprint*")) { + if (rest.equals("*fingerprint*")) { try (InputStream fingerprintInput = baseFile.open()) { rsp.forward(Jenkins.get().getFingerprint(Util.getDigestOf(fingerprintInput)), "/", req); } @@ -372,8 +373,8 @@ private void serveFile(StaplerRequest req, StaplerResponse rsp, VirtualFile root long lastModified = baseFile.lastModified(); long length = baseFile.length(); - if(LOGGER.isLoggable(Level.FINE)) - LOGGER.fine("Serving "+baseFile+" with lastModified=" + lastModified + ", length=" + length); + if (LOGGER.isLoggable(Level.FINE)) + LOGGER.fine("Serving " + baseFile + " with lastModified=" + lastModified + ", length=" + length); if (view) { InputStream in; @@ -423,13 +424,13 @@ private static final class IsAbsolute extends MasterToSlaveCallable> keepReadabilityOnlyOnDescendants(VirtualFile root, boolean patternUsed, List> pathFragmentsList){ + private List> keepReadabilityOnlyOnDescendants(VirtualFile root, boolean patternUsed, List> pathFragmentsList) { Stream> pathFragmentsStream = pathFragmentsList.stream().map((List pathFragments) -> { List mappedFragments = new ArrayList<>(pathFragments.size()); String relativePath = ""; @@ -440,7 +441,7 @@ private List> keepReadabilityOnlyOnDescendants(VirtualFile root, bool } else { relativePath += "/" + current.title; } - + if (!current.isReadable) { if (patternUsed) { // we do not want to leak information about existence of folders / files satisfying the pattern inside that folder @@ -463,15 +464,15 @@ private List> keepReadabilityOnlyOnDescendants(VirtualFile root, bool } return mappedFragments; }); - + if (patternUsed) { pathFragmentsStream = pathFragmentsStream.filter(Objects::nonNull); } - + return pathFragmentsStream.collect(Collectors.toList()); } - private boolean isDescendant(VirtualFile root, String relativePath){ + private boolean isDescendant(VirtualFile root, String relativePath) { try { return ALLOW_SYMLINK_ESCAPE || !root.supportIsDescendant() || root.isDescendant(relativePath); } @@ -482,7 +483,7 @@ private boolean isDescendant(VirtualFile root, String relativePath){ private String getPath(StaplerRequest req) { String path = req.getRestOfPath(); - if(path.length()==0) + if (path.length() == 0) path = "/"; return path; } @@ -495,19 +496,19 @@ private List buildParentPath(String pathList, int restSize) { List r = new ArrayList<>(); StringTokenizer tokens = new StringTokenizer(pathList, "/"); int total = tokens.countTokens(); - int current=1; - while(tokens.hasMoreTokens()) { + int current = 1; + while (tokens.hasMoreTokens()) { String token = tokens.nextToken(); - r.add(new Path(createBackRef(total-current+restSize),token,true,0, true,0)); + r.add(new Path(createBackRef(total - current + restSize), token, true, 0, true, 0)); current++; } return r; } private static String createBackRef(int times) { - if(times==0) return "./"; - StringBuilder buf = new StringBuilder(3*times); - for(int i=0; i nameToVirtualFiles = collectRecursivelyAllLegalChildren(dir); sendZipUsingMap(zos, dir, nameToVirtualFiles); @@ -612,7 +613,7 @@ public static final class Path implements Serializable { * File size, or null if this is not a file. */ private final long size; - + /** * If the current user can read the file. */ @@ -643,7 +644,7 @@ public Path(String href, String title, boolean isFolder, long size, boolean isRe public boolean isFolder() { return isFolder; } - + public boolean isReadable() { return isReadable; } @@ -658,16 +659,16 @@ public String getTitle() { public String getIconName() { if (isReadable) - return isFolder?"folder.png":"text.png"; + return isFolder ? "folder.svg" : "document.svg"; else - return isFolder?"folder-error.png":"text-error.png"; + return isFolder ? "folder-delete.svg" : "document-delete.svg"; } public String getIconClassName() { if (isReadable) - return isFolder?"icon-folder":"icon-text"; + return isFolder ? "icon-folder" : "icon-document"; else - return isFolder?"icon-folder-error":"icon-text-error"; + return isFolder ? "icon-folder-delete" : "icon-document-delete"; } public long getSize() { @@ -697,7 +698,7 @@ public Calendar getLastModifiedAsCalendar() { return cal; } - public static Path createNotReadableVersionOf(Path that){ + public static Path createNotReadableVersionOf(Path that) { return new Path(that.href, that.title, that.isFolder, that.size, false); } @@ -716,15 +717,15 @@ private static final class FileComparator implements Comparator { @Override public int compare(VirtualFile lhs, VirtualFile rhs) { // directories first, files next - int r = dirRank(lhs)-dirRank(rhs); - if(r!=0) return r; + int r = dirRank(lhs) - dirRank(rhs); + if (r != 0) return r; // otherwise alphabetical return this.collator.compare(lhs.getName(), rhs.getName()); } private int dirRank(VirtualFile f) { try { - if(f.isDirectory()) return 0; + if (f.isDirectory()) return 0; else return 1; } catch (IOException ex) { return 0; @@ -732,15 +733,17 @@ private int dirRank(VirtualFile f) { } } - private static final class BuildChildPaths extends MasterToSlaveCallable>,IOException> { + private static final class BuildChildPaths extends MasterToSlaveCallable>, IOException> { private VirtualFile root; private final VirtualFile cur; private final Locale locale; + BuildChildPaths(VirtualFile root, VirtualFile cur, Locale locale) { this.root = root; this.cur = cur; this.locale = locale; } + @Override public List> call() throws IOException { return buildChildPaths(cur, locale); } @@ -750,22 +753,24 @@ private static final class BuildChildPaths extends MasterToSlaveCallable> buildChildPaths(VirtualFile cur, Locale locale) throws IOException { List> r = new ArrayList<>(); VirtualFile[] files = cur.list(getNoFollowLinks()); - Arrays.sort(files,new FileComparator(locale)); - - for( VirtualFile f : files ) { + Arrays.sort(files, new FileComparator(locale)); + + for (VirtualFile f : files) { Path p = new Path(Util.rawEncode(f.getName()), f.getName(), f.isDirectory(), f.length(), f.canRead(), f.lastModified()); - if(!f.isDirectory()) { + if (!f.isDirectory()) { r.add(Collections.singletonList(p)); } else { // find all empty intermediate directory List l = new ArrayList<>(); l.add(p); String relPath = Util.rawEncode(f.getName()); - while(true) { + while (true) { // files that don't start with '.' qualify for 'meaningful files', nor SCM related files List sub = new ArrayList<>(); for (VirtualFile vf : f.list(getNoFollowLinks())) { @@ -774,11 +779,11 @@ private static List> buildChildPaths(VirtualFile cur, Locale locale) sub.add(vf); } } - if (sub.size() !=1 || !sub.get(0).isDirectory()) + if (sub.size() != 1 || !sub.get(0).isDirectory()) break; f = sub.get(0); - relPath += '/'+Util.rawEncode(f.getName()); - l.add(new Path(relPath,f.getName(),true, f.length(), f.canRead(), f.lastModified())); + relPath += '/' + Util.rawEncode(f.getName()); + l.add(new Path(relPath, f.getName(), true, f.length(), f.canRead(), f.lastModified())); } r.add(l); } diff --git a/core/src/main/java/hudson/model/DisplayNameListener.java b/core/src/main/java/hudson/model/DisplayNameListener.java index c8c0cc6d72322..2aee0c035c17b 100644 --- a/core/src/main/java/hudson/model/DisplayNameListener.java +++ b/core/src/main/java/hudson/model/DisplayNameListener.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2011, Yahoo!, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; @@ -41,7 +42,7 @@ public class DisplayNameListener extends ItemListener { private static final Logger LOGGER = Logger.getLogger(DisplayNameListener.class.getName()); /** - * Called after the user has clicked OK in the New Job page when + * Called after the user has clicked OK in the New Job page when * Copy existing job has been selected. * The fields in item will be displayed in when the config page is loaded * displayed. @@ -49,11 +50,11 @@ public class DisplayNameListener extends ItemListener { @Override public void onCopied(Item src, Item item) { // bug 5056825 - Display name field should be cleared when you copy a job within the same folder. - if(item instanceof AbstractItem && src.getParent() == item.getParent()) { - AbstractItem dest = (AbstractItem)item; - try { + if (item instanceof AbstractItem && src.getParent() == item.getParent()) { + AbstractItem dest = (AbstractItem) item; + try { dest.setDisplayName(null); - } catch(IOException ioe) { + } catch (IOException ioe) { LOGGER.log(Level.WARNING, String.format("onCopied():Exception while trying to clear the displayName for Item.name:%s", item.getName()), ioe); } } @@ -70,9 +71,9 @@ public void onCopied(Item src, Item item) { @Override public void onRenamed(Item item, String oldName, String newName) { // bug 5077308 - Display name field should be cleared when you rename a job. - if(item instanceof AbstractItem) { - AbstractItem abstractItem = (AbstractItem)item; - if(oldName.equals(abstractItem.getDisplayName())) { + if (item instanceof AbstractItem) { + AbstractItem abstractItem = (AbstractItem) item; + if (oldName.equals(abstractItem.getDisplayName())) { // the user renamed the job, but the old project name which is shown as the // displayname if no displayname was set, has been set into the displayname field. // This means that the displayname was never set, so we want to set it @@ -81,7 +82,7 @@ public void onRenamed(Item item, String oldName, String newName) { LOGGER.info(String.format("onRenamed():Setting displayname to null for item.name=%s", item.getName())); abstractItem.setDisplayName(null); } - catch(IOException ioe) { + catch (IOException ioe) { LOGGER.log(Level.WARNING, String.format("onRenamed():Exception while trying to clear the displayName for Item.name:%s", item.getName()), ioe); } diff --git a/core/src/main/java/hudson/model/DownloadService.java b/core/src/main/java/hudson/model/DownloadService.java index 92713f0cf9b15..000ef9f48d2f3 100644 --- a/core/src/main/java/hudson/model/DownloadService.java +++ b/core/src/main/java/hudson/model/DownloadService.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static java.util.concurrent.TimeUnit.DAYS; @@ -83,6 +84,7 @@ public class DownloadService { * * @deprecated browser-based download has been disabled */ + @Deprecated public String generateFragment() { return ""; @@ -94,7 +96,7 @@ public String generateFragment() { */ public Downloadable getById(String id) { for (Downloadable d : Downloadable.all()) - if(d.getId().equals(id)) + if (d.getId().equals(id)) return d; return null; } @@ -207,8 +209,8 @@ public static class Downloadable implements ExtensionPoint { private final String id; private final String url; private final long interval; - private volatile long due=0; - private volatile long lastAttempt=Long.MIN_VALUE; + private volatile long due = 0; + private volatile long lastAttempt = Long.MIN_VALUE; /** * Creates a new downloadable. @@ -289,14 +291,14 @@ public String getId() { */ @NonNull public static String idFor(@NonNull Class clazz) { - return clazz.getName().replace('$','.'); + return clazz.getName().replace('$', '.'); } /** * URL to download. */ public String getUrl() { - return Jenkins.get().getUpdateCenter().getDefaultBaseUrl()+"updates/"+url; + return Jenkins.get().getUpdateCenter().getDefaultBaseUrl() + "updates/" + url; } /** @@ -331,18 +333,18 @@ public long getInterval() { * This is where the retrieved file will be stored. */ public TextFile getDataFile() { - return new TextFile(new File(Jenkins.get().getRootDir(),"updates/"+id)); + return new TextFile(new File(Jenkins.get().getRootDir(), "updates/" + id)); } /** * When shall we retrieve this file next time? */ public long getDue() { - if(due==0) + if (due == 0) // if the file doesn't exist, this code should result // in a very small (but >0) due value, which should trigger // the retrieval immediately. - due = getDataFile().file.lastModified()+interval; + due = getDataFile().file.lastModified() + interval; return due; } @@ -352,7 +354,7 @@ public long getDue() { */ public JSONObject getData() throws IOException { TextFile df = getDataFile(); - if(df.exists()) + if (df.exists()) try { return JSONObject.fromObject(df.read()); } catch (JSONException e) { @@ -371,7 +373,7 @@ private FormValidation load(String json, long dataTimestamp) throws IOException TextFile df = getDataFile(); df.write(json); Files.setLastModifiedTime(Util.fileToPath(df.file), FileTime.fromMillis(dataTimestamp)); - LOGGER.info("Obtained the updated data file for "+id); + LOGGER.info("Obtained the updated data file for " + id); return FormValidation.ok(); } @@ -389,14 +391,14 @@ public FormValidation updateNow() throws IOException { jsonString = loadJSONHTML(new URL(site + ".html?id=" + URLEncoder.encode(getId(), "UTF-8") + "&version=" + URLEncoder.encode(Jenkins.VERSION, "UTF-8"))); toolInstallerMetadataExists = true; } catch (Exception e) { - LOGGER.log(Level.FINE, "Could not load json from " + site, e ); + LOGGER.log(Level.FINE, "Could not load json from " + site, e); continue; } JSONObject o = JSONObject.fromObject(jsonString); if (signatureCheck) { - FormValidation e = updatesite.getJsonSignatureValidator(signatureValidatorPrefix +" '"+id+"'").verifySignature(o); - if (e.kind!= FormValidation.Kind.OK) { - LOGGER.log(Level.WARNING, "signature check failed for " + site, e ); + FormValidation e = updatesite.getJsonSignatureValidator(signatureValidatorPrefix + " '" + id + "'").verifySignature(o); + if (e.kind != FormValidation.Kind.OK) { + LOGGER.log(Level.WARNING, "signature check failed for " + site, e); continue; } } @@ -428,7 +430,7 @@ public JSONObject reduce(List jsonList) { * @param the generic class * @return true if the list has duplicates, false otherwise */ - public static boolean hasDuplicates (List genericList, String comparator) { + public static boolean hasDuplicates(List genericList, String comparator) { if (genericList.isEmpty()) { return false; } @@ -439,9 +441,9 @@ public static boolean hasDuplicates (List genericList, String comparator) LOGGER.warning("comparator: " + comparator + "does not exist for " + genericList.get(0).getClass() + ", " + e); return false; } - for (int i = 0; i < genericList.size(); i ++ ) { + for (int i = 0; i < genericList.size(); i++) { T data1 = genericList.get(i); - for (int j = i + 1; j < genericList.size(); j ++ ) { + for (int j = i + 1; j < genericList.size(); j++) { T data2 = genericList.get(j); try { if (field.get(data1).equals(field.get(data2))) { @@ -484,7 +486,7 @@ public static Downloadable get(@NonNull Class clazz) { @CheckForNull public static Downloadable get(String id) { for (Downloadable d : all()) { - if(d.id.equals(id)) + if (d.id.equals(id)) return d; } return null; @@ -492,17 +494,17 @@ public static Downloadable get(String id) { private static final Logger LOGGER = Logger.getLogger(Downloadable.class.getName()); private static final long DEFAULT_INTERVAL = - SystemProperties.getLong(Downloadable.class.getName()+".defaultInterval", DAYS.toMillis(1)); + SystemProperties.getLong(Downloadable.class.getName() + ".defaultInterval", DAYS.toMillis(1)); } // TODO this was previously referenced in the browser-based download, but should probably be checked for the server-based download @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "Accessible via System Groovy Scripts") - public static boolean neverUpdate = SystemProperties.getBoolean(DownloadService.class.getName()+".never"); + public static boolean neverUpdate = SystemProperties.getBoolean(DownloadService.class.getName() + ".never"); /** * May be used to temporarily disable signature checking on {@link DownloadService} and {@link UpdateCenter}. * Useful when upstream signatures are broken, such as due to expired certificates. */ @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "Accessible via System Groovy Scripts") - public static boolean signatureCheck = !SystemProperties.getBoolean(DownloadService.class.getName()+".noSignatureCheck"); + public static boolean signatureCheck = !SystemProperties.getBoolean(DownloadService.class.getName() + ".noSignatureCheck"); } diff --git a/core/src/main/java/hudson/model/Environment.java b/core/src/main/java/hudson/model/Environment.java index 889116cdc9da2..987d74e7d6d22 100644 --- a/core/src/main/java/hudson/model/Environment.java +++ b/core/src/main/java/hudson/model/Environment.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.EnvVars; @@ -52,60 +53,60 @@ * @see RunListener#setUpEnvironment(AbstractBuild, Launcher, BuildListener) */ public abstract class Environment { - /** - * Adds environmental variables for the builds to the given map. - * - *

      - * If the {@link Environment} object wants to pass in information to the - * build that runs, it can do so by exporting additional environment - * variables to the map. - * - *

      - * When this method is invoked, the map already contains the current - * "planned export" list. - * - * @param env - * never null. This really should have been typed as {@link EnvVars} + /** + * Adds environmental variables for the builds to the given map. + * + *

      + * If the {@link Environment} object wants to pass in information to the + * build that runs, it can do so by exporting additional environment + * variables to the map. + * + *

      + * When this method is invoked, the map already contains the current + * "planned export" list. + * + * @param env + * never null. This really should have been typed as {@link EnvVars} * but by the time we realized it it was too late. - */ - public void buildEnvVars(Map env) { - // no-op by default - } + */ + public void buildEnvVars(Map env) { + // no-op by default + } - /** - * Runs after the {@link Builder} completes, and performs a tear down. - * - *

      - * This method is invoked even when the build failed, so that the clean up - * operation can be performed regardless of the build result (for example, - * you'll want to stop application server even if a build fails.) - * - * @param build - * The same {@link Build} object given to the set up method. - * @param listener - * The same {@link BuildListener} object given to the set up - * method. - * @return true if the build can continue, false if there was an error and - * the build needs to be failed. - * @throws IOException - * terminates the build abnormally. Jenkins will handle the - * exception and reports a nice error message. - */ - public boolean tearDown(AbstractBuild build, BuildListener listener) - throws IOException, InterruptedException { - return true; - } + /** + * Runs after the {@link Builder} completes, and performs a tear down. + * + *

      + * This method is invoked even when the build failed, so that the clean up + * operation can be performed regardless of the build result (for example, + * you'll want to stop application server even if a build fails.) + * + * @param build + * The same {@link Build} object given to the set up method. + * @param listener + * The same {@link BuildListener} object given to the set up + * method. + * @return true if the build can continue, false if there was an error and + * the build needs to be failed. + * @throws IOException + * terminates the build abnormally. Jenkins will handle the + * exception and reports a nice error message. + */ + public boolean tearDown(AbstractBuild build, BuildListener listener) + throws IOException, InterruptedException { + return true; + } /** * Creates {@link Environment} implementation that just sets the variables as given in the parameter. */ - public static Environment create(final EnvVars envVars) { - return new Environment() { - @Override - public void buildEnvVars(Map env) { - env.putAll(envVars); - } - }; - } - + public static Environment create(final EnvVars envVars) { + return new Environment() { + @Override + public void buildEnvVars(Map env) { + env.putAll(envVars); + } + }; + } + } diff --git a/core/src/main/java/hudson/model/EnvironmentContributingAction.java b/core/src/main/java/hudson/model/EnvironmentContributingAction.java index 1df68de4c37f4..0de322014c235 100644 --- a/core/src/main/java/hudson/model/EnvironmentContributingAction.java +++ b/core/src/main/java/hudson/model/EnvironmentContributingAction.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.NonNull; diff --git a/core/src/main/java/hudson/model/EnvironmentContributor.java b/core/src/main/java/hudson/model/EnvironmentContributor.java index 926ec551060fb..0fa5a96c70af0 100644 --- a/core/src/main/java/hudson/model/EnvironmentContributor.java +++ b/core/src/main/java/hudson/model/EnvironmentContributor.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.NonNull; diff --git a/core/src/main/java/hudson/model/EnvironmentList.java b/core/src/main/java/hudson/model/EnvironmentList.java index 1c1b07a205731..0e11a1c51ccc8 100644 --- a/core/src/main/java/hudson/model/EnvironmentList.java +++ b/core/src/main/java/hudson/model/EnvironmentList.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import java.util.AbstractList; diff --git a/core/src/main/java/hudson/model/EnvironmentSpecific.java b/core/src/main/java/hudson/model/EnvironmentSpecific.java index 32663e721491c..53e127e671e53 100644 --- a/core/src/main/java/hudson/model/EnvironmentSpecific.java +++ b/core/src/main/java/hudson/model/EnvironmentSpecific.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.EnvVars; @@ -28,7 +29,7 @@ /** * Represents any concept that can be adapted for a certain environment. - * + * * Mainly for documentation purposes. * * @since 1.286 @@ -37,8 +38,8 @@ * @see NodeSpecific */ public interface EnvironmentSpecific> { - /** - * Returns a specialized copy of T for functioning in the given environment. - */ - T forEnvironment(EnvVars environment); + /** + * Returns a specialized copy of T for functioning in the given environment. + */ + T forEnvironment(EnvVars environment); } diff --git a/core/src/main/java/hudson/model/Executor.java b/core/src/main/java/hudson/model/Executor.java index cf00f7be56658..e7b14b72aebfa 100644 --- a/core/src/main/java/hudson/model/Executor.java +++ b/core/src/main/java/hudson/model/Executor.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static hudson.model.queue.Executables.getParentOf; @@ -147,7 +148,7 @@ public class Executor extends Thread implements ModelObject { private final List causes = new Vector<>(); public Executor(@NonNull Computer owner, int n) { - super("Executor #"+n+" for "+owner.getDisplayName()); + super("Executor #" + n + " for " + owner.getDisplayName()); this.owner = owner; this.queue = Jenkins.get().getQueue(); this.number = n; @@ -194,6 +195,7 @@ void interruptForShutdown() { * * @since 1.417 */ + public void interrupt(Result result) { interrupt(result, false); } @@ -248,7 +250,7 @@ public Result abortResult() { // this method is almost always called as a result of the current thread being interrupted // as a result we need to clean the interrupt flag so that the lock's lock method doesn't // get confused and think it was interrupted while awaiting the lock - Thread.interrupted(); + Thread.interrupted(); // we need to use a write lock as we may be repeatedly interrupted while processing and // we need the same lock as used in void interrupt(Result,boolean,CauseOfInterruption...) // JENKINS-28690 @@ -269,7 +271,7 @@ public Result abortResult() { * * @since 1.425 */ - public void recordCauseOfInterruption(Run build, TaskListener listener) { + public void recordCauseOfInterruption(Run build, TaskListener listener) { List r; // atomically get&clear causes. @@ -363,7 +365,7 @@ public SubTask call() throws Exception { workUnit.setExecutor(Executor.this); queue.onStartExecuting(Executor.this); if (LOGGER.isLoggable(FINE)) - LOGGER.log(FINE, getName()+" grabbed "+workUnit+" from queue"); + LOGGER.log(FINE, getName() + " grabbed " + workUnit + " from queue"); SubTask task = workUnit.work; Executable executable = task.createExecutable(); if (executable == null) { @@ -392,7 +394,7 @@ public SubTask call() throws Exception { lock.readLock().unlock(); } if (LOGGER.isLoggable(FINE)) - LOGGER.log(FINE, getName()+" is going to execute "+executable); + LOGGER.log(FINE, getName() + " is going to execute " + executable); Throwable problems = null; try { @@ -419,7 +421,7 @@ public SubTask call() throws Exception { workUnit.context.item.getAllActions(), }); } - for (Action action: workUnit.context.actions) { + for (Action action : workUnit.context.actions) { ((Actionable) executable).addAction(action); } } @@ -463,10 +465,10 @@ public SubTask call() throws Exception { } } } catch (InterruptedException e) { - LOGGER.log(FINE, getName()+" interrupted",e); + LOGGER.log(FINE, getName() + " interrupted", e); // die peacefully - } catch(Exception | Error e) { - LOGGER.log(SEVERE, getName()+": Unexpected executor death", e); + } catch (Exception | Error e) { + LOGGER.log(SEVERE, getName() + ": Unexpected executor death", e); } finally { if (asynchronousExecution == null) { finish2(); @@ -533,18 +535,18 @@ public void completedAsynchronous(@CheckForNull Throwable error) { /** * Same as {@link #getCurrentExecutable} but checks {@link Item#READ}. */ - @Exported(name="currentExecutable") + @Exported(name = "currentExecutable") @Restricted(DoNotUse.class) // for exporting only public Queue.Executable getCurrentExecutableForApi() { Executable candidate = getCurrentExecutable(); return candidate instanceof AccessControlled && ((AccessControlled) candidate).hasPermission(Item.READ) ? candidate : null; } - + /** * Returns causes of interruption. * * @return Unmodifiable collection of causes of interruption. - * @since 1.617 + * @since 1.617 */ public @NonNull Collection getCausesOfInterruption() { return Collections.unmodifiableCollection(causes); @@ -593,7 +595,7 @@ public FilePath getCurrentWorkspace() { */ @Override public String getDisplayName() { - return "Executor #"+getNumber(); + return "Executor #" + getNumber(); } /** @@ -846,8 +848,8 @@ public void start() { */ @RequirePOST @Deprecated - public void doStop( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { - doStop().generateResponse(req,rsp,this); + public void doStop(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { + doStop().generateResponse(req, rsp, this); } /** @@ -879,7 +881,7 @@ public HttpResponse doStopBuild(@CheckForNull @QueryParameter(fixEmpty = true) S try { if (executable != null) { if (runExtId == null || runExtId.isEmpty() || ! (executable instanceof Run) - || (runExtId.equals(((Run) executable).getExternalizableId()))) { + || (runExtId.equals(((Run) executable).getExternalizableId()))) { final Queue.Task ownerTask = getParentOf(executable).getOwnerTask(); boolean canAbort = ownerTask.hasAbortPermission(); if (canAbort && ownerTask instanceof AccessControlled) { @@ -913,7 +915,7 @@ public boolean hasStopPermission() { lock.readLock().lock(); try { return executable != null && getParentOf(executable).getOwnerTask().hasAbortPermission(); - } catch(RuntimeException ex) { + } catch (RuntimeException ex) { if (!(ex instanceof AccessDeniedException)) { // Prevents UI from exploding in the case of unexpected runtime exceptions LOGGER.log(WARNING, "Unhandled exception", ex); @@ -957,12 +959,12 @@ protected Object call(Object o, Method m, Object[] args) throws Throwable { final Executor old = IMPERSONATION.get(); IMPERSONATION.set(Executor.this); try { - return m.invoke(o,args); + return m.invoke(o, args); } finally { IMPERSONATION.set(old); } } - }.wrap(type,core); + }.wrap(type, core); } /** diff --git a/core/src/main/java/hudson/model/ExecutorListener.java b/core/src/main/java/hudson/model/ExecutorListener.java index eb4a8cdb26818..6500e6acc2ecc 100644 --- a/core/src/main/java/hudson/model/ExecutorListener.java +++ b/core/src/main/java/hudson/model/ExecutorListener.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Stephen Connolly - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.ExtensionPoint; diff --git a/core/src/main/java/hudson/model/Failure.java b/core/src/main/java/hudson/model/Failure.java index 1931d505eb262..71318dd0464b5 100644 --- a/core/src/main/java/hudson/model/Failure.java +++ b/core/src/main/java/hudson/model/Failure.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -37,7 +38,7 @@ *

      * The error page is rendered into HTML, but without a stack trace. So only use * this exception when the error condition is anticipated by the program, and where - * we nor users don't need to see the stack trace to figure out the root cause. + * we nor users don't need to see the stack trace to figure out the root cause. * * @author Kohsuke Kawaguchi * @since 1.321 @@ -46,7 +47,7 @@ public class Failure extends RuntimeException implements HttpResponse { private final boolean pre; public Failure(String message) { - this(message,false); + this(message, false); } public Failure(String message, boolean pre) { @@ -63,12 +64,12 @@ public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object nod @Override public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException { - req.setAttribute("message",getMessage()); - if(pre) - req.setAttribute("pre",true); + req.setAttribute("message", getMessage()); + if (pre) + req.setAttribute("pre", true); if (node instanceof AbstractItem) // Maintain ancestors - rsp.forward(Jenkins.get(), ((AbstractItem)node).getUrl() + "error", req); + rsp.forward(Jenkins.get(), ((AbstractItem) node).getUrl() + "error", req); else - rsp.forward(node instanceof AbstractModelObject ? node : Jenkins.get() ,"error", req); + rsp.forward(node instanceof AbstractModelObject ? node : Jenkins.get(), "error", req); } } diff --git a/core/src/main/java/hudson/model/FileParameterDefinition.java b/core/src/main/java/hudson/model/FileParameterDefinition.java index 2d40c2d2fcab9..dcaf022b20fa1 100644 --- a/core/src/main/java/hudson/model/FileParameterDefinition.java +++ b/core/src/main/java/hudson/model/FileParameterDefinition.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,10 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import hudson.cli.CLICommand; import java.io.File; @@ -69,7 +71,7 @@ public FileParameterValue createValue(StaplerRequest req, JSONObject jo) { return p; } - @Extension @Symbol({"file","fileParam"}) + @Extension @Symbol({"file", "fileParam"}) public static class DescriptorImpl extends ParameterDescriptor { @Override public String getDisplayName() { @@ -82,17 +84,17 @@ public String getHelpFile() { } } - @Override - public ParameterValue createValue(StaplerRequest req) { + @Override + public ParameterValue createValue(StaplerRequest req) { FileItem src; try { - src = req.getFileItem( getName() ); + src = req.getFileItem(getName()); } catch (ServletException | IOException e) { // Not sure what to do here. We might want to raise this // but that would involve changing the throws for this call return null; } - if ( src == null ) { + if (src == null) { // the requested file parameter wasn't uploaded return null; } @@ -100,14 +102,14 @@ public ParameterValue createValue(StaplerRequest req) { p.setDescription(getDescription()); p.setLocation(getName()); return p; - } + } /** * Strip off the path portion if the given path contains it. */ private String getFileName(String possiblyPathName) { - possiblyPathName = possiblyPathName.substring(possiblyPathName.lastIndexOf('/')+1); - possiblyPathName = possiblyPathName.substring(possiblyPathName.lastIndexOf('\\')+1); + possiblyPathName = possiblyPathName.substring(possiblyPathName.lastIndexOf('/') + 1); + possiblyPathName = possiblyPathName.substring(possiblyPathName.lastIndexOf('\\') + 1); return possiblyPathName; } @@ -115,7 +117,7 @@ private String getFileName(String possiblyPathName) { @Override public ParameterValue createValue(CLICommand command, String value) throws IOException, InterruptedException { // capture the file to the server - File local = File.createTempFile("jenkins","parameter"); + File local = File.createTempFile("jenkins", "parameter"); String name; if (value.isEmpty()) { FileUtils.copyInputStreamToFile(command.stdin, local); @@ -140,6 +142,7 @@ public int hashCode() { } @Override + @SuppressFBWarnings(value = "EQ_GETCLASS_AND_CLASS_CONSTANT", justification = "ParameterDefinitionTest tests that subclasses are not equal to their parent classes, so the behavior appears to be intentional") public boolean equals(Object obj) { if (FileParameterDefinition.class != getClass()) return super.equals(obj); diff --git a/core/src/main/java/hudson/model/FileParameterValue.java b/core/src/main/java/hudson/model/FileParameterValue.java index b3e5c146cd9d4..e11d31c891fae 100644 --- a/core/src/main/java/hudson/model/FileParameterValue.java +++ b/core/src/main/java/hudson/model/FileParameterValue.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -36,6 +37,7 @@ import java.io.OutputStream; import java.io.UncheckedIOException; import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; import java.nio.file.Files; import java.util.regex.Pattern; import jenkins.util.SystemProperties; @@ -45,7 +47,6 @@ import org.apache.commons.fileupload.util.FileItemHeadersImpl; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; import org.kohsuke.stapler.DataBoundConstructor; @@ -86,7 +87,7 @@ public class FileParameterValue extends ParameterValue { /** * Overrides the location in the build to place this file. Initially set to {@link #getName()} - * The location could be directly the filename or also a hierarchical path. + * The location could be directly the filename or also a hierarchical path. * The intermediate folders will be created automatically. * Take care that no escape from the current directory is allowed and will result in the failure of the build. */ @@ -126,8 +127,8 @@ public Object getValue() { * Exposes the originalFileName as an environment variable. */ @Override - public void buildEnvironment(Run build, EnvVars env) { - env.put(name,originalFileName); + public void buildEnvironment(Run build, EnvVars env) { + env.put(name, originalFileName); } @Override @@ -151,13 +152,13 @@ public FileItem getFile() { } @Override - public BuildWrapper createBuildWrapper(AbstractBuild build) { + public BuildWrapper createBuildWrapper(AbstractBuild build) { return new BuildWrapper() { @SuppressFBWarnings(value = {"FILE_UPLOAD_FILENAME", "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"}, justification = "TODO needs triage") @Override public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { - if (!StringUtils.isEmpty(location) && !StringUtils.isEmpty(file.getName())) { - listener.getLogger().println("Copying file to "+location); + if (location != null && !location.isEmpty() && file.getName() != null && !file.getName().isEmpty()) { + listener.getLogger().println("Copying file to " + location); FilePath ws = build.getWorkspace(); if (ws == null) { throw new IllegalStateException("The workspace should be created when setUp method is called"); @@ -175,48 +176,48 @@ public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener l locationFilePath.delete(); } - locationFilePath.copyFrom(file); + locationFilePath.copyFrom(file); locationFilePath.copyTo(new FilePath(getLocationUnderBuild(build))); - } + } return new Environment() {}; } }; } - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result - + (location == null ? 0 : location.hashCode()); - return result; - } - - /** - * Compares file parameters (existing files will be considered as different). - * @since 1.586 Function has been modified in order to avoid JENKINS-19017 issue (wrong merge of builds in the queue). - */ - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - FileParameterValue other = (FileParameterValue) obj; - - if (location == null && other.location == null) - return true; // Consider null parameters as equal - - //TODO: check fingerprints or checksums to improve the behavior (JENKINS-25211) - // Return false even if files are equal - return false; - } + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + (location == null ? 0 : location.hashCode()); + return result; + } + + /** + * Compares file parameters (existing files will be considered as different). + * @since 1.586 Function has been modified in order to avoid JENKINS-19017 issue (wrong merge of builds in the queue). + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + FileParameterValue other = (FileParameterValue) obj; + + if (location == null && other.location == null) + return true; // Consider null parameters as equal + + //TODO: check fingerprints or checksums to improve the behavior (JENKINS-25211) + // Return false even if files are equal + return false; + } @Override public String toString() { - return "(FileParameterValue) " + getName() + "='" + originalFileName + "'"; + return "(FileParameterValue) " + getName() + "='" + originalFileName + "'"; } @Override public String getShortDescription() { @@ -227,7 +228,7 @@ public String toString() { * Serve this file parameter in response to a {@link StaplerRequest}. */ public DirectoryBrowserSupport doDynamic(StaplerRequest request, StaplerResponse response) { - AbstractBuild build = (AbstractBuild)request.findAncestor(AbstractBuild.class).getObject(); + AbstractBuild build = (AbstractBuild) request.findAncestor(AbstractBuild.class).getObject(); File fileParameter = getFileParameterFolderUnderBuild(build); return new DirectoryBrowserSupport(build, new FilePath(fileParameter), Messages.FileParameterValue_IndexTitle(), "folder.png", false); } @@ -242,7 +243,7 @@ private File getLocationUnderBuild(AbstractBuild build) { return new File(getFileParameterFolderUnderBuild(build), location); } - private File getFileParameterFolderUnderBuild(AbstractBuild build){ + private File getFileParameterFolderUnderBuild(AbstractBuild build) { return new File(build.getRootDir(), FOLDER_NAME); } @@ -302,7 +303,7 @@ public String getString(String encoding) throws UnsupportedEncodingException { @Override public String getString() { - return new String(get()); + return new String(get(), Charset.defaultCharset()); } @Override diff --git a/core/src/main/java/hudson/model/Fingerprint.java b/core/src/main/java/hudson/model/Fingerprint.java index 19c8a17feced9..d4b57badaefcc 100644 --- a/core/src/main/java/hudson/model/Fingerprint.java +++ b/core/src/main/java/hudson/model/Fingerprint.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Yahoo! Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import com.infradna.tool.bridge_method_injector.WithBridgeMethods; @@ -86,7 +87,7 @@ public class Fingerprint implements ModelObject, Saveable { /** * Pointer to a {@link Build}. */ - @ExportedBean(defaultVisibility=2) + @ExportedBean(defaultVisibility = 2) public static class BuildPtr { String name; final int number; @@ -97,13 +98,13 @@ public BuildPtr(String name, int number) { } public BuildPtr(Run run) { - this( run.getParent().getFullName(), run.getNumber() ); + this(run.getParent().getFullName(), run.getNumber()); } /** * Gets {@link Job#getFullName() the full name of the job}. * Such job could be since then removed, so there might not be a corresponding {@link Job}. - * + * * @return A name of the job */ @Exported @@ -111,12 +112,12 @@ public BuildPtr(Run run) { public String getName() { return name; } - + /** * Checks if the current user has permission to see this pointer. * @return {@code true} if the job exists and user has {@link Item#READ} permissions - * or if the current user has {@link Jenkins#ADMINISTER} permissions. - * If the job exists, but the current user has no permission to discover it, + * or if the current user has {@link Jenkins#ADMINISTER} permissions. + * If the job exists, but the current user has no permission to discover it, * {@code false} will be returned. * If the job has been deleted and the user has no {@link Jenkins#ADMINISTER} permissions, * it also returns {@code false} in order to avoid the job existence fact exposure. @@ -128,22 +129,22 @@ private boolean hasPermissionToDiscoverBuild() { if (instance.hasPermission(Jenkins.ADMINISTER)) { return true; } - + return canDiscoverItem(name); } - - + + void setName(String newName) { name = newName; } - + /** * Gets the {@link Job} that this pointer points to, * or null if such a job no longer exists. */ - @WithBridgeMethods(value=AbstractProject.class, castRequired=true) - public Job getJob() { + @WithBridgeMethods(value = AbstractProject.class, castRequired = true) + public Job getJob() { return Jenkins.get().getItemByFullName(name, Job.class); } @@ -165,19 +166,19 @@ public int getNumber() { */ public Run getRun() { Job j = getJob(); - if(j==null) return null; + if (j == null) return null; return j.getBuildByNumber(number); } private boolean isAlive() { - return getRun()!=null; + return getRun() != null; } /** * Returns true if {@link BuildPtr} points to the given run. */ public boolean is(Run r) { - return r.getNumber()==number && r.getParent().getFullName().equals(name); + return r.getNumber() == number && r.getParent().getFullName().equals(name); } /** @@ -193,12 +194,12 @@ public boolean is(Job job) { * *

      * This is useful to check if an artifact in MavenModule - * belongs to MavenModuleSet. + * belongs to MavenModuleSet. */ public boolean belongsTo(Job job) { Item p = Jenkins.get().getItemByFullName(name); - while(p!=null) { - if(p==job) + while (p != null) { + if (p == job) return true; // go up the chain while we @@ -221,13 +222,13 @@ public boolean belongsTo(Job job) { /** * Range of build numbers [start,end). Immutable. */ - @ExportedBean(defaultVisibility=4) + @ExportedBean(defaultVisibility = 4) public static final class Range { final int start; final int end; public Range(int start, int end) { - assert start ranges; @@ -364,10 +365,10 @@ public Iterable listNumbers() { return new Iterable() { @Override public Iterator iterator() { - return new Iterators.FlattenIterator(ranges) { + return new Iterators.FlattenIterator(ranges) { @Override protected Iterator expand(Range range) { - return Iterators.sequence(range.start,range.end).iterator(); + return Iterators.sequence(range.start, range.end).iterator(); } }; } @@ -382,10 +383,10 @@ public Iterable listNumbersReverse() { return new Iterable() { @Override public Iterator iterator() { - return new Iterators.FlattenIterator(Iterators.reverse(ranges)) { + return new Iterators.FlattenIterator(Iterators.reverse(ranges)) { @Override protected Iterator expand(Range range) { - return Iterators.reverseSequence(range.start,range.end).iterator(); + return Iterators.reverseSequence(range.start, range.end).iterator(); } }; } @@ -405,27 +406,27 @@ public synchronized List getRanges() { * If the set already includes this number, this will be a no-op. */ public synchronized void add(int n) { - for( int i=0; i intersection = new ArrayList<>(); - int lhs=0,rhs=0; - while(lhs sub = new ArrayList<>(); - int lhs=0,rhs=0; - while(lhs0) buf.append(','); + if (buf.length() > 0) buf.append(','); buf.append(r); } return buf.toString(); @@ -647,7 +648,7 @@ public synchronized int min() { * If this range is empty, this method throws an exception. */ public synchronized int max() { - return ranges.get(ranges.size()-1).end; + return ranges.get(ranges.size() - 1).end; } /** @@ -658,7 +659,7 @@ public synchronized int max() { * Note that {} is smaller than any n. */ public synchronized boolean isSmallerThan(int n) { - if(ranges.isEmpty()) return true; + if (ranges.isEmpty()) return true; return ranges.get(ranges.size() - 1).isSmallerThan(n); } @@ -679,8 +680,8 @@ public static RangeSet fromString(String list, boolean skipError) { return rs; } - String[] items = Util.tokenize(list,","); - if(items.length > 1 && items.length <= StringUtils.countMatches(list, ",")) { + String[] items = Util.tokenize(list, ","); + if (items.length > 1 && items.length <= StringUtils.countMatches(list, ",")) { if (!skipError) { throw new IllegalArgumentException( String.format("Unable to parse '%s', expected correct notation M,N or M-N", list)); @@ -702,8 +703,8 @@ public static RangeSet fromString(String list, boolean skipError) { continue; } - if(s.contains("-")) { - if(StringUtils.countMatches(s, "-") > 1) { + if (s.contains("-")) { + if (StringUtils.countMatches(s, "-") > 1) { if (!skipError) { throw new IllegalArgumentException(String.format( "Unable to parse '%s', expected correct notation M,N or M-N", list)); @@ -711,11 +712,11 @@ public static RangeSet fromString(String list, boolean skipError) { // ignore malformed ranges like "-5-2" or "2-5-" continue; } - String[] tokens = Util.tokenize(s,"-"); + String[] tokens = Util.tokenize(s, "-"); if (tokens.length == 2) { int left = Integer.parseInt(tokens[0]); int right = Integer.parseInt(tokens[1]); - if(left < 0 || right < 0) { + if (left < 0 || right < 0) { if (!skipError) { throw new IllegalArgumentException( String.format("Unable to parse '%s', expected number above zero", list)); @@ -723,7 +724,7 @@ public static RangeSet fromString(String list, boolean skipError) { // ignore a range which starts or ends under zero like "-5-3" continue; } - if(left > right) { + if (left > right) { if (!skipError) { throw new IllegalArgumentException(String.format( "Unable to parse '%s', expected string with a range M-N where M0) buf.append(','); - if(r.isSingle()) + if (buf.length() > 0) buf.append(','); + if (r.isSingle()) buf.append(r.start); else - buf.append(r.start).append('-').append(r.end-1); + buf.append(r.start).append('-').append(r.end - 1); } return buf.toString(); } @Override public Object unmarshal(HierarchicalStreamReader reader, final UnmarshallingContext context) { - if(reader.hasMoreChildren()) { + if (reader.hasMoreChildren()) { /* old format where elements are nested like 1337 1479 */ - return new RangeSet((List)collectionConv.unmarshal(reader,context)); + return new RangeSet((List) collectionConv.unmarshal(reader, context)); } else { - return RangeSet.fromString(reader.getValue(),true); + return RangeSet.fromString(reader.getValue(), true); } } } @@ -821,6 +822,7 @@ public void onLocationChanged(final Item item, final String oldName, final Strin locationChanged(item, oldName, newName); } } + private void locationChanged(Item item, String oldName, String newName) { if (item instanceof Job) { Job p = Jenkins.get().getItemByFullName(newName, Job.class); @@ -842,7 +844,7 @@ private void locationChanged(Item item, String oldName, String newName) { } private static final DateConverter DATE_CONVERTER = new DateConverter(); - + /** * Time when the fingerprint has been captured. */ @@ -861,7 +863,7 @@ private void locationChanged(Item item, String oldName, String newName) { /** * Range of builds that use this file keyed by a job full name. */ - private Hashtable usages = new Hashtable<>(); + private Hashtable usages = new Hashtable<>(); PersistedList facets = new PersistedList<>(this); @@ -871,7 +873,7 @@ private void locationChanged(Item item, String oldName, String newName) { private transient volatile List transientFacets = null; public Fingerprint(@CheckForNull Run build, @NonNull String fileName, @NonNull byte[] md5sum) throws IOException { - this(build==null ? null : new BuildPtr(build), fileName, md5sum); + this(build == null ? null : new BuildPtr(build), fileName, md5sum); save(); } @@ -918,7 +920,7 @@ public Fingerprint(@CheckForNull Run build, @NonNull String fileName, @NonNull b /** * Gets the MD5 hash string. */ - @Exported(name="hash") + @Exported(name = "hash") public @NonNull String getHashString() { return Util.toHexString(md5sum); } @@ -938,7 +940,7 @@ public Fingerprint(@CheckForNull Run build, @NonNull String fileName, @NonNull b * string like "3 minutes" "1 day" etc. */ public @NonNull String getTimestampString() { - long duration = System.currentTimeMillis()-timestamp.getTime(); + long duration = System.currentTimeMillis() - timestamp.getTime(); return Util.getTimeSpanString(duration); } @@ -951,7 +953,7 @@ public Fingerprint(@CheckForNull Run build, @NonNull String fileName, @NonNull b */ public @NonNull RangeSet getRangeSet(String jobFullName) { RangeSet r = usages.get(jobFullName); - if(r==null) r = new RangeSet(); + if (r == null) r = new RangeSet(); return r; } @@ -969,11 +971,11 @@ public synchronized List getJobs() { return r; } - public @CheckForNull Hashtable getUsages() { + public @CheckForNull Hashtable getUsages() { return usages; } - @ExportedBean(defaultVisibility=2) + @ExportedBean(defaultVisibility = 2) public static final class RangeItem { @Exported public final String name; @@ -987,7 +989,7 @@ public RangeItem(String name, RangeSet ranges) { } // this is for remote API - @Exported(name="usage") + @Exported(name = "usage") public @NonNull List _getUsages() { List r = new ArrayList<>(); final Jenkins instance = Jenkins.get(); @@ -1035,11 +1037,11 @@ protected Object readResolve() { } void addWithoutSaving(@NonNull String jobFullName, int n) { - synchronized(usages) { // TODO why not synchronized (this) like some, though not all, other accesses? + synchronized (usages) { // TODO why not synchronized (this) like some, though not all, other accesses? RangeSet r = usages.get(jobFullName); - if(r==null) { + if (r == null) { r = new RangeSet(); - usages.put(jobFullName,r); + usages.put(jobFullName, r); } r.add(n); } @@ -1054,20 +1056,20 @@ void addWithoutSaving(@NonNull String jobFullName, int n) { * without losing too much information. */ public synchronized boolean isAlive() { - if(original!=null && original.isAlive()) + if (original != null && original.isAlive()) return true; - for (Map.Entry e : usages.entrySet()) { - Job j = Jenkins.get().getItemByFullName(e.getKey(),Job.class); - if(j==null) + for (Map.Entry e : usages.entrySet()) { + Job j = Jenkins.get().getItemByFullName(e.getKey(), Job.class); + if (j == null) continue; Run firstBuild = j.getFirstBuild(); - if(firstBuild==null) + if (firstBuild == null) continue; int oldest = firstBuild.getNumber(); - if(!e.getValue().isSmallerThan(oldest)) + if (!e.getValue().isSmallerThan(oldest)) return true; } return false; @@ -1078,22 +1080,22 @@ public synchronized boolean isAlive() { * * @return true * if this record was modified. - * + * * @throws IOException Save failure */ public synchronized boolean trim() throws IOException { boolean modified = false; - for (Map.Entry e : new Hashtable<>(usages).entrySet()) {// copy because we mutate - Job j = Jenkins.get().getItemByFullName(e.getKey(),Job.class); - if(j==null) {// no such job any more. recycle the record + for (Map.Entry e : new Hashtable<>(usages).entrySet()) { // copy because we mutate + Job j = Jenkins.get().getItemByFullName(e.getKey(), Job.class); + if (j == null) { // no such job any more. recycle the record modified = true; usages.remove(e.getKey()); continue; } Run firstBuild = j.getFirstBuild(); - if(firstBuild==null) {// no builds. recycle the whole record + if (firstBuild == null) { // no builds. recycle the whole record modified = true; usages.remove(e.getKey()); continue; @@ -1106,17 +1108,17 @@ public synchronized boolean trim() throws IOException { // that are marked as kept RangeSet kept = new RangeSet(); Run r = firstBuild; - while (r!=null && r.isKeepLog()) { + while (r != null && r.isKeepLog()) { kept.add(r.getNumber()); r = r.getNextBuild(); } - if (r==null) { + if (r == null) { // all the build records are permanently kept ones, so we'll just have to keep 'kept' out of whatever currently in 'cur' modified |= cur.retainAll(kept); } else { // otherwise we are ready to discard [0,r.number) except those marked as 'kept' - RangeSet discarding = new RangeSet(new Range(-1,r.getNumber())); + RangeSet discarding = new RangeSet(new Range(-1, r.getNumber())); discarding.removeAll(kept); modified |= cur.removeAll(discarding); } @@ -1154,10 +1156,10 @@ public synchronized boolean trim() throws IOException { * @since 1.421 */ public @NonNull Collection getFacets() { - if (transientFacets==null) { + if (transientFacets == null) { List transientFacets = new ArrayList<>(); for (TransientFingerprintFacetFactory fff : TransientFingerprintFacetFactory.all()) { - fff.createFor(this,transientFacets); + fff.createFor(this, transientFacets); } this.transientFacets = Collections.unmodifiableList(transientFacets); } @@ -1186,7 +1188,7 @@ public boolean contains(Object o) { @Override public int size() { - return facets.size()+transientFacets.size(); + return facets.size() + transientFacets.size(); } }; } @@ -1202,7 +1204,7 @@ public int size() { /** * Sorts {@link FingerprintFacet}s by their timestamps. - * @return Sorted list of {@link FingerprintFacet}s + * @return Sorted list of {@link FingerprintFacet}s */ public @NonNull Collection getSortedFacets() { List r = new ArrayList<>(getFacets()); @@ -1247,12 +1249,12 @@ public int compare(FingerprintFacet o1, FingerprintFacet o2) { */ @Override public synchronized void save() throws IOException { - if(BulkChange.contains(this)) { + if (BulkChange.contains(this)) { return; } - long start=0; - if(logger.isLoggable(Level.FINE)) + long start = 0; + if (logger.isLoggable(Level.FINE)) start = System.currentTimeMillis(); FingerprintStorage configuredFingerprintStorage = FingerprintStorage.get(); @@ -1270,14 +1272,14 @@ public synchronized void save() throws IOException { fileFingerprintStorage.delete(this.getHashString()); } - if(logger.isLoggable(Level.FINE)) + if (logger.isLoggable(Level.FINE)) logger.fine("Saving fingerprint " + getHashString() + " took " + (System.currentTimeMillis() - start) + "ms"); } /** * Save the Fingerprint in the given file locally * @throws IOException Save error - * @deprecated as of TODO. Use {@link #save()} instead. + * @deprecated as of 2.242. Use {@link #save()} instead. */ @Deprecated void save(File file) throws IOException { @@ -1308,7 +1310,7 @@ public synchronized void rename(String oldName, String newName) throws IOExcepti touched = true; } } - + if (usages != null) { RangeSet r = usages.get(oldName); if (r != null) { @@ -1317,12 +1319,12 @@ public synchronized void rename(String oldName, String newName) throws IOExcepti touched = true; } } - + if (touched) { save(); } } - + public Api getApi() { return new Api(this); } @@ -1337,8 +1339,8 @@ public Api getApi() { * 2. If not found, then the local storage is polled to retrieve the fingerprint */ public static @CheckForNull Fingerprint load(@NonNull String id) throws IOException { - long start=0; - if(logger.isLoggable(Level.FINE)) { + long start = 0; + if (logger.isLoggable(Level.FINE)) { start = System.currentTimeMillis(); } @@ -1359,7 +1361,7 @@ public Api getApi() { initFacets(loaded); } - if(logger.isLoggable(Level.FINE)) { + if (logger.isLoggable(Level.FINE)) { logger.fine("Loading fingerprint took " + (System.currentTimeMillis() - start) + "ms"); } @@ -1368,7 +1370,7 @@ public Api getApi() { /** * Determines the file name from md5sum. - * @deprecated as of TODO. Use {@link #load(String)} instead. + * @deprecated as of 2.242. Use {@link #load(String)} instead. */ @Deprecated /*package*/ static @CheckForNull Fingerprint load(@NonNull byte[] md5sum) throws IOException { @@ -1379,7 +1381,7 @@ public Api getApi() { * Loads a {@link Fingerprint} from a file in the image. * @return Loaded {@link Fingerprint}. Null if the config file does not exist or * malformed. - * @deprecated as of TODO. Use {@link #load(String)} instead. + * @deprecated as of 2.242. Use {@link #load(String)} instead. */ @Deprecated /*package*/ static @CheckForNull Fingerprint load(@NonNull File file) throws IOException { @@ -1433,7 +1435,7 @@ private static void initFacets(@CheckForNull Fingerprint fingerprint) { + facets + "]"; } - + /** * Checks if the current user can Discover the item. * If yes, it may be displayed as a text in Fingerprint UIs. @@ -1453,7 +1455,7 @@ private static boolean canDiscoverItem(@NonNull final String fullName) { if (item != null) { return true; } - + // Probably it failed due to the missing Item.DISCOVER // We try to retrieve the job using SYSTEM2 user and to check permissions manually. final Authentication userAuth = Jenkins.getAuthentication2(); @@ -1498,10 +1500,10 @@ public static XStream2 getXStream() { } static { - XSTREAM.alias("fingerprint",Fingerprint.class); - XSTREAM.alias("range",Range.class); - XSTREAM.alias("ranges",RangeSet.class); - XSTREAM.registerConverter(new HexBinaryConverter(),10); + XSTREAM.alias("fingerprint", Fingerprint.class); + XSTREAM.alias("range", Range.class); + XSTREAM.alias("ranges", RangeSet.class); + XSTREAM.registerConverter(new HexBinaryConverter(), 10); XSTREAM.registerConverter(new RangeSet.ConverterImpl( new CollectionConverter(XSTREAM.getMapper()) { @Override @@ -1509,7 +1511,7 @@ protected Object createCollection(Class type) { return new ArrayList(); } } - ),10); + ), 10); } private static final Logger logger = Logger.getLogger(Fingerprint.class.getName()); diff --git a/core/src/main/java/hudson/model/FingerprintCleanupThread.java b/core/src/main/java/hudson/model/FingerprintCleanupThread.java index f7720bb78fc41..6ac6a361e8f72 100644 --- a/core/src/main/java/hudson/model/FingerprintCleanupThread.java +++ b/core/src/main/java/hudson/model/FingerprintCleanupThread.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.Extension; diff --git a/core/src/main/java/hudson/model/FingerprintMap.java b/core/src/main/java/hudson/model/FingerprintMap.java index 7679b384e39a0..b41edbb9f703d 100644 --- a/core/src/main/java/hudson/model/FingerprintMap.java +++ b/core/src/main/java/hudson/model/FingerprintMap.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2011, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -43,7 +44,7 @@ * @author Kohsuke Kawaguchi * @see Jenkins#getFingerprintMap() */ -public final class FingerprintMap extends KeyedDataStorage { +public final class FingerprintMap extends KeyedDataStorage { /** * Returns true if there's some data in the fingerprint database. @@ -60,25 +61,25 @@ public boolean isReady() { * @throws IOException Loading error */ public @NonNull Fingerprint getOrCreate(@CheckForNull AbstractBuild build, @NonNull String fileName, @NonNull byte[] md5sum) throws IOException { - return getOrCreate(build,fileName, Util.toHexString(md5sum)); + return getOrCreate(build, fileName, Util.toHexString(md5sum)); } public @NonNull Fingerprint getOrCreate(@CheckForNull AbstractBuild build, @NonNull String fileName, @NonNull String md5sum) throws IOException { - return super.getOrCreate(md5sum, new FingerprintParams(build,fileName)); + return super.getOrCreate(md5sum, new FingerprintParams(build, fileName)); } public @NonNull Fingerprint getOrCreate(@CheckForNull Run build, @NonNull String fileName, @NonNull String md5sum) throws IOException { - return super.getOrCreate(md5sum, new FingerprintParams(build,fileName)); + return super.getOrCreate(md5sum, new FingerprintParams(build, fileName)); } @Override protected Fingerprint get(String md5sum, boolean createIfNotExist, FingerprintParams createParams) throws IOException { // sanity check - if(md5sum.length()!=32) + if (md5sum.length() != 32) return null; // illegal input md5sum = md5sum.toLowerCase(Locale.ENGLISH); - return super.get(md5sum,createIfNotExist,createParams); + return super.get(md5sum, createIfNotExist, createParams); } @Override @@ -102,7 +103,7 @@ static class FingerprintParams { this.build = build; this.fileName = fileName; - assert fileName!=null; + assert fileName != null; } } } diff --git a/core/src/main/java/hudson/model/FreeStyleBuild.java b/core/src/main/java/hudson/model/FreeStyleBuild.java index f64e152102b15..d2871dc8da797 100644 --- a/core/src/main/java/hudson/model/FreeStyleBuild.java +++ b/core/src/main/java/hudson/model/FreeStyleBuild.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import java.io.File; @@ -29,7 +30,7 @@ /** * @author Kohsuke Kawaguchi */ -public class FreeStyleBuild extends Build { +public class FreeStyleBuild extends Build { public FreeStyleBuild(FreeStyleProject project) throws IOException { super(project); } diff --git a/core/src/main/java/hudson/model/FreeStyleProject.java b/core/src/main/java/hudson/model/FreeStyleProject.java index 9992ffcc80c21..814f2cf7e8a74 100644 --- a/core/src/main/java/hudson/model/FreeStyleProject.java +++ b/core/src/main/java/hudson/model/FreeStyleProject.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, id:cactusman - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,8 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import jenkins.model.Jenkins; import jenkins.model.item_category.StandaloneProjectsCategory; @@ -34,10 +36,10 @@ /** * Free-style software project. - * + * * @author Kohsuke Kawaguchi */ -public class FreeStyleProject extends Project implements TopLevelItem { +public class FreeStyleProject extends Project implements TopLevelItem { /** * @deprecated as of 1.390 @@ -58,7 +60,7 @@ protected Class getBuildClass() { @Override public DescriptorImpl getDescriptor() { - return (DescriptorImpl)Jenkins.get().getDescriptorOrDie(getClass()); + return (DescriptorImpl) Jenkins.get().getDescriptorOrDie(getClass()); } /** @@ -70,10 +72,12 @@ public DescriptorImpl getDescriptor() { */ @Deprecated @Restricted(NoExternalUse.class) + @SuppressFBWarnings(value = "MS_PKGPROTECT", justification = "for backward compatibility") public static /*almost final*/ DescriptorImpl DESCRIPTOR; - @Extension(ordinal=1000) @Symbol({"freeStyle","freeStyleJob"}) + @Extension(ordinal = 1000) @Symbol({"freeStyle", "freeStyleJob"}) public static class DescriptorImpl extends AbstractProjectDescriptor { + @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "for backward compatibility") public DescriptorImpl() { DESCRIPTOR = this; } @@ -85,7 +89,7 @@ public String getDisplayName() { @Override public FreeStyleProject newInstance(ItemGroup parent, String name) { - return new FreeStyleProject(parent,name); + return new FreeStyleProject(parent, name); } @Override diff --git a/core/src/main/java/hudson/model/FullDuplexHttpChannel.java b/core/src/main/java/hudson/model/FullDuplexHttpChannel.java index 6251bddec8423..64e2428f6a71d 100644 --- a/core/src/main/java/hudson/model/FullDuplexHttpChannel.java +++ b/core/src/main/java/hudson/model/FullDuplexHttpChannel.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.remoting.Channel; diff --git a/core/src/main/java/hudson/model/HealthReport.java b/core/src/main/java/hudson/model/HealthReport.java index de3cd5e028eb0..e5bb11319aa81 100644 --- a/core/src/main/java/hudson/model/HealthReport.java +++ b/core/src/main/java/hudson/model/HealthReport.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, Stephen Connolly - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import com.thoughtworks.xstream.converters.UnmarshallingContext; @@ -355,6 +356,7 @@ public static HealthReport max(HealthReport a, HealthReport b) { */ public static class ConverterImpl extends XStream2.PassthruConverter { public ConverterImpl(XStream2 xstream) { super(xstream); } + @Override protected void callback(HealthReport hr, UnmarshallingContext context) { // If we are being read back in from an older version if (hr.localizibleDescription == null) { diff --git a/core/src/main/java/hudson/model/HealthReportingAction.java b/core/src/main/java/hudson/model/HealthReportingAction.java index 024c9488725f7..b26277cc5143f 100644 --- a/core/src/main/java/hudson/model/HealthReportingAction.java +++ b/core/src/main/java/hudson/model/HealthReportingAction.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Stephen Connolly - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; /** @@ -42,7 +43,7 @@ public interface HealthReportingAction extends Action { * Get this {@link Action}'s {@link HealthReport}. * * @return - * The health report for this instance of the Action or + * The health report for this instance of the Action or * {@code null} if the Action does not want to * contribute a HealthReport. */ diff --git a/core/src/main/java/hudson/model/Hudson.java b/core/src/main/java/hudson/model/Hudson.java index f8b80787dfad8..784fa47da20e9 100644 --- a/core/src/main/java/hudson/model/Hudson.java +++ b/core/src/main/java/hudson/model/Hudson.java @@ -23,6 +23,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static hudson.Util.fixEmpty; @@ -74,11 +75,11 @@ public class Hudson extends Jenkins { @CLIResolver @Nullable public static Hudson getInstance() { - return (Hudson)Jenkins.get(); + return (Hudson) Jenkins.get(); } public Hudson(File root, ServletContext context) throws IOException, InterruptedException, ReactorException { - this(root,context,null); + this(root, context, null); } public Hudson(File root, ServletContext context, PluginManager pluginManager) throws IOException, InterruptedException, ReactorException { @@ -117,7 +118,7 @@ public CopyOnWriteList getComputerListeners() { public Slave getSlave(String name) { Node n = getNode(name); if (n instanceof Slave) - return (Slave)n; + return (Slave) n; return null; } @@ -127,7 +128,7 @@ public Slave getSlave(String name) { */ @Deprecated public List getSlaves() { - return (List)getNodes(); + return (List) getNodes(); } /** @@ -158,8 +159,8 @@ public TopLevelItem getJob(String name) { @Deprecated public TopLevelItem getJobCaseInsensitive(String name) { String match = Functions.toEmailSafeString(name); - for(TopLevelItem item : getItems()) { - if(Functions.toEmailSafeString(item.getName()).equalsIgnoreCase(match)) { + for (TopLevelItem item : getItems()) { + if (Functions.toEmailSafeString(item.getName()).equalsIgnoreCase(match)) { return item; } } @@ -183,9 +184,9 @@ public synchronized void doQuietDown(StaplerResponse rsp) throws IOException, Se * As on 1.267, moved to "/log/rss..." */ @Deprecated - public void doLogRss( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public void doLogRss(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { String qs = req.getQueryString(); - rsp.sendRedirect2("./log/rss"+(qs==null?"":'?'+qs)); + rsp.sendRedirect2("./log/rss" + (qs == null ? "" : '?' + qs)); } /** @@ -198,7 +199,7 @@ public void doFieldCheck(StaplerRequest req, StaplerResponse rsp) throws IOExcep fixEmpty(req.getParameter("value")), fixEmpty(req.getParameter("type")), fixEmpty(req.getParameter("errorText")), - fixEmpty(req.getParameter("warningText"))).generateResponse(req,rsp,this); + fixEmpty(req.getParameter("warningText"))).generateResponse(req, rsp, this); } /** @@ -215,10 +216,10 @@ public void doFieldCheck(StaplerRequest req, StaplerResponse rsp) throws IOExcep * or define your own check method, instead of relying on this generic one. */ @Deprecated - public FormValidation doFieldCheck(@QueryParameter(fixEmpty=true) String value, - @QueryParameter(fixEmpty=true) String type, - @QueryParameter(fixEmpty=true) String errorText, - @QueryParameter(fixEmpty=true) String warningText) { + public FormValidation doFieldCheck(@QueryParameter(fixEmpty = true) String value, + @QueryParameter(fixEmpty = true) String type, + @QueryParameter(fixEmpty = true) String errorText, + @QueryParameter(fixEmpty = true) String warningText) { if (value == null) { if (errorText != null) return FormValidation.error(errorText); @@ -252,7 +253,7 @@ public FormValidation doFieldCheck(@QueryParameter(fixEmpty=true) String value, */ @Deprecated public static boolean isWindows() { - return File.pathSeparatorChar==';'; + return File.pathSeparatorChar == ';'; } /** @@ -278,7 +279,7 @@ public static boolean adminCheck() throws IOException { * Use {@link #checkPermission(hudson.security.Permission)} */ @Deprecated - public static boolean adminCheck(StaplerRequest req,StaplerResponse rsp) throws IOException { + public static boolean adminCheck(StaplerRequest req, StaplerResponse rsp) throws IOException { if (isAdmin(req)) return true; rsp.sendError(HttpServletResponse.SC_FORBIDDEN); @@ -319,7 +320,7 @@ public static boolean isAdmin(StaplerRequest req) { } static { - XSTREAM.alias("hudson",Hudson.class); + XSTREAM.alias("hudson", Hudson.class); } /** diff --git a/core/src/main/java/hudson/model/InvisibleAction.java b/core/src/main/java/hudson/model/InvisibleAction.java index bb8c3b14ebe97..2f5ce02426323 100644 --- a/core/src/main/java/hudson/model/InvisibleAction.java +++ b/core/src/main/java/hudson/model/InvisibleAction.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; /** @@ -31,7 +32,7 @@ * {@link Action} for just storing data associated with a build. * *

      - * It could also be used to reduce the amount of code required to just create an accessible url for tests + * It could also be used to reduce the amount of code required to just create an accessible url for tests * by overriding the {@link #getUrlName()} method. * * @author Kohsuke Kawaguchi diff --git a/core/src/main/java/hudson/model/Item.java b/core/src/main/java/hudson/model/Item.java index 445c839984828..a57011579b154 100644 --- a/core/src/main/java/hudson/model/Item.java +++ b/core/src/main/java/hudson/model/Item.java @@ -1,19 +1,19 @@ /* * The MIT License - * + * * Copyright (c) 2004-2011, Sun Microsystems, Inc., Kohsuke Kawaguchi, Yahoo! Inc., * Manufacture Francaise des Pneumatiques Michelin, Romain Seguy - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,10 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; import hudson.Functions; import hudson.Util; import hudson.search.SearchableModelObject; @@ -39,7 +41,6 @@ import jenkins.model.Jenkins; import jenkins.util.SystemProperties; import jenkins.util.io.OnMaster; -import jline.internal.Nullable; import org.kohsuke.stapler.StaplerRequest; /** @@ -93,7 +94,7 @@ public interface Item extends PersistenceRoot, SearchableModelObject, AccessCont * This name is also used for directory name, so it cannot contain * any character that's not allowed on the file system. * - * @see #getFullName() + * @see #getFullName() */ String getName(); @@ -199,9 +200,9 @@ default String getRelativeNameFrom(@NonNull Item item) { @Deprecated default String getAbsoluteUrl() { String r = Jenkins.get().getRootUrl(); - if(r==null) + if (r == null) throw new IllegalStateException("Root URL isn't configured yet. Cannot compute absolute URL."); - return Util.encode(r+getUrl()); + return Util.encode(r + getUrl()); } /** @@ -248,7 +249,7 @@ default void onCreatedFromScratch() { */ void delete() throws IOException, InterruptedException; - PermissionGroup PERMISSIONS = new PermissionGroup(Item.class,Messages._Item_Permissions_Title()); + PermissionGroup PERMISSIONS = new PermissionGroup(Item.class, Messages._Item_Permissions_Title()); Permission CREATE = new Permission( PERMISSIONS, diff --git a/core/src/main/java/hudson/model/ItemGroup.java b/core/src/main/java/hudson/model/ItemGroup.java index 61989b1711c7b..6404e82626e1e 100644 --- a/core/src/main/java/hudson/model/ItemGroup.java +++ b/core/src/main/java/hudson/model/ItemGroup.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -44,12 +45,12 @@ public interface ItemGroup extends PersistenceRoot, ModelObject /** * Gets the full name of this {@link ItemGroup}. * - * @see Item#getFullName() + * @see Item#getFullName() */ String getFullName(); /** - * @see Item#getFullDisplayName() + * @see Item#getFullDisplayName() */ String getFullDisplayName(); diff --git a/core/src/main/java/hudson/model/ItemGroupMixIn.java b/core/src/main/java/hudson/model/ItemGroupMixIn.java index b1d52d9bfeeeb..748a13cc6ec4e 100644 --- a/core/src/main/java/hudson/model/ItemGroupMixIn.java +++ b/core/src/main/java/hudson/model/ItemGroupMixIn.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, CloudBees, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.Util; @@ -97,15 +98,15 @@ protected ItemGroupMixIn(ItemGroup parent, AccessControlled acl) { * @param modulesDir * Directory that contains sub-directories for each child item. */ - public static Map loadChildren(ItemGroup parent, File modulesDir, Function1 key) { + public static Map loadChildren(ItemGroup parent, File modulesDir, Function1 key) { try { - Files.createDirectories(modulesDir.toPath()); + Util.createDirectories(modulesDir.toPath()); } catch (IOException e) { throw new UncheckedIOException(e); } File[] subdirs = modulesDir.listFiles(File::isDirectory); - CopyOnWriteMap.Tree configurations = new CopyOnWriteMap.Tree<>(); + CopyOnWriteMap.Tree configurations = new CopyOnWriteMap.Tree<>(); for (File subdir : subdirs) { try { // Try to retain the identity of an existing child object if we can. @@ -133,13 +134,13 @@ public static Map loadChildren(ItemGroup parent, File mo /** * {@link Item} → name function. */ - public static final Function1 KEYED_BY_NAME = Item::getName; + public static final Function1 KEYED_BY_NAME = Item::getName; /** * Creates a {@link TopLevelItem} for example from the submission of the {@code /lib/hudson/newFromList/form} tag * or throws an exception if it fails. */ - public synchronized TopLevelItem createTopLevelItem( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public synchronized TopLevelItem createTopLevelItem(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { acl.checkPermission(Item.CREATE); TopLevelItem result; @@ -155,38 +156,38 @@ public synchronized TopLevelItem createTopLevelItem( StaplerRequest req, Stapler || requestContentType.startsWith("text/xml")); String name = req.getParameter("name"); - if(name==null) + if (name == null) throw new Failure("Query parameter 'name' is required"); - {// check if the name looks good + { // check if the name looks good Jenkins.checkGoodName(name); name = name.trim(); - if(parent.getItem(name)!=null) + if (parent.getItem(name) != null) throw new Failure(Messages.Hudson_JobAlreadyExists(name)); } - if(mode!=null && mode.equals("copy")) { + if (mode != null && mode.equals("copy")) { String from = req.getParameter("from"); // resolve a name to Item Item src = Jenkins.get().getItem(from, parent); - if(src==null) { - if(Util.fixEmpty(from)==null) + if (src == null) { + if (Util.fixEmpty(from) == null) throw new Failure("Specify which job to copy"); else - throw new Failure("No such job: "+from); + throw new Failure("No such job: " + from); } if (!(src instanceof TopLevelItem)) - throw new Failure(from+" cannot be copied"); + throw new Failure(from + " cannot be copied"); - result = copy((TopLevelItem) src,name); + result = copy((TopLevelItem) src, name); } else { - if(isXmlSubmission) { + if (isXmlSubmission) { result = createProjectFromXML(name, req.getInputStream()); rsp.setStatus(HttpServletResponse.SC_OK); return result; } else { - if(mode==null) + if (mode == null) throw new Failure("No mode given"); TopLevelItemDescriptor descriptor = Items.all().findByName(mode); if (descriptor == null) { @@ -208,7 +209,7 @@ public synchronized TopLevelItem createTopLevelItem( StaplerRequest req, Stapler * Computes the redirection target URL for the newly created {@link TopLevelItem}. */ protected String redirectAfterCreateItem(StaplerRequest req, TopLevelItem result) throws IOException { - return req.getContextPath()+'/'+result.getUrl()+"configure"; + return req.getContextPath() + '/' + result.getUrl() + "configure"; } /** @@ -239,7 +240,7 @@ public synchronized T copy(T src, String name) throws I Jenkins.checkGoodName(name); ItemListener.checkBeforeCopy(src, parent); - T result = (T)createProject(src.getDescriptor(),name,false); + T result = (T) createProject(src.getDescriptor(), name, false); // copy config Files.copy(Util.fileToPath(srcConfigFile.getFile()), Util.fileToPath(Items.getConfigFile(result).getFile()), @@ -247,7 +248,7 @@ public synchronized T copy(T src, String name) throws I // reload from the new config final File rootDir = result.getRootDir(); - result = Items.whileUpdatingByXml(new NotReallyRoleSensitiveCallable() { + result = Items.whileUpdatingByXml(new NotReallyRoleSensitiveCallable() { @Override public T call() throws IOException { return (T) Items.load(parent, rootDir); } @@ -255,7 +256,7 @@ public synchronized T copy(T src, String name) throws I result.onCopiedFrom(src); add(result); - ItemListener.fireOnCopied(src,result); + ItemListener.fireOnCopied(src, result); Jenkins.get().rebuildDependencyGraphAsync(); return result; @@ -273,11 +274,11 @@ public synchronized TopLevelItem createProjectFromXML(String name, InputStream x final File dir = configXml.getParentFile(); boolean success = false; try { - Files.createDirectories(dir.toPath()); + Util.createDirectories(dir.toPath()); XMLUtils.safeTransform(new StreamSource(xml), new StreamResult(configXml)); // load it - TopLevelItem result = Items.whileUpdatingByXml(new NotReallyRoleSensitiveCallable() { + TopLevelItem result = Items.whileUpdatingByXml(new NotReallyRoleSensitiveCallable() { @Override public TopLevelItem call() throws IOException { return (TopLevelItem) Items.load(parent, dir); } @@ -306,7 +307,7 @@ public synchronized TopLevelItem createProjectFromXML(String name, InputStream x } } - public synchronized TopLevelItem createProject( TopLevelItemDescriptor type, String name, boolean notify ) + public synchronized TopLevelItem createProject(TopLevelItemDescriptor type, String name, boolean notify) throws IOException { acl.checkPermission(Item.CREATE); type.checkApplicableIn(parent); diff --git a/core/src/main/java/hudson/model/ItemVisitor.java b/core/src/main/java/hudson/model/ItemVisitor.java index e33a6849b0eda..98e26c8023aa4 100644 --- a/core/src/main/java/hudson/model/ItemVisitor.java +++ b/core/src/main/java/hudson/model/ItemVisitor.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import jenkins.model.Jenkins; @@ -46,8 +47,8 @@ public void onItemGroup(ItemGroup group) { * visits the children. */ public void onItem(Item i) { - if(i instanceof ItemGroup) - onItemGroup((ItemGroup)i); + if (i instanceof ItemGroup) + onItemGroup((ItemGroup) i); } /** diff --git a/core/src/main/java/hudson/model/Items.java b/core/src/main/java/hudson/model/Items.java index ddb33a4e85050..7bda39bc8032d 100644 --- a/core/src/main/java/hudson/model/Items.java +++ b/core/src/main/java/hudson/model/Items.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import com.thoughtworks.xstream.XStream; @@ -53,12 +54,11 @@ import jenkins.model.Jenkins; import jenkins.util.MemoryReductionUtil; import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.StringUtils; import org.springframework.security.core.Authentication; /** * Convenience methods related to {@link Item}. - * + * * @author Kohsuke Kawaguchi */ public class Items { @@ -126,7 +126,7 @@ String name(Item i) { * @throws T anything {@code callable} throws * @since 1.546 */ - public static V whileUpdatingByXml(Callable callable) throws T { + public static V whileUpdatingByXml(Callable callable) throws T { updatingByXml.set(true); try { return callable.call(); @@ -148,7 +148,7 @@ public static boolean currentlyUpdatingByXml() { /** * Returns all the registered {@link TopLevelItemDescriptor}s. */ - public static DescriptorExtensionList all() { + public static DescriptorExtensionList all() { return Jenkins.get().getDescriptorList(TopLevelItem.class); } @@ -177,7 +177,7 @@ public static List all2(Authentication a, ItemGroup c) { // fall back to root acl = Jenkins.get().getACL(); } - for (TopLevelItemDescriptor d: all()) { + for (TopLevelItemDescriptor d : all()) { if (acl.hasCreatePermission2(a, c, d) && d.isApplicableIn(c)) { result.add(d); } @@ -208,7 +208,7 @@ public static TopLevelItemDescriptor getDescriptor(String fqcn) { public static String toNameList(Collection items) { StringBuilder buf = new StringBuilder(); for (Item item : items) { - if(buf.length()>0) + if (buf.length() > 0) buf.append(", "); buf.append(item.getFullName()); } @@ -221,7 +221,7 @@ public static String toNameList(Collection items) { */ @Deprecated public static List fromNameList(String list, Class type) { - return fromNameList(null,list,type); + return fromNameList(null, list, type); } /** @@ -229,15 +229,15 @@ public static List fromNameList(String list, Class type) */ public static List fromNameList(ItemGroup context, @NonNull String list, @NonNull Class type) { final Jenkins jenkins = Jenkins.get(); - + List r = new ArrayList<>(); - StringTokenizer tokens = new StringTokenizer(list,","); - while(tokens.hasMoreTokens()) { + StringTokenizer tokens = new StringTokenizer(list, ","); + while (tokens.hasMoreTokens()) { String fullName = tokens.nextToken().trim(); - if (StringUtils.isNotEmpty(fullName)) { + if (fullName != null && !fullName.isEmpty()) { T item = jenkins.getItem(fullName, context, type); - if(item!=null) + if (item != null) r.add(item); } } @@ -254,12 +254,12 @@ public static String getCanonicalName(ItemGroup context, String path) { String[] p = path.split("/"); Stack name = new Stack<>(); - for (int i=0; i newValue = new ArrayList<>(); - while(tokens.hasMoreTokens()) { + while (tokens.hasMoreTokens()) { String relativeName = tokens.nextToken().trim(); String canonicalName = getCanonicalName(context, relativeName); - if (canonicalName.equals(oldFullName) || canonicalName.startsWith(oldFullName+'/')) { + if (canonicalName.equals(oldFullName) || canonicalName.startsWith(oldFullName + '/')) { String newCanonicalName = newFullName + canonicalName.substring(oldFullName.length()); if (relativeName.startsWith("/")) { newValue.add("/" + newCanonicalName); @@ -372,8 +372,8 @@ static String getRelativeNameFrom(String itemFullName, String groupFullName) { * The directory that contains the config file, not the config file itself. */ public static Item load(ItemGroup parent, File dir) throws IOException { - Item item = (Item)getConfigFile(dir).read(); - item.onLoad(parent,dir.getName()); + Item item = (Item) getConfigFile(dir).read(); + item.onLoad(parent, dir.getName()); return item; } @@ -381,7 +381,7 @@ public static Item load(ItemGroup parent, File dir) throws IOException { * The file we save our configuration. */ public static XmlFile getConfigFile(File dir) { - return new XmlFile(XSTREAM,new File(dir,"config.xml")); + return new XmlFile(XSTREAM, new File(dir, "config.xml")); } /** @@ -390,7 +390,7 @@ public static XmlFile getConfigFile(File dir) { public static XmlFile getConfigFile(Item item) { return getConfigFile(item.getRootDir()); } - + /** * Gets all the {@link Item}s recursively in the {@link ItemGroup} tree * and filter them by the given type. The returned list will represent a snapshot view of the items present at some @@ -403,11 +403,11 @@ public static XmlFile getConfigFile(Item item) { * @param root Root node to start searching from * @param type Given type of of items being searched for * @return List of items matching given criteria - * + * * @since 1.512 */ public static List getAllItems(final ItemGroup root, Class type) { - return getAllItems(root ,type, t -> true); + return getAllItems(root, type, t -> true); } /** @@ -425,6 +425,7 @@ public static List getAllItems(final ItemGroup root, Class void getAllItems(final ItemGroup root, Class type, List r, Predicate pred) { List items = new ArrayList<>(((ItemGroup) root).getItems(t -> t instanceof ItemGroup || (type.isInstance(t) && pred.test(type.cast(t))))); // because we add items depth first, we can use the quicker BY_NAME comparison @@ -542,7 +543,7 @@ public static Iterable allItems(org.acegisecurity.Authentica */ public static @CheckForNull T findNearest(Class type, String name, ItemGroup context) { List names = new ArrayList<>(); - for (T item: Jenkins.get().allItems(type)) { + for (T item : Jenkins.get().allItems(type)) { names.add(item.getRelativeNameFrom(context)); } String nearest = EditDistance.findNearest(name, names); @@ -727,9 +728,9 @@ static void verifyItemDoesNotAlreadyExist(@NonNull ItemGroup parent, @NonNull /** * Alias to {@link #XSTREAM} so that one can access additional methods on {@link XStream2} more easily. */ - public static final XStream2 XSTREAM2 = (XStream2)XSTREAM; + public static final XStream2 XSTREAM2 = (XStream2) XSTREAM; static { - XSTREAM.alias("project",FreeStyleProject.class); + XSTREAM.alias("project", FreeStyleProject.class); } } diff --git a/core/src/main/java/hudson/model/JDK.java b/core/src/main/java/hudson/model/JDK.java index 1eeafbbc66829..0c9bcbda493d6 100644 --- a/core/src/main/java/hudson/model/JDK.java +++ b/core/src/main/java/hudson/model/JDK.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.EnvVars; @@ -103,14 +104,15 @@ public String getJavaHome() { * Gets the path to the bin directory. */ public File getBinDir() { - return new File(getHome(),"bin"); + return new File(getHome(), "bin"); } /** * Gets the path to 'java'. */ + private File getExecutable() { String execName = File.separatorChar == '\\' ? "java.exe" : "java"; - return new File(getHome(),"bin/"+execName); + return new File(getHome(), "bin/" + execName); } /** @@ -124,13 +126,13 @@ public boolean getExists() { * @deprecated as of 1.460. Use {@link #buildEnvVars(EnvVars)} */ @Deprecated - public void buildEnvVars(Map env) { + public void buildEnvVars(Map env) { String home = getHome(); if (home == null) { return; } // see EnvVars javadoc for why this adds PATH. - env.put("PATH+JDK",home+"/bin"); + env.put("PATH+JDK", home + "/bin"); env.put("JAVA_HOME", home); } @@ -139,7 +141,7 @@ public void buildEnvVars(Map env) { */ @Override public void buildEnvVars(EnvVars env) { - buildEnvVars((Map)env); + buildEnvVars((Map) env); } @Override @@ -163,7 +165,7 @@ public static boolean isDefaultJDKValid(Node n) { try { TaskListener listener = new StreamTaskListener(new NullStream()); Launcher launcher = n.createLauncher(listener); - return launcher.launch().cmds("java","-fullversion").stdout(listener).join()==0; + return launcher.launch().cmds("java", "-fullversion").stdout(listener).join() == 0; } catch (IOException | InterruptedException e) { return false; } @@ -206,13 +208,13 @@ public List getDefaultInstallers() { * Checks if the JAVA_HOME is a valid JAVA_HOME path. */ @Override protected FormValidation checkHomeDirectory(File value) { - File toolsJar = new File(value,"lib/tools.jar"); - File mac = new File(value,"lib/dt.jar"); + 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()) + if (!toolsJar.exists() && !mac.exists() && !javac.exists() && !javacExe.exists()) return FormValidation.error(Messages.Hudson_NotJDKDir(value)); return FormValidation.ok(); @@ -222,8 +224,9 @@ public List getDefaultInstallers() { public static class ConverterImpl extends ToolConverter { public ConverterImpl(XStream2 xstream) { super(xstream); } + @Override protected String oldHomeField(ToolInstallation obj) { - return ((JDK)obj).javaHome; + return ((JDK) obj).javaHome; } } diff --git a/core/src/main/java/hudson/model/Job.java b/core/src/main/java/hudson/model/Job.java index 8458722c1ffbc..6fab17d419f07 100644 --- a/core/src/main/java/hudson/model/Job.java +++ b/core/src/main/java/hudson/model/Job.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Martin Eigenbrodt, Matthew R. Harrah, Red Hat, Inc., Stephen Connolly, Tom Huybrechts, CloudBees, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; @@ -123,7 +124,7 @@ /** * A job is an runnable entity under the monitoring of Hudson. - * + * *

      * Every time it "runs", it will be recorded as a {@link Run} object. * @@ -132,7 +133,6 @@ * * @author Kohsuke Kawaguchi */ -@SuppressFBWarnings(value = "SE_BAD_FIELD", justification = "TODO needs triage") public abstract class Job, RunT extends Run> extends AbstractItem implements ExtensionPoint, StaplerOverridable, ModelObjectWithChildren { @@ -303,16 +303,16 @@ public Queue.Item getQueueItem() { */ public boolean isBuilding() { RunT b = getLastBuild(); - return b!=null && b.isBuilding(); + return b != null && b.isBuilding(); } - + /** * Returns true if the log file is still being updated. */ public boolean isLogUpdated() { RunT b = getLastBuild(); - return b!=null && b.isLogUpdated(); - } + return b != null && b.isLogUpdated(); + } @Override public String getPronoun() { @@ -359,9 +359,9 @@ public int getNextBuildNumber() { */ public EnvVars getCharacteristicEnvVars() { EnvVars env = new EnvVars(); - env.put("JENKINS_SERVER_COOKIE",SERVER_COOKIE.get()); - env.put("HUDSON_SERVER_COOKIE",SERVER_COOKIE.get()); // Legacy compatibility - env.put("JOB_NAME",getFullName()); + env.put("JENKINS_SERVER_COOKIE", SERVER_COOKIE.get()); + env.put("HUDSON_SERVER_COOKIE", SERVER_COOKIE.get()); // Legacy compatibility + env.put("JOB_NAME", getFullName()); env.put("JOB_BASE_NAME", getName()); return env; } @@ -383,7 +383,7 @@ public EnvVars getCharacteristicEnvVars() { if (node != null) { final Computer computer = node.toComputer(); if (computer != null) { - // we need to get computer environment to inherit platform details + // we need to get computer environment to inherit platform details env = computer.getEnvironment(); env.putAll(computer.buildEnvironment(listener)); } @@ -394,11 +394,11 @@ public EnvVars getCharacteristicEnvVars() { // servlet container may have set CLASSPATH in its launch script, // so don't let that inherit to the new child process. // see http://www.nabble.com/Run-Job-with-JDK-1.4.2-tf4468601.html - env.put("CLASSPATH",""); + env.put("CLASSPATH", ""); // apply them in a reverse order so that higher ordinal ones can modify values added by lower ordinal ones for (EnvironmentContributor ec : EnvironmentContributor.all().reverseView()) - ec.buildEnvironmentFor(this,env,listener); + ec.buildEnvironmentFor(this, env, listener); return env; @@ -406,17 +406,17 @@ public EnvVars getCharacteristicEnvVars() { /** * Programmatically updates the next build number. - * + * *

      * Much of Hudson assumes that the build number is unique and monotonic, so * this method can only accept a new value that's bigger than * {@link #getLastBuild()} returns. Otherwise it'll be no-op. - * + * * @since 1.199 (before that, this method was package private.) */ public synchronized void updateNextBuildNumber(int next) throws IOException { RunT lb = getLastBuild(); - if (lb!=null ? next>lb.getNumber() : next>0) { + if (lb != null ? next > lb.getNumber() : next > 0) { this.nextBuildNumber = next; saveNextBuildNumber(); } @@ -505,16 +505,16 @@ public boolean supportsLogRotator() { @Override public Collection getAllJobs() { - return Collections. singleton(this); + return Collections.singleton(this); } /** * Adds {@link JobProperty}. - * + * * @since 1.188 */ public void addProperty(JobProperty jobProp) throws IOException { - ((JobProperty)jobProp).setOwner(this); + ((JobProperty) jobProp).setOwner(this); properties.add(jobProp); save(); } @@ -562,7 +562,7 @@ public Map> getProperties() { * List of all {@link JobProperty} exposed primarily for the remoting API. * @since 1.282 */ - @Exported(name="property",inline=true) + @Exported(name = "property", inline = true) public List> getAllProperties() { return properties.getView(); } @@ -664,7 +664,7 @@ public void renameTo(String newName) throws IOException { super.renameTo(newName); File newBuildDir = getBuildDir(); if (Files.isDirectory(Util.fileToPath(oldBuildDir)) && !Files.isDirectory(Util.fileToPath(newBuildDir))) { - Files.createDirectories(Util.fileToPath(newBuildDir.getParentFile())); + Util.createDirectories(Util.fileToPath(newBuildDir.getParentFile())); Files.move(Util.fileToPath(oldBuildDir), Util.fileToPath(newBuildDir)); } } @@ -691,7 +691,7 @@ public static class SubItemBuildsLocationImpl extends ItemListener { public void onLocationChanged(Item item, String oldFullName, String newFullName) { final Jenkins jenkins = Jenkins.get(); if (!jenkins.isDefaultBuildDir() && item instanceof Job) { - File newBuildDir = ((Job)item).getBuildDir(); + File newBuildDir = ((Job) item).getBuildDir(); try { if (!Util.isDescendant(item.getRootDir(), newBuildDir)) { //OK builds are stored somewhere outside of the item's root, so none of the other move operations has probably moved it. @@ -726,10 +726,10 @@ public void onLocationChanged(Item item, String oldFullName, String newFullName) /** * Gets the read-only view of all the builds. - * + * * @return never null. The first entry is the latest build. */ - @Exported(name="allBuilds",visibility=-2) + @Exported(name = "allBuilds", visibility = -2) @WithBridgeMethods(List.class) public RunList getBuilds() { return RunList.fromRuns(_getRuns().values()); @@ -740,7 +740,7 @@ public RunList getBuilds() { * * @since 1.485 */ - @Exported(name="builds") + @Exported(name = "builds") public RunList getNewBuilds() { return getBuilds().limit(100); } @@ -752,7 +752,7 @@ public synchronized List getBuilds(RangeSet rs) { List builds = new ArrayList<>(); for (Range r : rs.getRanges()) { - for (RunT b = getNearestBuild(r.start); b!=null && b.getNumber() getBuildsByTimestamp(long start, long end) { - return getBuilds().byTimestamp(start,end); + return getBuilds().byTimestamp(start, end); } @CLIResolver - public RunT getBuildForCLI(@Argument(required=true,metaVar="BUILD#",usage="Build number") String id) throws CmdLineException { + public RunT getBuildForCLI(@Argument(required = true, metaVar = "BUILD#", usage = "Build number") String id) throws CmdLineException { try { int n = Integer.parseInt(id); RunT r = getBuildByNumber(n); - if (r==null) - throw new CmdLineException(null, "No such build '#"+n+"' exists"); + if (r == null) + throw new CmdLineException(null, "No such build '#" + n + "' exists"); return r; } catch (NumberFormatException e) { - throw new CmdLineException(null, id+ "is not a number", e); + throw new CmdLineException(null, id + "is not a number", e); } } /** * Gets the youngest build #m that satisfies {@code n<=m}. - * + * * This is useful when you'd like to fetch a build but the exact build might * be already gone (deleted, rotated, etc.) * @see LazyBuildMixIn#getNearestBuild @@ -833,7 +833,7 @@ public RunT getNearestBuild(int n) { /** * Gets the latest build #m that satisfies {@code m<=n}. - * + * * This is useful when you'd like to fetch a build but the exact build might * be already gone (deleted, rotated, etc.) * @see LazyBuildMixIn#getNearestOldBuild @@ -860,7 +860,7 @@ public Object getDynamic(String token, StaplerRequest req, // is this a permalink? for (Permalink p : getPermalinks()) { - if(p.getId().equals(token)) + if (p.getId().equals(token)) return p.resolve(this); } @@ -874,7 +874,7 @@ public Object getDynamic(String token, StaplerRequest req, * Some {@link Job}s may not have backing data store for {@link Run}s, but * those {@link Job}s that use file system for storing data should use this * directory for consistency. - * + * * @see RunMap */ public File getBuildDir() { @@ -890,7 +890,7 @@ public File getBuildDir() { /** * Gets all the runs. - * + * * The resulting map must be treated immutable (by employing copy-on-write * semantics.) The map is descending order, with newest builds at the top. * @see LazyBuildMixIn#_getRuns @@ -899,7 +899,7 @@ public File getBuildDir() { /** * Called from {@link Run} to remove it from this job. - * + * * The files are deleted already. So all the callee needs to do is to remove * a reference from this {@link Job}. * @see LazyBuildMixIn#removeRun @@ -937,13 +937,13 @@ public RunT getFirstBuild() { /** * Returns the last successful build, if any. Otherwise null. A successful build * would include either {@link Result#SUCCESS} or {@link Result#UNSTABLE}. - * + * * @see #getLastStableBuild() */ @Exported @QuickSilver public RunT getLastSuccessfulBuild() { - return (RunT)Permalink.LAST_SUCCESSFUL_BUILD.resolve(this); + return (RunT) Permalink.LAST_SUCCESSFUL_BUILD.resolve(this); } /** @@ -953,7 +953,7 @@ public RunT getLastSuccessfulBuild() { @Exported @QuickSilver public RunT getLastUnsuccessfulBuild() { - return (RunT)Permalink.LAST_UNSUCCESSFUL_BUILD.resolve(this); + return (RunT) Permalink.LAST_UNSUCCESSFUL_BUILD.resolve(this); } /** @@ -963,7 +963,7 @@ public RunT getLastUnsuccessfulBuild() { @Exported @QuickSilver public RunT getLastUnstableBuild() { - return (RunT)Permalink.LAST_UNSTABLE_BUILD.resolve(this); + return (RunT) Permalink.LAST_UNSTABLE_BUILD.resolve(this); } /** @@ -973,7 +973,7 @@ public RunT getLastUnstableBuild() { @Exported @QuickSilver public RunT getLastStableBuild() { - return (RunT)Permalink.LAST_STABLE_BUILD.resolve(this); + return (RunT) Permalink.LAST_STABLE_BUILD.resolve(this); } /** @@ -982,7 +982,7 @@ public RunT getLastStableBuild() { @Exported @QuickSilver public RunT getLastFailedBuild() { - return (RunT)Permalink.LAST_FAILED_BUILD.resolve(this); + return (RunT) Permalink.LAST_FAILED_BUILD.resolve(this); } /** @@ -991,12 +991,12 @@ public RunT getLastFailedBuild() { @Exported @QuickSilver public RunT getLastCompletedBuild() { - return (RunT)Permalink.LAST_COMPLETED_BUILD.resolve(this); + return (RunT) Permalink.LAST_COMPLETED_BUILD.resolve(this); } - + /** * Returns the last {@code numberOfBuilds} builds with a build result ≥ {@code threshold} - * + * * @return a list with the builds. May be smaller than 'numberOfBuilds' or even empty * if not enough builds satisfying the threshold have been found. Never null. */ @@ -1004,13 +1004,13 @@ public List getLastBuildsOverThreshold(int numberOfBuilds, Result threshol RunT r = getLastBuild(); return r.getBuildsOverThreshold(numberOfBuilds, threshold); } - + /** * Returns candidate build for calculating the estimated duration of the current run. - * + * * Returns the 3 last successful (stable or unstable) builds, if there are any. * Failing to find 3 of those, it will return up to 3 last unsuccessful builds. - * + * * In any case it will not go more than 6 builds into the past to avoid costly build loading. */ protected List getEstimatedDurationCandidates() { @@ -1037,29 +1037,29 @@ protected List getEstimatedDurationCandidates() { i++; r = r.getPreviousBuild(); } - + while (candidates.size() < 3) { if (fallbackCandidates.isEmpty()) break; RunT run = fallbackCandidates.remove(0); candidates.add(run); } - + return candidates; } - + public long getEstimatedDuration() { List builds = getEstimatedDurationCandidates(); - - if(builds.isEmpty()) return -1; + + if (builds.isEmpty()) return -1; long totalDuration = 0; for (RunT b : builds) { totalDuration += b.getDuration(); } - if(totalDuration==0) return -1; + if (totalDuration == 0) return -1; - return Math.round((double)totalDuration / builds.size()); + return Math.round((double) totalDuration / builds.size()); } /** @@ -1110,7 +1110,7 @@ class FeedItem { for (RunT r = getLastBuild(); r != null; r = r.getPreviousBuild()) { int idx = 0; if (r instanceof RunWithSCM) { - for (ChangeLogSet c : ((RunWithSCM) r).getChangeSets()) { + for (ChangeLogSet c : ((RunWithSCM) r).getChangeSets()) { for (ChangeLogSet.Entry e : c) { entries.add(new FeedItem(e, idx++)); } @@ -1188,7 +1188,7 @@ public BallColor getIconColor() { /** * Get the current health report for a job. - * + * * @return the health report. Never returns null */ public HealthReport getBuildHealth() { @@ -1334,7 +1334,7 @@ public synchronized void doConfigSubmit(StaplerRequest req, DescribableList, JobPropertyDescriptor> t = new DescribableList<>(NOOP, getAllProperties()); JSONObject jsonProperties = json.optJSONObject("properties"); if (jsonProperties != null) { - t.rebuild(req,jsonProperties,JobPropertyDescriptor.getPropertyDescriptors(Job.this.getClass())); + t.rebuild(req, jsonProperties, JobPropertyDescriptor.getPropertyDescriptors(Job.this.getClass())); } else { t.clear(); } @@ -1350,7 +1350,7 @@ public synchronized void doConfigSubmit(StaplerRequest req, ItemListener.fireOnUpdated(this); final ProjectNamingStrategy namingStrategy = Jenkins.get().getProjectNamingStrategy(); - if(namingStrategy.isForceExistingJobs()){ + if (namingStrategy.isForceExistingJobs()) { namingStrategy.checkName(name); } FormApply.success(".").generateResponse(req, rsp, null); @@ -1410,65 +1410,91 @@ public String getBuildStatusIconClassName() { return getIconColor().getIconClassName(); } - public Graph getBuildTimeGraph() { - return new Graph(getLastBuildTime(),500,400) { - @Override - protected JFreeChart createGraph() { - class ChartLabel implements Comparable { - final Run run; + private static class ChartLabel implements Comparable { + final Run run; - ChartLabel(Run r) { - this.run = r; - } + ChartLabel(Run r) { + this.run = r; + } - @Override - public int compareTo(ChartLabel that) { - return this.run.number - that.run.number; - } + @Override + public int compareTo(ChartLabel that) { + return this.run.number - that.run.number; + } - @Override - public boolean equals(Object o) { - // JENKINS-2682 workaround for Eclipse compilation bug - // on (c instanceof ChartLabel) - if (o == null || !ChartLabel.class.isAssignableFrom( o.getClass() )) { - return false; - } - ChartLabel that = (ChartLabel) o; - return run == that.run; - } + @Override + public boolean equals(Object o) { + // JENKINS-2682 workaround for Eclipse compilation bug + // on (c instanceof ChartLabel) + if (o == null || !ChartLabel.class.isAssignableFrom(o.getClass())) { + return false; + } + ChartLabel that = (ChartLabel) o; + return run == that.run; + } - public Color getColor() { - // TODO: consider gradation. See - // http://www.javadrive.jp/java2d/shape/index9.html - Result r = run.getResult(); - if (r == Result.FAILURE) - return ColorPalette.RED; - else if (r == Result.UNSTABLE) - return ColorPalette.YELLOW; - else if (r == Result.ABORTED || r == Result.NOT_BUILT) - return ColorPalette.GREY; - else - return ColorPalette.BLUE; - } + public Color getColor() { + // TODO: consider gradation. See + // http://www.javadrive.jp/java2d/shape/index9.html + Result r = run.getResult(); + if (r == Result.FAILURE) + return ColorPalette.RED; + else if (r == Result.UNSTABLE) + return ColorPalette.YELLOW; + else if (r == Result.ABORTED || r == Result.NOT_BUILT) + return ColorPalette.GREY; + else + return ColorPalette.BLUE; + } - @Override - public int hashCode() { - return run.hashCode(); - } + @Override + public int hashCode() { + return run.hashCode(); + } - @Override - public String toString() { - String l = run.getDisplayName(); - if (run instanceof Build) { - String s = ((Build) run).getBuiltOnStr(); - if (s != null) - l += ' ' + s; - } - return l; - } + @Override + public String toString() { + String l = run.getDisplayName(); + if (run instanceof Build) { + String s = ((Build) run).getBuiltOnStr(); + if (s != null) + l += ' ' + s; + } + return l; + } + } - } + @SuppressFBWarnings(value = "EQ_DOESNT_OVERRIDE_EQUALS", justification = "category dataset is only relevant for coloring, not equality") + private static class ChartLabelStackedAreaRenderer2 extends StackedAreaRenderer2 { + private final CategoryDataset categoryDataset; + + ChartLabelStackedAreaRenderer2(CategoryDataset categoryDataset) { + this.categoryDataset = categoryDataset; + } + + @Override + public Paint getItemPaint(int row, int column) { + ChartLabel key = (ChartLabel) categoryDataset.getColumnKey(column); + return key.getColor(); + } + + @Override + public String generateURL(CategoryDataset dataset, int row, int column) { + ChartLabel label = (ChartLabel) dataset.getColumnKey(column); + return String.valueOf(label.run.number); + } + @Override + public String generateToolTip(CategoryDataset dataset, int row, int column) { + ChartLabel label = (ChartLabel) dataset.getColumnKey(column); + return label.run.getDisplayName() + " : " + label.run.getDurationString(); + } + } + + public Graph getBuildTimeGraph() { + return new Graph(getLastBuildTime(), 500, 400) { + @Override + protected JFreeChart createGraph() { DataSetBuilder data = new DataSetBuilder<>(); for (Run r : getNewBuilds()) { if (r.isBuilding()) @@ -1512,28 +1538,7 @@ public String toString() { ChartUtil.adjustChebyshev(dataset, rangeAxis); rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); - StackedAreaRenderer ar = new StackedAreaRenderer2() { - @Override - public Paint getItemPaint(int row, int column) { - ChartLabel key = (ChartLabel) dataset.getColumnKey(column); - return key.getColor(); - } - - @Override - public String generateURL(CategoryDataset dataset, int row, - int column) { - ChartLabel label = (ChartLabel) dataset.getColumnKey(column); - return String.valueOf(label.run.number); - } - - @Override - public String generateToolTip(CategoryDataset dataset, int row, - int column) { - ChartLabel label = (ChartLabel) dataset.getColumnKey(column); - return label.run.getDisplayName() + " : " - + label.run.getDurationString(); - } - }; + StackedAreaRenderer ar = new ChartLabelStackedAreaRenderer2(dataset); plot.setRenderer(ar); // crop extra space around the graph @@ -1546,7 +1551,7 @@ public String generateToolTip(CategoryDataset dataset, int row, private Calendar getLastBuildTime() { final RunT lastBuild = getLastBuild(); - if (lastBuild ==null) { + if (lastBuild == null) { final GregorianCalendar neverBuiltCalendar = new GregorianCalendar(); neverBuiltCalendar.setTimeInMillis(0); return neverBuiltCalendar; @@ -1598,5 +1603,5 @@ public BuildTimelineWidget getTimeline() { return new BuildTimelineWidget(getBuilds()); } - private static final HexStringConfidentialKey SERVER_COOKIE = new HexStringConfidentialKey(Job.class,"serverCookie",16); + private static final HexStringConfidentialKey SERVER_COOKIE = new HexStringConfidentialKey(Job.class, "serverCookie", 16); } diff --git a/core/src/main/java/hudson/model/JobProperty.java b/core/src/main/java/hudson/model/JobProperty.java index b4d5772cc3235..fe02891987e9f 100644 --- a/core/src/main/java/hudson/model/JobProperty.java +++ b/core/src/main/java/hudson/model/JobProperty.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.NonNull; @@ -67,14 +68,14 @@ * @param * When you restrict your job property to be only applicable to a certain * subtype of {@link Job}, you can use this type parameter to improve - * the type signature of this class. See {@link JobPropertyDescriptor#isApplicable(Class)}. + * the type signature of this class. See {@link JobPropertyDescriptor#isApplicable(Class)}. * * @author Kohsuke Kawaguchi * @see JobPropertyDescriptor * @since 1.72 */ @ExportedBean -public abstract class JobProperty> implements ReconfigurableDescribable>, BuildStep, ExtensionPoint { +public abstract class JobProperty> implements ReconfigurableDescribable>, BuildStep, ExtensionPoint { /** * The {@link Job} object that owns this property. * This value will be set by the Hudson code. @@ -132,7 +133,7 @@ public Action getJobAction(J job) { public Collection getJobActions(J job) { // delegate to getJobAction (singular) for backward compatible behavior Action a = getJobAction(job); - if (a==null) return Collections.emptyList(); + if (a == null) return Collections.emptyList(); return Collections.singletonList(a); } @@ -141,7 +142,7 @@ public Collection getJobActions(J job) { // @Override - public boolean prebuild(AbstractBuild build, BuildListener listener) { + public boolean prebuild(AbstractBuild build, BuildListener listener) { return true; } @@ -152,7 +153,7 @@ public boolean prebuild(AbstractBuild build, BuildListener listener) { * Invoked after {@link Publisher}s have run. */ @Override - public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { return true; } @@ -166,14 +167,14 @@ public BuildStepMonitor getRequiredMonitorService() { } @Override - public final Action getProjectAction(AbstractProject project) { - return getJobAction((J)project); + public final Action getProjectAction(AbstractProject project) { + return getJobAction((J) project); } @Override @NonNull - public final Collection getProjectActions(AbstractProject project) { - return getJobActions((J)project); + public final Collection getProjectActions(AbstractProject project) { + return getJobActions((J) project); } /** @see Job#getOverrides */ @@ -183,7 +184,7 @@ public Collection getJobOverrides() { @Override public JobProperty reconfigure(StaplerRequest req, JSONObject form) throws FormException { - return form==null ? null : getDescriptor().newInstance(req,form); + return form == null ? null : getDescriptor().newInstance(req, form); } /** diff --git a/core/src/main/java/hudson/model/JobPropertyDescriptor.java b/core/src/main/java/hudson/model/JobPropertyDescriptor.java index 36f781b67ba18..1f1c3aa7e6f07 100644 --- a/core/src/main/java/hudson/model/JobPropertyDescriptor.java +++ b/core/src/main/java/hudson/model/JobPropertyDescriptor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import java.lang.reflect.ParameterizedType; @@ -36,7 +37,7 @@ /** * {@link Descriptor} for {@link JobProperty}. - * + * * @author Kohsuke Kawaguchi * @since 1.72 */ @@ -62,8 +63,8 @@ protected JobPropertyDescriptor() { @Override public JobProperty newInstance(StaplerRequest req, JSONObject formData) throws FormException { // JobPropertyDescriptors are bit different in that we allow them even without any user-visible configuration parameter, - // so replace the lack of form data by an empty one. - if(formData.isNullObject()) formData=new JSONObject(); + // so replace the lack of form data by an empty one. + if (formData.isNullObject()) formData = new JSONObject(); return super.newInstance(req, formData); } @@ -71,7 +72,7 @@ public JobProperty newInstance(StaplerRequest req, JSONObject formData) throw /** * Returns true if this {@link JobProperty} type is applicable to the * given job type. - * + * *

      * The default implementation of this method checks if the given job type is assignable to {@code J} of * {@link JobProperty}{@code }, but subtypes can extend this to change this behavior. @@ -87,7 +88,7 @@ public boolean isApplicable(Class jobType) { Class applicable = Types.erasure(Types.getTypeArgument(pt, 0)); return applicable.isAssignableFrom(jobType); } else { - throw new AssertionError(clazz+" doesn't properly parameterize JobProperty. The isApplicable() method must be overridden."); + throw new AssertionError(clazz + " doesn't properly parameterize JobProperty. The isApplicable() method must be overridden."); } } @@ -97,7 +98,7 @@ public boolean isApplicable(Class jobType) { public static List getPropertyDescriptors(Class clazz) { List r = new ArrayList<>(); for (JobPropertyDescriptor p : all()) - if(p.isApplicable(clazz)) + if (p.isApplicable(clazz)) r.add(p); return r; } diff --git a/core/src/main/java/hudson/model/Jobs.java b/core/src/main/java/hudson/model/Jobs.java index 63117247d2260..a9452f68d8a92 100644 --- a/core/src/main/java/hudson/model/Jobs.java +++ b/core/src/main/java/hudson/model/Jobs.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.Extension; @@ -29,7 +30,7 @@ /** * List of all installed {@link Job} types. - * + * * @author Kohsuke Kawaguchi * @deprecated since 1.281 */ @@ -49,5 +50,5 @@ public class Jobs { */ @Deprecated public static final List PROPERTIES = (List) - new DescriptorList>((Class)JobProperty.class); + new DescriptorList>((Class) JobProperty.class); } diff --git a/core/src/main/java/hudson/model/Label.java b/core/src/main/java/hudson/model/Label.java index 0e38b876f8a70..12426e8ba9e6a 100644 --- a/core/src/main/java/hudson/model/Label.java +++ b/core/src/main/java/hudson/model/Label.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static hudson.Util.fixNull; @@ -31,6 +32,7 @@ import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Util; import hudson.model.labels.LabelAtom; @@ -100,7 +102,7 @@ public abstract class Label extends Actionable implements Comparable

      - * If you are a {@link BuildStep}, most likely you should call {@link AbstractBuild#getBuildVariableResolver()}. + * If you are a {@link BuildStep}, most likely you should call {@link AbstractBuild#getBuildVariableResolver()}. */ - public VariableResolver createVariableResolver(AbstractBuild build) { - VariableResolver[] resolvers = new VariableResolver[getParameters().size()+1]; - int i=0; + public VariableResolver createVariableResolver(AbstractBuild build) { + VariableResolver[] resolvers = new VariableResolver[getParameters().size() + 1]; + int i = 0; for (ParameterValue p : getParameters()) { if (p == null) continue; resolvers[i++] = p.createVariableResolver(build); } - + resolvers[i] = build.getBuildVariableResolver(); return new VariableResolver.Union(resolvers); } - + @Override public Iterator iterator() { return getParameters().iterator(); } - @Exported(visibility=2) + @Exported(visibility = 2) public List getParameters() { return Collections.unmodifiableList(filter(parameters)); } @@ -195,7 +196,7 @@ public Label getAssignedLabel(SubTask task) { for (ParameterValue p : getParameters()) { if (p == null) continue; Label l = p.getAssignedLabel(task); - if (l!=null) return l; + if (l != null) return l; } return null; } @@ -226,7 +227,7 @@ public boolean shouldSchedule(List actions) { } else { // I don't think we need multiple ParametersActions, but let's be defensive Set params = new HashSet<>(); - for (ParametersAction other: others) { + for (ParametersAction other : others) { params.addAll(other.parameters); } return !params.equals(new HashSet<>(this.parameters)); @@ -240,7 +241,7 @@ public boolean shouldSchedule(List actions) { */ @NonNull public ParametersAction createUpdated(Collection overrides) { - if(overrides == null) { + if (overrides == null) { ParametersAction parametersAction = new ParametersAction(parameters); parametersAction.safeParameters = this.safeParameters; return parametersAction; @@ -248,7 +249,7 @@ public ParametersAction createUpdated(Collection overr List combinedParameters = new ArrayList<>(overrides); Set names = new HashSet<>(); - for(ParameterValue v : overrides) { + for (ParameterValue v : overrides) { if (v == null) continue; names.add(v.getName()); } diff --git a/core/src/main/java/hudson/model/ParametersDefinitionProperty.java b/core/src/main/java/hudson/model/ParametersDefinitionProperty.java index f08b067d29fb3..e09131c268a31 100644 --- a/core/src/main/java/hudson/model/ParametersDefinitionProperty.java +++ b/core/src/main/java/hudson/model/ParametersDefinitionProperty.java @@ -1,19 +1,19 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, * Jean-Baptiste Quenot, Seiji Sogabe, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static javax.servlet.http.HttpServletResponse.SC_CREATED; @@ -67,7 +68,7 @@ *

      The owning job needs a {@code sidepanel.jelly} and should have web methods delegating to {@link ParameterizedJobMixIn#doBuild} and {@link ParameterizedJobMixIn#doBuildWithParameters}. * The builds also need a {@code sidepanel.jelly}. */ -@ExportedBean(defaultVisibility=2) +@ExportedBean(defaultVisibility = 2) public class ParametersDefinitionProperty extends OptionalJobProperty> implements Action { @@ -87,7 +88,7 @@ private Object readResolve() { } @Deprecated - public AbstractProject getOwner() { + public AbstractProject getOwner() { return (AbstractProject) owner; } @@ -137,12 +138,12 @@ public void _doBuild(StaplerRequest req, StaplerResponse rsp) throws IOException * This method is supposed to be invoked from {@link ParameterizedJobMixIn#doBuild(StaplerRequest, StaplerResponse, TimeDuration)}. */ public void _doBuild(StaplerRequest req, StaplerResponse rsp, @QueryParameter TimeDuration delay) throws IOException, ServletException { - if (delay==null) - delay=new TimeDuration(TimeUnit.MILLISECONDS.convert(getJob().getQuietPeriod(), TimeUnit.SECONDS)); + if (delay == null) + delay = new TimeDuration(TimeUnit.MILLISECONDS.convert(getJob().getQuietPeriod(), TimeUnit.SECONDS)); List values = new ArrayList<>(); - + JSONObject formData = req.getSubmittedForm(); JSONArray a = JSONArray.fromObject(formData.get("parameter")); @@ -151,7 +152,7 @@ public void _doBuild(StaplerRequest req, StaplerResponse rsp, @QueryParameter Ti String name = jo.getString("name"); ParameterDefinition d = getParameterDefinition(name); - if(d==null) + if (d == null) throw new IllegalArgumentException("No such parameter definition: " + name); ParameterValue parameterValue = d.createValue(req, jo); if (parameterValue != null) { @@ -161,13 +162,13 @@ public void _doBuild(StaplerRequest req, StaplerResponse rsp, @QueryParameter Ti } } - WaitingItem item = Jenkins.get().getQueue().schedule( + WaitingItem item = Jenkins.get().getQueue().schedule( getJob(), delay.getTimeInSeconds(), new ParametersAction(values), new CauseAction(new Cause.UserIdCause())); - if (item!=null) { + if (item != null) { String url = formData.optString("redirectTo"); - if (url==null || !Util.isSafeToRedirectTo(url)) // avoid open redirect - url = req.getContextPath()+'/'+item.getUrl(); - rsp.sendRedirect(formData.optInt("statusCode",SC_CREATED), url); + if (url == null || !Util.isSafeToRedirectTo(url)) // avoid open redirect + url = req.getContextPath() + '/' + item.getUrl(); + rsp.sendRedirect(formData.optInt("statusCode", SC_CREATED), url); } else // send the user back to the job top page. rsp.sendRedirect("."); @@ -176,24 +177,24 @@ public void _doBuild(StaplerRequest req, StaplerResponse rsp, @QueryParameter Ti /** @deprecated use {@link #buildWithParameters(StaplerRequest, StaplerResponse, TimeDuration)} */ @Deprecated public void buildWithParameters(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { - buildWithParameters(req,rsp,TimeDuration.fromString(req.getParameter("delay"))); + buildWithParameters(req, rsp, TimeDuration.fromString(req.getParameter("delay"))); } public void buildWithParameters(StaplerRequest req, StaplerResponse rsp, @CheckForNull TimeDuration delay) throws IOException, ServletException { List values = new ArrayList<>(); - for (ParameterDefinition d: parameterDefinitions) { - ParameterValue value = d.createValue(req); - if (value != null) { - values.add(value); - } + for (ParameterDefinition d : parameterDefinitions) { + ParameterValue value = d.createValue(req); + if (value != null) { + values.add(value); + } } - if (delay==null) - delay=new TimeDuration(TimeUnit.MILLISECONDS.convert(getJob().getQuietPeriod(), TimeUnit.SECONDS)); + if (delay == null) + delay = new TimeDuration(TimeUnit.MILLISECONDS.convert(getJob().getQuietPeriod(), TimeUnit.SECONDS)); ScheduleResult scheduleResult = Jenkins.get().getQueue().schedule2( getJob(), delay.getTimeInSeconds(), new ParametersAction(values), ParameterizedJobMixIn.getBuildCause(getJob(), req)); Queue.Item item = scheduleResult.getItem(); - + if (item != null && !scheduleResult.isCreated()) { rsp.sendRedirect(SC_SEE_OTHER, req.getContextPath() + '/' + item.getUrl()); return; @@ -221,7 +222,7 @@ public ParameterDefinition getParameterDefinition(String name) { public static class DescriptorImpl extends OptionalJobPropertyDescriptor { @Override public ParametersDefinitionProperty newInstance(StaplerRequest req, JSONObject formData) throws FormException { - ParametersDefinitionProperty prop = (ParametersDefinitionProperty)super.newInstance(req, formData); + ParametersDefinitionProperty prop = (ParametersDefinitionProperty) super.newInstance(req, formData); if (prop != null && prop.parameterDefinitions.isEmpty()) { return null; } diff --git a/core/src/main/java/hudson/model/PasswordParameterDefinition.java b/core/src/main/java/hudson/model/PasswordParameterDefinition.java index b5422725984a9..58846ac4a2b56 100644 --- a/core/src/main/java/hudson/model/PasswordParameterDefinition.java +++ b/core/src/main/java/hudson/model/PasswordParameterDefinition.java @@ -21,10 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import hudson.util.Secret; import java.util.Objects; @@ -116,6 +118,7 @@ public int hashCode() { } @Override + @SuppressFBWarnings(value = "EQ_GETCLASS_AND_CLASS_CONSTANT", justification = "ParameterDefinitionTest tests that subclasses are not equal to their parent classes, so the behavior appears to be intentional") public boolean equals(Object obj) { if (PasswordParameterDefinition.class != getClass()) return super.equals(obj); diff --git a/core/src/main/java/hudson/model/PasswordParameterValue.java b/core/src/main/java/hudson/model/PasswordParameterValue.java index a69b3e40317c5..4f761587a370e 100644 --- a/core/src/main/java/hudson/model/PasswordParameterValue.java +++ b/core/src/main/java/hudson/model/PasswordParameterValue.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.NonNull; @@ -56,10 +57,10 @@ public PasswordParameterValue(String name, Secret value, String description) { } @Override - public void buildEnvironment(Run build, EnvVars env) { + public void buildEnvironment(Run build, EnvVars env) { String v = Secret.toString(value); env.put(name, v); - env.put(name.toUpperCase(Locale.ENGLISH),v); // backward compatibility pre 1.345 + env.put(name.toUpperCase(Locale.ENGLISH), v); // backward compatibility pre 1.345 } @Override diff --git a/core/src/main/java/hudson/model/PeriodicWork.java b/core/src/main/java/hudson/model/PeriodicWork.java index c2fe69a61b6e8..3a5bb3b4f01f7 100644 --- a/core/src/main/java/hudson/model/PeriodicWork.java +++ b/core/src/main/java/hudson/model/PeriodicWork.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static hudson.init.InitMilestone.JOB_CONFIG_ADAPTED; @@ -53,12 +54,12 @@ * *

      * This class is designed to run a short task. Implementations whose periodic work takes a long time - * to run should extend from {@link AsyncPeriodicWork} instead. + * to run should extend from {@link AsyncPeriodicWork} instead. * * @author Kohsuke Kawaguchi * @see AsyncPeriodicWork */ -@SuppressFBWarnings(value="PREDICTABLE_RANDOM", justification = "The random is just used for an initial delay.") +@SuppressFBWarnings(value = "PREDICTABLE_RANDOM", justification = "The random is just used for an initial delay.") public abstract class PeriodicWork extends SafeTimerTask implements ExtensionPoint { /** @deprecated Use your own logger, or send messages to the logger in {@link AsyncPeriodicWork#execute}. */ @@ -88,9 +89,9 @@ public abstract class PeriodicWork extends SafeTimerTask implements ExtensionPoi public long getInitialDelay() { long l = RANDOM.nextLong(); // Math.abs(Long.MIN_VALUE)==Long.MIN_VALUE! - if (l==Long.MIN_VALUE) + if (l == Long.MIN_VALUE) l++; - return Math.abs(l)%getRecurrencePeriod(); + return Math.abs(l) % getRecurrencePeriod(); } /** @@ -100,7 +101,7 @@ public static ExtensionList all() { return ExtensionList.lookup(PeriodicWork.class); } - @Initializer(after= JOB_CONFIG_ADAPTED) + @Initializer(after = JOB_CONFIG_ADAPTED) public static void init() { // start all PeriodicWorks ExtensionList extensionList = all(); @@ -115,9 +116,9 @@ private static void schedulePeriodicWork(PeriodicWork p) { } // time constants - protected static final long MIN = 1000*60; - protected static final long HOUR =60*MIN; - protected static final long DAY = 24*HOUR; + protected static final long MIN = 1000 * 60; + protected static final long HOUR = 60 * MIN; + protected static final long DAY = 24 * HOUR; private static final Random RANDOM = new Random(); diff --git a/core/src/main/java/hudson/model/PermalinkProjectAction.java b/core/src/main/java/hudson/model/PermalinkProjectAction.java index 301c966777104..9013ddd5efc58 100644 --- a/core/src/main/java/hudson/model/PermalinkProjectAction.java +++ b/core/src/main/java/hudson/model/PermalinkProjectAction.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -51,7 +52,7 @@ public interface PermalinkProjectAction extends Action { *

      * Because {@link Permalink} is a strategy-pattern object, * this method should normally return a pre-initialized - * read-only static list object. + * read-only static list object. * * @return * can be empty, but never null. @@ -87,7 +88,7 @@ abstract class Permalink { * @return null * if the target of the permalink doesn't exist. */ - public abstract @CheckForNull Run resolve(Job job); + public abstract @CheckForNull Run resolve(Job job); /** * List of {@link Permalink}s that are built into Jenkins. @@ -106,7 +107,7 @@ public String getId() { } @Override - public Run resolve(Job job) { + public Run resolve(Job job) { return job.getLastBuild(); } }; @@ -123,7 +124,7 @@ public String getId() { @Override public boolean apply(Run run) { - return !run.isBuilding() && run.getResult()==Result.SUCCESS; + return !run.isBuilding() && run.getResult() == Result.SUCCESS; } }; public static final Permalink LAST_SUCCESSFUL_BUILD = new PeepholePermalink() { @@ -156,7 +157,7 @@ public String getId() { @Override public boolean apply(Run run) { - return !run.isBuilding() && run.getResult()==Result.FAILURE; + return !run.isBuilding() && run.getResult() == Result.FAILURE; } }; @@ -173,7 +174,7 @@ public String getId() { @Override public boolean apply(Run run) { - return !run.isBuilding() && run.getResult()==Result.UNSTABLE; + return !run.isBuilding() && run.getResult() == Result.UNSTABLE; } }; @@ -190,7 +191,7 @@ public String getId() { @Override public boolean apply(Run run) { - return !run.isBuilding() && run.getResult()!=Result.SUCCESS; + return !run.isBuilding() && run.getResult() != Result.SUCCESS; } }; public static final Permalink LAST_COMPLETED_BUILD = new PeepholePermalink() { diff --git a/core/src/main/java/hudson/model/PersistenceRoot.java b/core/src/main/java/hudson/model/PersistenceRoot.java index 4e417d0539631..759094428f34c 100644 --- a/core/src/main/java/hudson/model/PersistenceRoot.java +++ b/core/src/main/java/hudson/model/PersistenceRoot.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import java.io.File; diff --git a/core/src/main/java/hudson/model/PersistentDescriptor.java b/core/src/main/java/hudson/model/PersistentDescriptor.java index 80a2f829e491d..908752151279c 100644 --- a/core/src/main/java/hudson/model/PersistentDescriptor.java +++ b/core/src/main/java/hudson/model/PersistentDescriptor.java @@ -1,6 +1,6 @@ package hudson.model; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; /** * Marker interface for Descriptors which use xml persistent data, and as such need to load from disk when instantiated. diff --git a/core/src/main/java/hudson/model/Project.java b/core/src/main/java/hudson/model/Project.java index 3ed33d9bcd1a4..7dc8b692d9401 100644 --- a/core/src/main/java/hudson/model/Project.java +++ b/core/src/main/java/hudson/model/Project.java @@ -1,19 +1,19 @@ /* * The MIT License - * + * * Copyright (c) 2004-2011, Sun Microsystems, Inc., Kohsuke Kawaguchi, * Jorg Heymans, Stephen Connolly, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.Util; @@ -59,35 +60,35 @@ * * @author Kohsuke Kawaguchi */ -public abstract class Project

      ,B extends Build> - extends AbstractProject implements SCMTriggerItem, Saveable, ProjectWithMaven, BuildableItemWithBuildWrappers { +public abstract class Project

      , B extends Build> + extends AbstractProject implements SCMTriggerItem, Saveable, ProjectWithMaven, BuildableItemWithBuildWrappers { /** * List of active {@link Builder}s configured for this project. */ - private volatile DescribableList> builders; - private static final AtomicReferenceFieldUpdater buildersSetter - = AtomicReferenceFieldUpdater.newUpdater(Project.class,DescribableList.class,"builders"); + private volatile DescribableList> builders; + private static final AtomicReferenceFieldUpdater buildersSetter + = AtomicReferenceFieldUpdater.newUpdater(Project.class, DescribableList.class, "builders"); /** * List of active {@link Publisher}s configured for this project. */ - private volatile DescribableList> publishers; - private static final AtomicReferenceFieldUpdater publishersSetter - = AtomicReferenceFieldUpdater.newUpdater(Project.class,DescribableList.class,"publishers"); + private volatile DescribableList> publishers; + private static final AtomicReferenceFieldUpdater publishersSetter + = AtomicReferenceFieldUpdater.newUpdater(Project.class, DescribableList.class, "publishers"); /** * List of active {@link BuildWrapper}s configured for this project. */ - private volatile DescribableList> buildWrappers; - private static final AtomicReferenceFieldUpdater buildWrappersSetter - = AtomicReferenceFieldUpdater.newUpdater(Project.class,DescribableList.class,"buildWrappers"); + private volatile DescribableList> buildWrappers; + private static final AtomicReferenceFieldUpdater buildWrappersSetter + = AtomicReferenceFieldUpdater.newUpdater(Project.class, DescribableList.class, "buildWrappers"); /** * Creates a new project. */ - protected Project(ItemGroup parent,String name) { - super(parent,name); + protected Project(ItemGroup parent, String name) { + super(parent, name); } @Override @@ -125,33 +126,33 @@ public List getBuilders() { * Use {@link #getPublishersList()} instead. */ @Deprecated - public Map,Publisher> getPublishers() { + public Map, Publisher> getPublishers() { return getPublishersList().toMap(); } - public DescribableList> getBuildersList() { + public DescribableList> getBuildersList() { if (builders == null) { - buildersSetter.compareAndSet(this,null,new DescribableList>(this)); + buildersSetter.compareAndSet(this, null, new DescribableList>(this)); } return builders; } - + @Override - public DescribableList> getPublishersList() { + public DescribableList> getPublishersList() { if (publishers == null) { - publishersSetter.compareAndSet(this,null,new DescribableList>(this)); + publishersSetter.compareAndSet(this, null, new DescribableList>(this)); } return publishers; } - public Map,BuildWrapper> getBuildWrappers() { + public Map, BuildWrapper> getBuildWrappers() { return getBuildWrappersList().toMap(); } @Override public DescribableList> getBuildWrappersList() { if (buildWrappers == null) { - buildWrappersSetter.compareAndSet(this,null,new DescribableList>(this)); + buildWrappersSetter.compareAndSet(this, null, new DescribableList>(this)); } return buildWrappers; } @@ -161,9 +162,9 @@ protected Set getResourceActivities() { final Set activities = new HashSet<>(); activities.addAll(super.getResourceActivities()); - activities.addAll(Util.filter(getBuildersList(),ResourceActivity.class)); - activities.addAll(Util.filter(getPublishersList(),ResourceActivity.class)); - activities.addAll(Util.filter(getBuildWrappersList(),ResourceActivity.class)); + activities.addAll(Util.filter(getBuildersList(), ResourceActivity.class)); + activities.addAll(Util.filter(getPublishersList(), ResourceActivity.class)); + activities.addAll(Util.filter(getBuildWrappersList(), ResourceActivity.class)); return activities; } @@ -192,7 +193,7 @@ public void removePublisher(Descriptor descriptor) throws IOException public Publisher getPublisher(Descriptor descriptor) { for (Publisher p : getPublishersList()) { - if(p.getDescriptor()==descriptor) + if (p.getDescriptor() == descriptor) return p; } return null; @@ -200,20 +201,20 @@ public Publisher getPublisher(Descriptor descriptor) { @Override protected void buildDependencyGraph(DependencyGraph graph) { super.buildDependencyGraph(graph); - getPublishersList().buildDependencyGraph(this,graph); - getBuildersList().buildDependencyGraph(this,graph); - getBuildWrappersList().buildDependencyGraph(this,graph); + getPublishersList().buildDependencyGraph(this, graph); + getBuildersList().buildDependencyGraph(this, graph); + getBuildWrappersList().buildDependencyGraph(this, graph); } @Override public boolean isFingerprintConfigured() { - return getPublishersList().get(Fingerprinter.class)!=null; + return getPublishersList().get(Fingerprinter.class) != null; } @Override public MavenInstallation inferMavenInstallation() { Maven m = getBuildersList().get(Maven.class); - if (m!=null) return m.getMaven(); + if (m != null) return m.getMaven(); return null; } @@ -223,13 +224,13 @@ public MavenInstallation inferMavenInstallation() { // // @Override - protected void submit( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, FormException { - super.submit(req,rsp); + protected void submit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException { + super.submit(req, rsp); JSONObject json = req.getSubmittedForm(); - getBuildWrappersList().rebuild(req,json, BuildWrappers.getFor(this)); - getBuildersList().rebuildHetero(req,json, Builder.all(), "builder"); + getBuildWrappersList().rebuild(req, json, BuildWrappers.getFor(this)); + getBuildersList().rebuildHetero(req, json, Builder.all(), "builder"); getPublishersList().rebuildHetero(req, json, Publisher.all(), "publisher"); } diff --git a/core/src/main/java/hudson/model/ProminentProjectAction.java b/core/src/main/java/hudson/model/ProminentProjectAction.java index 082f87580ed3a..6d3e48aef31dc 100644 --- a/core/src/main/java/hudson/model/ProminentProjectAction.java +++ b/core/src/main/java/hudson/model/ProminentProjectAction.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.tasks.BuildStep; diff --git a/core/src/main/java/hudson/model/ProxyView.java b/core/src/main/java/hudson/model/ProxyView.java index e78c864947614..3f33302744dc8 100644 --- a/core/src/main/java/hudson/model/ProxyView.java +++ b/core/src/main/java/hudson/model/ProxyView.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.Extension; @@ -42,9 +43,9 @@ /** * A view that delegates to another. - * + * * TODO: this does not respond to renaming or deleting the proxied view. - * + * * @author Tom Huybrechts * */ @@ -117,9 +118,9 @@ public FormValidation doViewExistsCheck(@QueryParameter String value) { checkPermission(View.CREATE); String view = Util.fixEmpty(value); - if(view==null) return FormValidation.ok(); + if (view == null) return FormValidation.ok(); - if(Jenkins.get().getView(view)!=null) + if (Jenkins.get().getView(view) != null) return FormValidation.ok(); else return FormValidation.error(Messages.ProxyView_NoSuchViewExists(value)); @@ -132,11 +133,11 @@ public static class DescriptorImpl extends ViewDescriptor { public String getDisplayName() { return Messages.ProxyView_DisplayName(); } - + @Override public boolean isInstantiable() { - // doesn't make sense to add a ProxyView to the global views - return !(Stapler.getCurrentRequest().findAncestorObject(ViewGroup.class) instanceof Jenkins); + // doesn't make sense to add a ProxyView to the global views + return !(Stapler.getCurrentRequest().findAncestorObject(ViewGroup.class) instanceof Jenkins); } } diff --git a/core/src/main/java/hudson/model/Queue.java b/core/src/main/java/hudson/model/Queue.java index 9d3bfb1194b4e..50ad97232bd5a 100644 --- a/core/src/main/java/hudson/model/Queue.java +++ b/core/src/main/java/hudson/model/Queue.java @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static hudson.init.InitMilestone.JOB_CONFIG_ADAPTED; @@ -211,7 +212,7 @@ public class Queue extends ResourceController implements Saveable { * * This map is forgetful, since we can't remember everything that executed in the past. */ - private final Cache leftItems = CacheBuilder.newBuilder().expireAfterWrite(5*60, TimeUnit.SECONDS).build(); + private final Cache leftItems = CacheBuilder.newBuilder().expireAfterWrite(5 * 60, TimeUnit.SECONDS).build(); /** * Data structure created for each idle {@link Executor}. @@ -315,7 +316,7 @@ public boolean isNotExclusive() { @Override public String toString() { - return String.format("JobOffer[%s #%d]",executor.getOwner().getName(), executor.getNumber()); + return String.format("JobOffer[%s #%d]", executor.getOwner().getName(), executor.getNumber()); } } @@ -398,7 +399,7 @@ public void load() { long maxId = 0; for (Object o : items) { if (o instanceof Item) { - maxId = Math.max(maxId, ((Item)o).id); + maxId = Math.max(maxId, ((Item) o).id); } } WaitingItem.COUNTER.set(maxId); @@ -407,9 +408,9 @@ public void load() { for (Object o : items) { if (o instanceof Task) { // backward compatibility - schedule((Task)o, 0); + schedule((Task) o, 0); } else if (o instanceof Item) { - Item item = (Item)o; + Item item = (Item) o; if (item.task == null) { continue; // botched persistence. throw this one away @@ -447,7 +448,7 @@ public void load() { */ @Override public void save() { - if(BulkChange.contains(this)) return; + if (BulkChange.contains(this)) return; if (Jenkins.getInstanceOrNull() == null) { return; } @@ -460,8 +461,8 @@ public void save() { state.counter = WaitingItem.COUNTER.longValue(); // write out the tasks on the queue - for (Item item: getItems()) { - if(item.task instanceof TransientTask) continue; + for (Item item : getItems()) { + if (item.task instanceof TransientTask) continue; state.items.add(item); } @@ -505,7 +506,7 @@ public void clear() { */ @Deprecated public boolean add(AbstractProject p) { - return schedule(p)!=null; + return schedule(p) != null; } /** @@ -528,7 +529,7 @@ public boolean add(AbstractProject p) { */ @Deprecated public boolean add(AbstractProject p, int quietPeriod) { - return schedule(p, quietPeriod)!=null; + return schedule(p, quietPeriod) != null; } /** @@ -665,7 +666,7 @@ public WaitingItem schedule(Task p, int quietPeriod, List actions) { */ @Deprecated public boolean add(Task p, int quietPeriod) { - return schedule(p, quietPeriod)!=null; + return schedule(p, quietPeriod) != null; } public @CheckForNull WaitingItem schedule(Task p, int quietPeriod) { @@ -678,7 +679,7 @@ public boolean add(Task p, int quietPeriod) { */ @Deprecated public boolean add(Task p, int quietPeriod, Action... actions) { - return schedule(p, quietPeriod, actions)!=null; + return schedule(p, quietPeriod, actions) != null; } /** @@ -745,8 +746,8 @@ public HttpResponse doCancelItem(@QueryParameter long id) throws IOException, Se item = null; } if (item != null) { - if(item.hasCancelPermission()){ - if(cancel(item)) { + if (item.hasCancelPermission()) { + if (cancel(item)) { return HttpResponses.status(HttpServletResponse.SC_NO_CONTENT); } return HttpResponses.error(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Could not cancel run for id " + id); @@ -772,15 +773,15 @@ private WaitingItem peek() { * Generally speaking the array is sorted such that the items that are most likely built sooner are * at the end. */ - @Exported(inline=true) + @Exported(inline = true) public Item[] getItems() { Snapshot s = this.snapshot; List r = new ArrayList<>(); - for(WaitingItem p : s.waitingList) { + for (WaitingItem p : s.waitingList) { r = checkPermissionsAndAddToList(r, p); } - for (BlockedItem p : s.blockedProjects){ + for (BlockedItem p : s.blockedProjects) { r = checkPermissionsAndAddToList(r, p); } for (BuildableItem p : reverse(s.buildables)) { @@ -825,15 +826,15 @@ private static boolean hasReadPermission(Queue.Task t, boolean valueIfNotAccessC * at the end. */ @Restricted(NoExternalUse.class) - @Exported(inline=true) + @Exported(inline = true) public StubItem[] getDiscoverableItems() { Snapshot s = this.snapshot; List r = new ArrayList<>(); - for(WaitingItem p : s.waitingList) { + for (WaitingItem p : s.waitingList) { r = filterDiscoverableItemListBasedOnPermissions(r, p); } - for (BlockedItem p : s.blockedProjects){ + for (BlockedItem p : s.blockedProjects) { r = filterDiscoverableItemListBasedOnPermissions(r, p); } for (BuildableItem p : reverse(s.buildables)) { @@ -850,7 +851,7 @@ public StubItem[] getDiscoverableItems() { private List filterDiscoverableItemListBasedOnPermissions(List r, Item t) { if (t.task instanceof hudson.model.Item) { hudson.model.Item taskAsItem = (hudson.model.Item) t.task; - if (!taskAsItem.hasPermission(hudson.model.Item.READ) + if (!taskAsItem.hasPermission(hudson.model.Item.READ) && taskAsItem.hasPermission(hudson.model.Item.DISCOVER)) { r.add(new StubItem(new StubTask(t.task))); } @@ -947,7 +948,7 @@ public List getPendingItems() { protected List getBlockedItems() { return new ArrayList<>(snapshot.blockedProjects); } - + /** * Returns the snapshot of all {@link LeftItem}s. * @@ -1010,7 +1011,7 @@ public boolean isPending(Task t) { * @param l Label to be checked. If null, any label will be accepted. * If you want to count {@link BuildableItem}s without assigned labels, * use {@link #strictCountBuildableItemsFor(hudson.model.Label)}. - * @return Number of {@link BuildableItem}s for the specified label. + * @return Number of {@link BuildableItem}s for the specified label. */ public /* @java.annotation.Nonnegative */ int countBuildableItemsFor(@CheckForNull Label l) { Snapshot snapshot = this.snapshot; @@ -1025,7 +1026,7 @@ public boolean isPending(Task t) { r++; return r; } - + /** * How many {@link BuildableItem}s are assigned for the given label? *

      @@ -1149,7 +1150,7 @@ public List getItems(Task t) { * Returns true if this queue contains the said project. */ public boolean contains(Task t) { - return getItem(t)!=null; + return getItem(t) != null; } /** @@ -1209,7 +1210,7 @@ private CauseOfBlockage getCauseOfBlockageForItem(Item i) { return causeOfBlockage; } - if(!(i instanceof BuildableItem)) { + if (!(i instanceof BuildableItem)) { // Make sure we don't queue two tasks of the same project to be built // unless that project allows concurrent builds. Once item is buildable it's ok. // @@ -1331,11 +1332,12 @@ public static boolean tryWithLock(Runnable runnable) { } } /** - * Wraps a {@link Runnable} with the {@link Queue} lock held. + * Wraps a {@link Runnable} with the {@link Queue} lock held. * * @param runnable the operation to wrap. * @since 1.618 */ + public static Runnable wrapWithLock(Runnable runnable) { final Jenkins jenkins = Jenkins.getInstanceOrNull(); // TODO confirm safe to assume non-null and use getInstance() @@ -1344,7 +1346,7 @@ public static Runnable wrapWithLock(Runnable runnable) { } /** - * Wraps a {@link hudson.remoting.Callable} with the {@link Queue} lock held. + * Wraps a {@link hudson.remoting.Callable} with the {@link Queue} lock held. * * @param callable the operation to wrap. * @since 1.618 @@ -1357,7 +1359,7 @@ public static hudson.remoting.Callable wrapWithLo } /** - * Wraps a {@link java.util.concurrent.Callable} with the {@link Queue} lock held. + * Wraps a {@link java.util.concurrent.Callable} with the {@link Queue} lock held. * * @param callable the operation to wrap. * @since 1.618 @@ -1370,6 +1372,7 @@ public static java.util.concurrent.Callable wrapWithLock(java.util.concur } @Override + @SuppressFBWarnings(value = "WA_AWAIT_NOT_IN_LOOP", justification = "the caller does indeed call this method in a loop") protected void _await() throws InterruptedException { condition.await(); } @@ -1481,7 +1484,7 @@ public void maintain() { // The executors that are currently waiting for a job to run. Map parked = new HashMap<>(); - {// update parked (and identify any pending items whose executor has disappeared) + { // update parked (and identify any pending items whose executor has disappeared) List lostPendings = new ArrayList<>(pendings); for (Computer c : jenkins.getComputers()) { for (Executor e : c.getAllExecutors()) { @@ -1506,7 +1509,7 @@ public void maintain() { } } // pending -> buildable - for (BuildableItem p: lostPendings) { + for (BuildableItem p : lostPendings) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "BuildableItem {0}: pending -> buildable as the assigned executor disappeared", @@ -1520,7 +1523,7 @@ public void maintain() { final QueueSorter s = sorter; - {// blocked -> buildable + { // blocked -> buildable // copy as we'll mutate the list and we want to process in a potentially different order List blockedItems = new ArrayList<>(blockedProjects.values()); // if facing a cycle of blocked tasks, ensure we process in the desired sort order @@ -1592,13 +1595,13 @@ public void maintain() { LOGGER.log(Level.WARNING, "s.sortBuildableItems() threw Throwable: {0}", e); } } - + // Ensure that identification of blocked tasks is using the live state: JENKINS-27708 & JENKINS-27871 updateSnapshot(); - + // allocate buildable jobs to executors for (BuildableItem p : new ArrayList<>( - buildables)) {// copy as we'll mutate the list in the loop + buildables)) { // copy as we'll mutate the list in the loop // one last check to make sure this build is not blocked. CauseOfBlockage causeOfBlockage = getCauseOfBlockageForItem(p); if (causeOfBlockage != null) { @@ -1700,7 +1703,7 @@ public void maintain() { Runnable runnable = makeFlyWeightTaskBuildable(p); LOGGER.log(Level.FINEST, "Converting flyweight task: {0} into a BuildableRunnable", taskDisplayName); - if(runnable != null){ + if (runnable != null) { return runnable; } @@ -1726,7 +1729,7 @@ public void maintain() { * @return a Runnable if there is an executor that can take the task, null otherwise */ @CheckForNull - private Runnable makeFlyWeightTaskBuildable(final BuildableItem p){ + private Runnable makeFlyWeightTaskBuildable(final BuildableItem p) { //we double check if this is a flyweight task if (p.task instanceof FlyweightTask) { Jenkins h = Jenkins.get(); @@ -1764,7 +1767,7 @@ private Runnable makeFlyWeightTaskBuildable(final BuildableItem p){ if (c == null || c.isOffline()) { continue; } - if (lbl!=null && !lbl.contains(n)) { + if (lbl != null && !lbl.contains(n)) { continue; } if (n.canTake(p) != null) { @@ -1916,9 +1919,8 @@ default CauseOfBlockage getCauseOfBlockage() { * amongst all the free executors on all possibly suitable nodes. * NOTE: To be able to re-use the same node during the next run this key should not change from one run to * another. You probably want to compute that key based on the job's name. - *

      - * @return by default: {@link #getFullDisplayName()} * + * @return by default: {@link #getFullDisplayName()} * @see hudson.model.LoadBalancer */ default String getAffinityKey() { return getFullDisplayName(); } @@ -2207,7 +2209,7 @@ public String getInQueueForString() { public Label getAssignedLabel() { for (LabelAssignmentAction laa : getActions(LabelAssignmentAction.class)) { Label l = laa.getAssignedLabel(task); - if (l!=null) return l; + if (l != null) return l; } return task.getAssignedLabel(); } @@ -2216,7 +2218,7 @@ public Label getAssignedLabel() { * Test if the specified {@link SubTask} needs to be run on a node with a particular label. *

      * This method takes {@link LabelAssignmentAction} into account, the first - * non-null assignment will be returned. + * non-null assignment will be returned. * Otherwise falls back to {@link SubTask#getAssignedLabel()} * @param st {@link SubTask} to be checked. * @return Required {@link Label}. Otherwise null, indicating it can run on anywhere. @@ -2225,7 +2227,7 @@ public Label getAssignedLabel() { public @CheckForNull Label getAssignedLabelFor(@NonNull SubTask st) { for (LabelAssignmentAction laa : getActions(LabelAssignmentAction.class)) { Label l = laa.getAssignedLabel(st); - if (l!=null) return l; + if (l != null) return l; } return st.getAssignedLabel(); } @@ -2238,7 +2240,7 @@ public Label getAssignedLabel() { */ public final List getCauses() { CauseAction ca = getAction(CauseAction.class); - if (ca!=null) + if (ca != null) return Collections.unmodifiableList(ca.getCauses()); return Collections.emptyList(); } @@ -2258,7 +2260,7 @@ protected Item(Task task, List actions, long id, FutureImpl future) { this.id = id; this.future = future; this.inQueueSince = System.currentTimeMillis(); - for (Action action: actions) addAction(action); + for (Action action : actions) addAction(action); } protected Item(Task task, List actions, long id, FutureImpl future, long inQueueSince) { @@ -2266,7 +2268,7 @@ protected Item(Task task, List actions, long id, FutureImpl future, long this.id = id; this.future = future; this.inQueueSince = inQueueSince; - for (Action action: actions) addAction(action); + for (Action action : actions) addAction(action); } @SuppressWarnings("deprecation") // JENKINS-51584 @@ -2284,7 +2286,7 @@ protected Item(Item item) { */ @Exported public String getUrl() { - return "queue/item/"+id+'/'; + return "queue/item/" + id + '/'; } /** @@ -2293,7 +2295,7 @@ public String getUrl() { @Exported public final String getWhy() { CauseOfBlockage cob = getCauseOfBlockage(); - return cob!=null ? cob.getShortDescription() : null; + return cob != null ? cob.getShortDescription() : null; } /** @@ -2338,7 +2340,7 @@ public String getSearchUrl() { @Deprecated @RequirePOST public HttpResponse doCancelQueue() { - if(hasCancelPermission()){ + if (hasCancelPermission()) { Jenkins.get().getQueue().cancel(this); } return HttpResponses.status(HttpServletResponse.SC_NO_CONTENT); @@ -2358,7 +2360,7 @@ public HttpResponse doCancelQueue() { public Authentication authenticate2() { for (QueueItemAuthenticator auth : QueueItemAuthenticatorProvider.authenticators()) { Authentication a = auth.authenticate2(this); - if (a!=null) + if (a != null) return a; } return task.getDefaultAuthentication2(this); @@ -2454,7 +2456,7 @@ public String getName() { */ @Restricted(NoExternalUse.class) @ExportedBean(defaultVisibility = 999) - @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", justification = "it is exported, so it might be used") + @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", justification = "read by Stapler") public static class StubItem { @Exported public StubTask task; @@ -2464,7 +2466,7 @@ public StubItem(StubTask task) { } } - + /** * An optional interface for actions on Queue.Item. * Lets the action cooperate in queue management. @@ -2671,7 +2673,7 @@ public BuildableItem(NotWaitingItem ni) { @Override public CauseOfBlockage getCauseOfBlockage() { Jenkins jenkins = Jenkins.get(); - if(isBlockedByShutdown(task)) + if (isBlockedByShutdown(task)) return CauseOfBlockage.fromMessage(Messages._Queue_HudsonIsAboutToShutDown()); List causesOfBlockage = transientCausesOfBlockage; @@ -2703,18 +2705,18 @@ public CauseOfBlockage getCauseOfBlockage() { @Override public boolean isStuck() { Label label = getAssignedLabel(); - if(label!=null && label.isOffline()) + if (label != null && label.isOffline()) // no executor online to process this job. definitely stuck. return true; long d = task.getEstimatedDuration(); - long elapsed = System.currentTimeMillis()-buildableStartMilliseconds; - if(d>=0) { + long elapsed = System.currentTimeMillis() - buildableStartMilliseconds; + if (d >= 0) { // if we were running elsewhere, we would have done this build ten times. - return elapsed > Math.max(d,60000L)*10; + return elapsed > Math.max(d, 60000L) * 10; } else { // more than a day in the queue - return TimeUnit.MILLISECONDS.toHours(elapsed)>24; + return TimeUnit.MILLISECONDS.toHours(elapsed) > 24; } } @@ -2776,7 +2778,7 @@ public CauseOfBlockage getCauseOfBlockage() { */ @Exported public @CheckForNull Executable getExecutable() { - return outcome!=null ? outcome.getPrimaryWorkUnit().getExecutable() : null; + return outcome != null ? outcome.getPrimaryWorkUnit().getExecutable() : null; } /** @@ -2784,12 +2786,12 @@ public CauseOfBlockage getCauseOfBlockage() { */ @Exported public boolean isCancelled() { - return outcome==null; + return outcome == null; } @Override void enter(Queue q) { - q.leftItems.put(getId(),this); + q.leftItems.put(getId(), this); Listeners.notify(QueueListener.class, true, l -> l.onLeft(this)); } @@ -2818,7 +2820,7 @@ public boolean canConvert(Class klazz) { @Override public Object fromString(String string) { Object item = Jenkins.get().getItemByFullName(string); - if(item==null) throw new NoSuchElementException("No such job exists: "+string); + if (item == null) throw new NoSuchElementException("No such job exists: " + string); return item; } @@ -2839,16 +2841,16 @@ public Object fromString(String string) { String[] split = string.split("#"); String projectName = split[0]; int buildNumber = Integer.parseInt(split[1]); - Job job = (Job) Jenkins.get().getItemByFullName(projectName); - if(job==null) throw new NoSuchElementException("No such job exists: "+projectName); - Run run = job.getBuildByNumber(buildNumber); - if(run==null) throw new NoSuchElementException("No such build: "+string); + Job job = (Job) Jenkins.get().getItemByFullName(projectName); + if (job == null) throw new NoSuchElementException("No such job exists: " + projectName); + Run run = job.getBuildByNumber(buildNumber); + if (run == null) throw new NoSuchElementException("No such build: " + string); return run; } @Override public String toString(Object object) { - Run run = (Run) object; + Run run = (Run) object; return run.getParent().getFullName() + "#" + run.getNumber(); } }); @@ -2905,7 +2907,7 @@ protected void doRun() { */ private class ItemList extends ArrayList { public T get(Task task) { - for (T item: this) { + for (T item : this) { if (item.task.equals(task)) { return item; } @@ -2915,7 +2917,7 @@ public T get(Task task) { public List getAll(Task task) { List result = new ArrayList<>(); - for (T item: this) { + for (T item : this) { if (item.task.equals(task)) { result.add(item); } @@ -2953,7 +2955,7 @@ public ItemList values() { */ public T cancel(Task p) { T x = get(p); - if(x!=null) x.cancel(Queue.this); + if (x != null) x.cancel(Queue.this); return x; } @@ -2986,7 +2988,7 @@ public String toString() { return "Queue.Snapshot{waitingList=" + waitingList + ";blockedProjects=" + blockedProjects + ";buildables=" + buildables + ";pendings=" + pendings + "}"; } } - + private static class LockedRunnable implements Runnable { private final Runnable delegate; @@ -3027,11 +3029,11 @@ public V call() throws Exception { } } - private static class LockedHRCallable implements hudson.remoting.Callable { + private static class LockedHRCallable implements hudson.remoting.Callable { private static final long serialVersionUID = 1L; - private final hudson.remoting.Callable delegate; + private final hudson.remoting.Callable delegate; - private LockedHRCallable(hudson.remoting.Callable delegate) { + private LockedHRCallable(hudson.remoting.Callable delegate) { this.delegate = delegate; } @@ -3054,7 +3056,7 @@ public static Queue getInstance() { /** * Restores the queue content during the start up. */ - @Initializer(after=JOB_CONFIG_ADAPTED) + @Initializer(after = JOB_CONFIG_ADAPTED) public static void init(Jenkins h) { Queue queue = h.getQueue(); Item[] items = queue.getItems(); diff --git a/core/src/main/java/hudson/model/RSS.java b/core/src/main/java/hudson/model/RSS.java index 4b95c28d937f5..19727656e729e 100644 --- a/core/src/main/java/hudson/model/RSS.java +++ b/core/src/main/java/hudson/model/RSS.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.FeedAdapter; @@ -53,13 +54,13 @@ public final class RSS { * Controls how to render entries to RSS. */ public static void forwardToRss(String title, String url, Collection entries, FeedAdapter adapter, StaplerRequest req, HttpServletResponse rsp) throws IOException, ServletException { - req.setAttribute("adapter",adapter); - req.setAttribute("title",title); - req.setAttribute("url",url); - req.setAttribute("entries",entries); + req.setAttribute("adapter", adapter); + req.setAttribute("title", title); + req.setAttribute("url", url); + req.setAttribute("entries", entries); String flavor = req.getParameter("flavor"); - if(flavor==null) flavor="atom"; + if (flavor == null) flavor = "atom"; flavor = flavor.replace('/', '_'); // Don't allow path to any jelly if (flavor.equals("atom")) { @@ -68,7 +69,7 @@ public static void forwardToRss(String title, String url, CollectionUse Cases - *

      Invisible Property

      *

      + * Invisible Property: * This mechanism can be used to create an entirely invisible {@link Describable}, which is handy * for {@link NodeProperty}, {@link JobProperty}, etc. To do so, define an empty config.jelly to prevent it from * showing up in the config UI, then implement {@link #reconfigure(StaplerRequest, JSONObject)} * and simply return {@code this}. * - *

      Passing some values without going through clients

      *

      + * Passing some values without going through clients: * Sometimes your {@link Describable} object may have some expensive objects that you might want to * hand over to the next instance. This hook lets you do that. * diff --git a/core/src/main/java/hudson/model/Resource.java b/core/src/main/java/hudson/model/Resource.java index cb1e06a9cc828..b407f6df99d6f 100644 --- a/core/src/main/java/hudson/model/Resource.java +++ b/core/src/main/java/hudson/model/Resource.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -63,14 +64,14 @@ public final class Resource { public final int numConcurrentWrite; public Resource(@CheckForNull Resource parent, @NonNull String displayName) { - this(parent,displayName,1); + this(parent, displayName, 1); } /** * @since 1.155 */ public Resource(@CheckForNull Resource parent, @NonNull String displayName, int numConcurrentWrite) { - if(numConcurrentWrite<1) + if (numConcurrentWrite < 1) throw new IllegalArgumentException(); this.parent = parent; @@ -79,7 +80,7 @@ public Resource(@CheckForNull Resource parent, @NonNull String displayName, int } public Resource(@NonNull String displayName) { - this(null,displayName); + this(null, displayName); } /** @@ -90,12 +91,12 @@ public Resource(@NonNull String displayName) { * For R/W conflict test, this value should be set to {@link Integer#MAX_VALUE}. */ public boolean isCollidingWith(Resource that, int count) { - assert that!=null; - for(Resource r=that; r!=null; r=r.parent) - if(this.equals(r) && r.numConcurrentWrite resourceView = new AbstractCollection() { @Override public Iterator iterator() { - return new AdaptedIterator(inProgress.iterator()) { + return new AdaptedIterator(inProgress.iterator()) { @Override protected ResourceList adapt(ResourceActivity item) { return item.getResourceList(); @@ -78,9 +80,9 @@ public int size() { * @throws InterruptedException * the thread can be interrupted while waiting for the available resources. */ - public void execute(@NonNull Runnable task, final ResourceActivity activity ) throws InterruptedException { + public void execute(@NonNull Runnable task, final ResourceActivity activity) throws InterruptedException { final ResourceList resources = activity.getResourceList(); - _withLock(new NotReallyRoleSensitiveCallable() { + _withLock(new NotReallyRoleSensitiveCallable() { @Override public Void call() throws InterruptedException { while (inUse.isCollidingWith(resources)) { @@ -161,11 +163,12 @@ public Resource call() { public ResourceActivity getBlockingActivity(ResourceActivity activity) { ResourceList res = activity.getResourceList(); for (ResourceActivity a : inProgress) - if(res.isCollidingWith(a.getResourceList())) + if (res.isCollidingWith(a.getResourceList())) return a; return null; } + @SuppressFBWarnings(value = "WA_NOT_IN_LOOP", justification = "the caller does indeed call this method in a loop") protected void _await() throws InterruptedException { wait(); } @@ -186,7 +189,7 @@ protected V _withLock(java.util.concurrent.Callable callable) throws Exce } } - protected V _withLock(hudson.remoting.Callable callable) throws T { + protected V _withLock(hudson.remoting.Callable callable) throws T { synchronized (this) { return callable.call(); } diff --git a/core/src/main/java/hudson/model/ResourceList.java b/core/src/main/java/hudson/model/ResourceList.java index eb57076c9a9d3..e94a91996a13e 100644 --- a/core/src/main/java/hudson/model/ResourceList.java +++ b/core/src/main/java/hudson/model/ResourceList.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import java.util.Arrays; @@ -39,7 +40,7 @@ * As with usual reader/writer pattern, multiple read accesses can * co-exist concurrently, but write access requires exclusive access * (the number of allowed concurrent write activity is determined by - * {@link Resource#numConcurrentWrite}. + * {@link Resource#numConcurrentWrite}. * * @author Kohsuke Kawaguchi * @since 1.121 @@ -59,7 +60,7 @@ public final class ResourceList { * The values are mostly supposed to be 1, but when {@link ResourceController} * uses a list to keep track of the union of all the activities, it can get larger. */ - private final Map write = new HashMap<>(); + private final Map write = new HashMap<>(); private static final Integer MAX_INT = Integer.MAX_VALUE; /** @@ -73,7 +74,7 @@ public static ResourceList union(ResourceList... lists) { * Creates union of all resources. */ public static ResourceList union(Collection lists) { - switch(lists.size()) { + switch (lists.size()) { case 0: return EMPTY; case 1: @@ -83,7 +84,7 @@ public static ResourceList union(Collection lists) { for (ResourceList l : lists) { r.all.addAll(l.all); for (Map.Entry e : l.write.entrySet()) - r.write.put(e.getKey(), unbox(r.write.get(e.getKey()))+e.getValue()); + r.write.put(e.getKey(), unbox(r.write.get(e.getKey())) + e.getValue()); } return r; } @@ -102,7 +103,7 @@ public ResourceList r(Resource r) { */ public ResourceList w(Resource r) { all.add(r); - write.put(r, unbox(write.get(r))+1); + write.put(r, unbox(write.get(r)) + 1); return this; } @@ -111,27 +112,27 @@ public ResourceList w(Resource r) { * resource access. */ public boolean isCollidingWith(ResourceList that) { - return getConflict(that)!=null; + return getConflict(that) != null; } /** * Returns the resource in this list that's colliding with the given resource list. */ public Resource getConflict(ResourceList that) { - Resource r = _getConflict(this,that); - if(r!=null) return r; - return _getConflict(that,this); + Resource r = _getConflict(this, that); + if (r != null) return r; + return _getConflict(that, this); } private Resource _getConflict(ResourceList lhs, ResourceList rhs) { - for (Map.Entry r : lhs.write.entrySet()) { + for (Map.Entry r : lhs.write.entrySet()) { for (Resource l : rhs.all) { Integer v = rhs.write.get(l); - if(v!=null) // this is write/write conflict. + if (v != null) // this is write/write conflict. v += r.getValue(); else // Otherwise set it to a very large value, since it's read/write conflict v = MAX_INT; - if(r.getKey().isCollidingWith(l,unbox(v))) { + if (r.getKey().isCollidingWith(l, unbox(v))) { LOGGER.info("Collision with " + r + " and " + l); return r.getKey(); } @@ -142,11 +143,11 @@ private Resource _getConflict(ResourceList lhs, ResourceList rhs) { @Override public String toString() { - Map m = new HashMap<>(); + Map m = new HashMap<>(); for (Resource r : all) - m.put(r,"R"); - for (Map.Entry e : write.entrySet()) - m.put(e.getKey(),"W"+e.getValue()); + m.put(r, "R"); + for (Map.Entry e : write.entrySet()) + m.put(e.getKey(), "W" + e.getValue()); return m.toString(); } @@ -154,7 +155,7 @@ public String toString() { * {@link Integer} unbox operation that treats null as 0. */ private static int unbox(Integer x) { - return x==null ? 0 : x; + return x == null ? 0 : x; } /** diff --git a/core/src/main/java/hudson/model/RestartListener.java b/core/src/main/java/hudson/model/RestartListener.java index 2160abc9fbdd9..828eeb0d2e2e9 100644 --- a/core/src/main/java/hudson/model/RestartListener.java +++ b/core/src/main/java/hudson/model/RestartListener.java @@ -63,6 +63,7 @@ public boolean isReadyToRestart() throws IOException, InterruptedException { } return true; } + private static boolean blocksRestart(Executor e) { if (e.isBusy()) { AsynchronousExecution execution = e.getAsynchronousExecution(); diff --git a/core/src/main/java/hudson/model/Result.java b/core/src/main/java/hudson/model/Result.java index 72b7a87f86836..b56867e37ed01 100644 --- a/core/src/main/java/hudson/model/Result.java +++ b/core/src/main/java/hudson/model/Result.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import com.thoughtworks.xstream.converters.SingleValueConverter; @@ -51,30 +52,30 @@ public final class Result implements Serializable, CustomExportedBean { /** * The build had no errors. */ - public static final @NonNull Result SUCCESS = new Result("SUCCESS",BallColor.BLUE,0,true); + public static final @NonNull Result SUCCESS = new Result("SUCCESS", BallColor.BLUE, 0, true); /** * The build had some errors but they were not fatal. * For example, some tests failed. */ - public static final @NonNull Result UNSTABLE = new Result("UNSTABLE",BallColor.YELLOW,1,true); + public static final @NonNull Result UNSTABLE = new Result("UNSTABLE", BallColor.YELLOW, 1, true); /** * The build had a fatal error. */ - public static final @NonNull Result FAILURE = new Result("FAILURE",BallColor.RED,2,true); + public static final @NonNull Result FAILURE = new Result("FAILURE", BallColor.RED, 2, true); /** * The module was not built. *

      * This status code is used in a multi-stage build (like maven2) * where a problem in earlier stage prevented later stages from building. */ - public static final @NonNull Result NOT_BUILT = new Result("NOT_BUILT",BallColor.NOTBUILT,3,false); + public static final @NonNull Result NOT_BUILT = new Result("NOT_BUILT", BallColor.NOTBUILT, 3, false); /** * The build was manually aborted. * * If you are catching {@link InterruptedException} and interpreting it as {@link #ABORTED}, * you should check {@link Executor#abortResult()} instead (starting 1.417.) */ - public static final @NonNull Result ABORTED = new Result("ABORTED",BallColor.ABORTED,4,false); + public static final @NonNull Result ABORTED = new Result("ABORTED", BallColor.ABORTED, 4, false); private final @NonNull String name; @@ -87,7 +88,7 @@ public final class Result implements Serializable, CustomExportedBean { * Default ball color for this status. */ public final @NonNull BallColor color; - + /** * Is this a complete build - i.e. did it run to the end (not aborted)? * @since 1.526 @@ -105,7 +106,7 @@ private Result(@NonNull String name, @NonNull BallColor color, /*@java.annotatio * Combines two {@link Result}s and returns the worse one. */ public @NonNull Result combine(@NonNull Result that) { - if(this.ordinal < that.ordinal) + if (this.ordinal < that.ordinal) return that; else return this; @@ -149,7 +150,7 @@ public boolean isBetterThan(@NonNull Result that) { public boolean isBetterOrEqualTo(@NonNull Result that) { return this.ordinal <= that.ordinal; } - + /** * Is this a complete build - i.e. did it run to the end (not aborted)? * @since 1.526 @@ -167,7 +168,7 @@ public boolean isCompleteBuild() { public @NonNull String toExportedObject() { return name; } - + public static @NonNull Result fromString(@NonNull String s) { for (Result r : all) if (s.equalsIgnoreCase(r.name)) @@ -185,19 +186,19 @@ public boolean isCompleteBuild() { // Maintain each Result as a singleton deserialized (like build result from an agent node) private Object readResolve() { for (Result r : all) - if (ordinal==r.ordinal) + if (ordinal == r.ordinal) return r; return FAILURE; } private static final long serialVersionUID = 1L; - private static final Result[] all = new Result[] {SUCCESS,UNSTABLE,FAILURE,NOT_BUILT,ABORTED}; + private static final Result[] all = new Result[] {SUCCESS, UNSTABLE, FAILURE, NOT_BUILT, ABORTED}; - public static final SingleValueConverter conv = new AbstractSingleValueConverter () { + public static final SingleValueConverter conv = new AbstractSingleValueConverter() { @Override public boolean canConvert(Class clazz) { - return clazz==Result.class; + return clazz == Result.class; } @Override @@ -216,8 +217,8 @@ public OptionHandlerImpl(CmdLineParser parser, OptionDef option, Setter build) { - return getResultTrend((Run)build); + return getResultTrend((Run) build); } /** * Returns the result trend of a run. - * + * * @param run the run * @return the result trend - * + * * @since 1.441 */ public static ResultTrend getResultTrend(Run run) { - + Result result = run.getResult(); - + if (result == Result.ABORTED) { return ABORTED; } else if (result == Result.NOT_BUILT) { return NOT_BUILT; } - + if (result == Result.SUCCESS) { if (isFix(run)) { return FIXED; @@ -127,14 +128,14 @@ public static ResultTrend getResultTrend(Run run) { return SUCCESS; } } - + Run previousBuild = getPreviousNonAbortedBuild(run); if (result == Result.UNSTABLE) { if (previousBuild == null) { return UNSTABLE; } - - + + if (previousBuild.getResult() == Result.UNSTABLE) { return STILL_UNSTABLE; } else if (previousBuild.getResult() == Result.FAILURE) { @@ -149,10 +150,10 @@ public static ResultTrend getResultTrend(Run run) { return FAILURE; } } - + throw new IllegalArgumentException("Unknown result: '" + result + "' for build: " + run); } - + /** * Returns the previous 'not aborted' build (i.e. ignores ABORTED and NOT_BUILT builds) * or null. @@ -160,10 +161,10 @@ public static ResultTrend getResultTrend(Run run) { private static Run getPreviousNonAbortedBuild(Run build) { Run previousBuild = build.getPreviousBuild(); while (previousBuild != null) { - if (previousBuild.getResult() == null + if (previousBuild.getResult() == null || previousBuild.getResult() == Result.ABORTED || previousBuild.getResult() == Result.NOT_BUILT) { - + previousBuild = previousBuild.getPreviousBuild(); } else { return previousBuild; @@ -171,7 +172,7 @@ public static ResultTrend getResultTrend(Run run) { } return previousBuild; } - + /** * Returns true if this build represents a 'fix'. * I.e. it is the first successful build after previous @@ -182,7 +183,7 @@ private static boolean isFix(Run build) { if (build.getResult() != Result.SUCCESS) { return false; } - + Run previousBuild = getPreviousNonAbortedBuild(build); if (previousBuild != null) { return previousBuild.getResult().isWorseThan(Result.SUCCESS); diff --git a/core/src/main/java/hudson/model/RootAction.java b/core/src/main/java/hudson/model/RootAction.java index 54bb86699c698..9c431ee635ffc 100644 --- a/core/src/main/java/hudson/model/RootAction.java +++ b/core/src/main/java/hudson/model/RootAction.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.Extension; diff --git a/core/src/main/java/hudson/model/Run.java b/core/src/main/java/hudson/model/Run.java index dcfe9eef0a014..1e5d9d4c650f5 100644 --- a/core/src/main/java/hudson/model/Run.java +++ b/core/src/main/java/hudson/model/Run.java @@ -1,22 +1,22 @@ /* * The MIT License - * + * * Copyright (c) 2004-2012, Sun Microsystems, Inc., Kohsuke Kawaguchi, * Daniel Dyer, Red Hat, Inc., Tom Huybrechts, Romain Seguy, Yahoo! Inc., * Darek Ostolski, CloudBees, Inc. * Copyright (c) 2012, Martin Schroeder, Intel Mobile Communications GmbH * Copyright (c) 2019 Intel Corporation - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -25,6 +25,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static java.util.logging.Level.FINE; @@ -154,7 +155,7 @@ * @see RunListener */ @ExportedBean -public abstract class Run ,RunT extends Run> +public abstract class Run, RunT extends Run> extends Actionable implements ExtensionPoint, Comparable, AccessControlled, PersistenceRoot, DescriptorByNameOwner, OnMaster, StaplerProxy { /** @@ -214,7 +215,7 @@ public abstract class Run ,RunT extends Run getTransientActions() { List actions = new ArrayList<>(); - for (TransientBuildActionFactory factory: TransientBuildActionFactory.all()) { + for (TransientBuildActionFactory factory : TransientBuildActionFactory.all()) { for (Action created : factory.createFor(this)) { if (created == null) { LOGGER.log(WARNING, "null action added by {0}", factory); @@ -438,10 +439,10 @@ public void addAction(@NonNull Action a) { /** * Obtains 'this' in a more type safe signature. - */ + */ @SuppressWarnings("unchecked") protected @NonNull RunT _this() { - return (RunT)this; + return (RunT) this; } /** @@ -506,7 +507,7 @@ public void setResult(@NonNull Result r) { } // result can only get worse - if (result==null || r.isWorseThan(result)) { + if (result == null || r.isWorseThan(result)) { result = r; LOGGER.log(FINE, this + " in " + getRootDir() + ": result is set to " + r, LOGGER.isLoggable(Level.FINER) ? new Exception() : null); } @@ -517,7 +518,7 @@ public void setResult(@NonNull Result r) { */ public @NonNull List getBadgeActions() { List r = getActions(BuildBadgeAction.class); - if(isKeepLog()) { + if (isKeepLog()) { r = new ArrayList<>(r); r.add(new KeepLogBuildBadge()); } @@ -552,14 +553,14 @@ public boolean isLogUpdated() { /** * Gets the {@link Executor} building this job, if it's being built. * Otherwise null. - * + * * This method looks for {@link Executor} who's {@linkplain Executor#getCurrentExecutable() assigned to this build}, * and because of that this might not be necessarily in sync with the return value of {@link #isBuilding()} — * an executor holds on to {@link Run} some more time even after the build is finished (for example to * perform {@linkplain Run.State#POST_PRODUCTION post-production processing}.) * @see Executor#of */ - @Exported + @Exported public @CheckForNull Executor getExecutor() { return this instanceof Queue.Executable ? Executor.of((Queue.Executable) this) : null; } @@ -567,12 +568,12 @@ public boolean isLogUpdated() { /** * Gets the one off {@link Executor} building this job, if it's being built. * Otherwise null. - * @since 1.433 + * @since 1.433 */ public @CheckForNull Executor getOneOffExecutor() { - for( Computer c : Jenkins.get().getComputers() ) { + for (Computer c : Jenkins.get().getComputers()) { for (Executor e : c.getOneOffExecutors()) { - if(e.getCurrentExecutable()==this) + if (e.getCurrentExecutable() == this) return e; } } @@ -583,9 +584,9 @@ public boolean isLogUpdated() { * Gets the charset in which the log file is written. * @return never null. * @since 1.257 - */ + */ public final @NonNull Charset getCharset() { - if(charset==null) return Charset.defaultCharset(); + if (charset == null) return Charset.defaultCharset(); return Charset.forName(charset); } @@ -602,7 +603,7 @@ public boolean isLogUpdated() { */ public @NonNull List getCauses() { CauseAction a = getAction(CauseAction.class); - if (a==null) return Collections.emptyList(); + if (a == null) return Collections.emptyList(); return Collections.unmodifiableList(a.getCauses()); } @@ -610,7 +611,7 @@ public boolean isLogUpdated() { * Returns a {@link Cause} of a particular type. * * @since 1.362 - */ + */ public @CheckForNull T getCause(Class type) { for (Cause c : getCauses()) if (type.isInstance(c)) @@ -625,22 +626,22 @@ public boolean isLogUpdated() { */ @Exported public final boolean isKeepLog() { - return getWhyKeepLog()!=null; + return getWhyKeepLog() != null; } /** * If {@link #isKeepLog()} returns true, returns a short, human-readable * sentence that explains why it's being kept. - */ + */ public @CheckForNull String getWhyKeepLog() { - if(keepLog) + if (keepLog) return Messages.Run_MarkedExplicitly(); return null; // not marked at all } /** * The project this build is for. - */ + */ public @NonNull JobT getParent() { return project; } @@ -649,7 +650,7 @@ public final boolean isKeepLog() { * When the build is scheduled. * * @see #getStartTimeInMillis() - */ + */ @Exported public @NonNull Calendar getTimestamp() { GregorianCalendar c = new GregorianCalendar(); @@ -659,7 +660,7 @@ public final boolean isKeepLog() { /** * Same as {@link #getTimestamp()} but in a different type. - */ + */ public final @NonNull Date getTime() { return new Date(timestamp); } @@ -680,7 +681,7 @@ public final long getTimeInMillis() { * @see #getTimestamp() */ public final long getStartTimeInMillis() { - if (startTime==0) return timestamp; // fallback: approximate by the queuing time + if (startTime == 0) return timestamp; // fallback: approximate by the queuing time return startTime; } @@ -720,9 +721,9 @@ public String getDescription() { int displayChars = 0; int lastTruncatablePoint = -1; - for (int i=0; i') { inTag = false; @@ -747,9 +748,9 @@ public String getDescription() { if (displayChars >= maxDescrLength) { truncDesc = truncDesc.substring(0, lastTruncatablePoint) + ending; } - + return truncDesc; - + } /** @@ -759,7 +760,7 @@ public String getDescription() { * string like "3 minutes" "1 day" etc. */ public @NonNull String getTimestampString() { - long duration = new GregorianCalendar().getTimeInMillis()-timestamp; + long duration = new GregorianCalendar().getTimeInMillis() - timestamp; return Util.getTimeSpanString(duration); } @@ -778,7 +779,7 @@ public String getDescription() { return Messages.Run_NotStartedYet(); } else if (isBuilding()) { return Messages.Run_InProgressDuration( - Util.getTimeSpanString(System.currentTimeMillis()-startTime)); + Util.getTimeSpanString(System.currentTimeMillis() - startTime)); } return Util.getTimeSpanString(duration); } @@ -795,7 +796,7 @@ public long getDuration() { * Gets the icon color for display. */ public @NonNull BallColor getIconColor() { - if(!isBuilding()) { + if (!isBuilding()) { // already built return getResult().color; } @@ -803,7 +804,7 @@ public long getDuration() { // a new build is in progress BallColor baseColor; RunT pb = getPreviousBuild(); - if(pb==null) + if (pb == null) baseColor = BallColor.NOTBUILT; else baseColor = pb.getIconColor(); @@ -815,7 +816,7 @@ public long getDuration() { * Returns true if the build is still queued and hasn't started yet. */ public boolean hasntStartedYet() { - return state ==State.NOT_STARTED; + return state == State.NOT_STARTED; } @SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE", justification = "see JENKINS-45892") @@ -829,17 +830,17 @@ public String toString() { @Exported public String getFullDisplayName() { - return project.getFullDisplayName()+' '+getDisplayName(); + return project.getFullDisplayName() + ' ' + getDisplayName(); } @Override @Exported public String getDisplayName() { - return displayName!=null ? displayName : "#"+number; + return displayName != null ? displayName : "#" + number; } public boolean hasCustomDisplayName() { - return displayName!=null; + return displayName != null; } /** @@ -852,7 +853,7 @@ public void setDisplayName(String value) throws IOException { save(); } - @Exported(visibility=2) + @Exported(visibility = 2) public int getNumber() { return number; } @@ -862,7 +863,7 @@ public int getNumber() { * @return Reference to the build. Never null * @see jenkins.model.lazy.LazyBuildMixIn.RunMixIn#createReference * @since 1.556 - */ + */ protected @NonNull BuildReference createReference() { return new BuildReference<>(getId(), _this()); } @@ -874,26 +875,26 @@ public int getNumber() { * @since 1.556 */ protected void dropLinks() { - if(nextBuild!=null) + if (nextBuild != null) nextBuild.previousBuild = previousBuild; - if(previousBuild!=null) + if (previousBuild != null) previousBuild.nextBuild = nextBuild; } /** * @see jenkins.model.lazy.LazyBuildMixIn.RunMixIn#getPreviousBuild - */ + */ public @CheckForNull RunT getPreviousBuild() { return previousBuild; } /** * Gets the most recent {@linkplain #isBuilding() completed} build excluding 'this' Run itself. - */ + */ public final @CheckForNull RunT getPreviousCompletedBuild() { - RunT r=getPreviousBuild(); - while (r!=null && r.isBuilding()) - r=r.getPreviousBuild(); + RunT r = getPreviousBuild(); + while (r != null && r.isBuilding()) + r = r.getPreviousBuild(); return r; } @@ -904,20 +905,20 @@ protected void dropLinks() { *

      * We basically follow the existing skip list, and wherever we find a non-optimal pointer, we remember them * in 'fixUp' and update them later. - */ + */ public final @CheckForNull RunT getPreviousBuildInProgress() { - if(previousBuildInProgress==this) return null; // the most common case + if (previousBuildInProgress == this) return null; // the most common case List fixUp = new ArrayList<>(); RunT r = _this(); // 'r' is the source of the pointer (so that we can add it to fix up if we find that the target of the pointer is inefficient.) RunT answer; while (true) { RunT n = r.previousBuildInProgress; - if (n==null) {// no field computed yet. - n=r.getPreviousBuild(); + if (n == null) { // no field computed yet. + n = r.getPreviousBuild(); fixUp.add(r); } - if (r==n || n==null) { + if (r == n || n == null) { // this indicates that we know there's no build in progress beyond this point answer = null; break; @@ -934,38 +935,38 @@ protected void dropLinks() { // fix up so that the next look up will run faster for (RunT f : fixUp) - f.previousBuildInProgress = answer==null ? f : answer; + f.previousBuildInProgress = answer == null ? f : answer; return answer; } /** * Returns the last build that was actually built - i.e., skipping any with Result.NOT_BUILT - */ + */ public @CheckForNull RunT getPreviousBuiltBuild() { - RunT r=getPreviousBuild(); + RunT r = getPreviousBuild(); // in certain situations (aborted m2 builds) r.getResult() can still be null, although it should theoretically never happen - while( r!=null && (r.getResult() == null || r.getResult()==Result.NOT_BUILT) ) - r=r.getPreviousBuild(); + while (r != null && (r.getResult() == null || r.getResult() == Result.NOT_BUILT)) + r = r.getPreviousBuild(); return r; } /** * Returns the last build that didn't fail before this build. - */ + */ public @CheckForNull RunT getPreviousNotFailedBuild() { - RunT r=getPreviousBuild(); - while( r!=null && r.getResult()==Result.FAILURE ) - r=r.getPreviousBuild(); + RunT r = getPreviousBuild(); + while (r != null && r.getResult() == Result.FAILURE) + r = r.getPreviousBuild(); return r; } /** * Returns the last failed build before this build. - */ + */ public @CheckForNull RunT getPreviousFailedBuild() { - RunT r=getPreviousBuild(); - while( r!=null && r.getResult()!=Result.FAILURE ) - r=r.getPreviousBuild(); + RunT r = getPreviousBuild(); + while (r != null && r.getResult() != Result.FAILURE) + r = r.getPreviousBuild(); return r; } @@ -974,22 +975,22 @@ protected void dropLinks() { * @since 1.383 */ public @CheckForNull RunT getPreviousSuccessfulBuild() { - RunT r=getPreviousBuild(); - while( r!=null && r.getResult()!=Result.SUCCESS ) - r=r.getPreviousBuild(); + RunT r = getPreviousBuild(); + while (r != null && r.getResult() != Result.SUCCESS) + r = r.getPreviousBuild(); return r; } /** * Returns the last {@code numberOfBuilds} builds with a build result ≥ {@code threshold}. - * + * * @param numberOfBuilds the desired number of builds * @param threshold the build result threshold * @return a list with the builds (youngest build first). * May be smaller than 'numberOfBuilds' or even empty * if not enough builds satisfying the threshold have been found. Never null. * @since 1.383 - */ + */ public @NonNull List getPreviousBuildsOverThreshold(int numberOfBuilds, @NonNull Result threshold) { RunT r = getPreviousBuild(); if (r != null) { @@ -1025,7 +1026,7 @@ protected void dropLinks() { /** * @see jenkins.model.lazy.LazyBuildMixIn.RunMixIn#getNextBuild - */ + */ public @CheckForNull RunT getNextBuild() { return nextBuild; } @@ -1034,7 +1035,7 @@ protected void dropLinks() { * Returns the URL of this {@link Run}, relative to the context root of Hudson. * * @return - * String like "job/foo/32/" with trailing slash but no leading slash. + * String like "job/foo/32/" with trailing slash but no leading slash. */ // I really messed this up. I'm hoping to fix this some time // it shouldn't have trailing '/', and instead it should have leading '/' @@ -1045,14 +1046,14 @@ protected void dropLinks() { // @see also {@link AbstractItem#getUrl} StaplerRequest req = Stapler.getCurrentRequest(); if (req != null) { - String seed = Functions.getNearestAncestorUrl(req,this); - if(seed!=null) { + String seed = Functions.getNearestAncestorUrl(req, this); + if (seed != null) { // trim off the context path portion and leading '/', but add trailing '/' - return seed.substring(req.getContextPath().length()+1)+'/'; + return seed.substring(req.getContextPath().length() + 1) + '/'; } } - return project.getUrl()+getNumber()+'/'; + return project.getUrl() + getNumber() + '/'; } /** @@ -1063,15 +1064,15 @@ protected void dropLinks() { * misconfiguration to break this value, with network set up like Apache reverse proxy. * This method is only intended for the remote API clients who cannot resolve relative references. */ - @Exported(visibility=2,name="url") + @Exported(visibility = 2, name = "url") @Deprecated public final @NonNull String getAbsoluteUrl() { - return project.getAbsoluteUrl()+getNumber()+'/'; + return project.getAbsoluteUrl() + getNumber() + '/'; } @Override public final @NonNull String getSearchUrl() { - return getNumber()+"/"; + return getNumber() + "/"; } /** @@ -1082,7 +1083,7 @@ protected void dropLinks() { public @NonNull String getId() { return id != null ? id : Integer.toString(number); } - + /** * Get the root directory of this {@link Run} on the controller. * Files related to this {@link Run} should be stored below this directory. @@ -1141,14 +1142,14 @@ protected void dropLinks() { */ @Deprecated public File getArtifactsDir() { - return new File(getRootDir(),"archive"); + return new File(getRootDir(), "archive"); } /** * Gets the artifacts (relative to {@link #getArtifactsDir()}. * @return The list can be empty but never null - */ - @Exported + */ + @Exported public @NonNull List getArtifacts() { return getArtifactsUpTo(Integer.MAX_VALUE); } @@ -1156,7 +1157,7 @@ public File getArtifactsDir() { /** * Gets the first N artifacts. * @return The list can be empty but never null - */ + */ public @NonNull List getArtifactsUpTo(int artifactsNumber) { SerializableArtifactList sal; VirtualFile root = getArtifactManager().root(); @@ -1185,10 +1186,12 @@ private static final class AddArtifacts extends MasterToSlaveCallable=upTo) break; + n += addArtifacts(sub, childPath + '/', childHref + '/', r, a, upTo - n); + if (n >= upTo) break; } else { // Don't store collapsed path in ArrayList (for correct data in external API) r.add(collapsed ? new SerializableArtifact(child, a.relativePath, a.href, length, a.treeNodeId) : a); - if (++n>=upTo) break; + if (++n >= upTo) break; } } return n; } - + /** * Maximum number of artifacts to list before using switching to the tree view. */ @@ -1247,7 +1250,7 @@ private static int addArtifacts(@NonNull VirtualFile dir, public static final int TREE_CUTOFF = Integer.parseInt(SystemProperties.getString("hudson.model.Run.ArtifactList.treeCutoff", "40")); // ..and then "too many" - + /** {@link Run.Artifact} without the implicit link to {@link Run} */ private static final class SerializableArtifact implements Serializable { private static final long serialVersionUID = 1L; @@ -1256,6 +1259,7 @@ private static final class SerializableArtifact implements Serializable { final String href; final String length; final String treeNodeId; + SerializableArtifact(String name, String relativePath, String href, String length, String treeNodeId) { this.name = name; this.relativePath = relativePath; @@ -1278,7 +1282,7 @@ public final class ArtifactList extends ArrayList { * Map of Artifact to treeNodeId of parent node in tree view. * Contains Artifact objects for directories and files (the ArrayList contains only files). */ - private LinkedHashMap tree = new LinkedHashMap<>(); + private LinkedHashMap tree = new LinkedHashMap<>(); void updateFrom(SerializableArtifactList clone) { Map artifacts = new HashMap<>(); // need to share objects between tree and list, since computeDisplayName mutates displayPath @@ -1298,43 +1302,43 @@ void updateFrom(SerializableArtifactList clone) { } } - public Map getTree() { + public Map getTree() { return tree; } public void computeDisplayName() { - if(size()>LIST_CUTOFF) return; // we are not going to display file names, so no point in computing this + if (size() > LIST_CUTOFF) return; // we are not going to display file names, so no point in computing this int maxDepth = 0; int[] len = new int[size()]; String[][] tokens = new String[size()][]; - for( int i=0; i names = new HashMap<>(); + Map names = new HashMap<>(); for (int i = 0; i < tokens.length; i++) { String[] token = tokens[i]; - String displayName = combineLast(token,len[i]); + String displayName = combineLast(token, len[i]); Integer j = names.put(displayName, i); - if(j!=null) { + if (j != null) { collision = true; - if(j>=0) + if (j >= 0) len[j]++; len[i]++; - names.put(displayName,-1); // occupy this name but don't let len[i] incremented with additional collisions + names.put(displayName, -1); // occupy this name but don't let len[i] incremented with additional collisions } } - } while(collision && depth++0) buf.append('/'); + for (int i = Math.max(0, token.length - n); i < token.length; i++) { + if (buf.length() > 0) buf.append('/'); buf.append(token[i]); } return buf.toString(); @@ -1358,7 +1362,7 @@ public class Artifact { /** * Relative path name from artifacts root. */ - @Exported(visibility=3) + @Exported(visibility = 3) public final String relativePath; /** @@ -1407,18 +1411,18 @@ public class Artifact { */ @Deprecated public @NonNull File getFile() { - return new File(getArtifactsDir(),relativePath); + return new File(getArtifactsDir(), relativePath); } /** * Returns just the file name portion, without the path. */ - @Exported(visibility=3) + @Exported(visibility = 3) public String getFileName() { return name; } - @Exported(visibility=3) + @Exported(visibility = 3) public String getDisplayPath() { return displayPath; } @@ -1430,8 +1434,8 @@ public String getHref() { public String getLength() { return length; } - - public long getFileSize(){ + + public long getFileSize() { try { return Long.decode(length); } @@ -1465,7 +1469,7 @@ public Collection getBuildFingerprints() { } return Collections.emptyList(); } - + /** * Returns the log file. * @return The file may reference both uncompressed or compressed logs @@ -1490,15 +1494,15 @@ public Collection getBuildFingerprints() { * Returns an input stream that reads from the log file. * It will use a gzip-compressed log file (log.gz) if that exists. * - * @return An input stream from the log file. + * @return An input stream from the log file. * If the log file does not exist, the error message will be returned to the output. * @since 1.349 */ public @NonNull InputStream getLogInputStream() throws IOException { - File logFile = getLogFile(); - - if (logFile.exists() ) { - // Checking if a ".gz" file was return + File logFile = getLogFile(); + + if (logFile.exists()) { + // Checking if a ".gz" file was return try { InputStream fis = Files.newInputStream(logFile.toPath()); if (logFile.getName().endsWith(".gz")) { @@ -1509,15 +1513,15 @@ public Collection getBuildFingerprints() { } catch (InvalidPathException e) { throw new IOException(e); } - } - + } + String message = "No such file: " + logFile; - return new ByteArrayInputStream(charset != null ? message.getBytes(charset) : message.getBytes()); + return new ByteArrayInputStream(charset != null ? message.getBytes(charset) : message.getBytes(Charset.defaultCharset())); } - + public @NonNull Reader getLogReader() throws IOException { - if (charset==null) return new InputStreamReader(getLogInputStream()); - else return new InputStreamReader(getLogInputStream(),charset); + if (charset == null) return new InputStreamReader(getLogInputStream(), Charset.defaultCharset()); + else return new InputStreamReader(getLogInputStream(), charset); } /** @@ -1525,6 +1529,7 @@ public Collection getBuildFingerprints() { * * @since 1.349 */ + @SuppressFBWarnings(value = "RV_RETURN_VALUE_IGNORED", justification = "method signature does not permit plumbing through the return value") public void writeLogTo(long offset, @NonNull XMLOutput out) throws IOException { long start = offset; if (offset > 0) { @@ -1567,9 +1572,9 @@ public void writeWholeLogTo(@NonNull OutputStream out) throws IOException, Inter /** * Used to URL-bind {@link AnnotatedLargeText}. * @return A {@link Run} log with annotations - */ + */ public @NonNull AnnotatedLargeText getLogText() { - return new AnnotatedLargeText(getLogFile(),getCharset(),!isLogUpdated(),this); + return new AnnotatedLargeText(getLogFile(), getCharset(), !isLogUpdated(), this); } @Override @@ -1618,7 +1623,7 @@ public SearchIndex getSearchIndex() { } }); for (Action a : getAllActions()) { - if(a.getIconFileName()!=null) + if (a.getIconFileName() != null) builder.add(a.getUrlName()); } return builder; @@ -1635,7 +1640,7 @@ public ACL getACL() { } /** - * Deletes this build's artifacts. + * Deletes this build's artifacts. * * @throws IOException * if we fail to delete. @@ -1681,17 +1686,17 @@ public void delete() throws IOException { } return; } - + //The root dir exists and is a directory that needs to be purged RunListener.fireDeleted(this); - + if (artifactManager != null) { deleteArtifacts(); } // for StandardArtifactManager, deleting the whole build dir suffices - + synchronized (this) { // avoid holding a lock while calling plugin impls of onDeleted - File tmp = new File(rootDir.getParentFile(),'.'+rootDir.getName()); - + File tmp = new File(rootDir.getParentFile(), '.' + rootDir.getName()); + if (tmp.exists()) { Util.deleteRecursive(tmp); } @@ -1704,7 +1709,7 @@ public void delete() throws IOException { } catch (UnsupportedOperationException | SecurityException ex) { throw new IOException(rootDir + " is in use", ex); } - + Util.deleteRecursive(tmp); // some user reported that they see some left-over .xyz files in the workspace, // so just to make sure we've really deleted it, schedule the deletion on VM exit, too. @@ -1718,7 +1723,7 @@ public void delete() throws IOException { @SuppressWarnings("unchecked") // seems this is too clever for Java's type system? private void removeRunFromParent() { - getParent().removeRun((RunT)this); + getParent().removeRun((RunT) this); } @@ -1726,7 +1731,7 @@ private void removeRunFromParent() { * @see CheckPoint#report() */ /*package*/ static void reportCheckpoint(@NonNull CheckPoint id) { - Run.RunExecution exec = RunnerStack.INSTANCE.peek(); + Run.RunExecution exec = RunnerStack.INSTANCE.peek(); if (exec == null) { return; } @@ -1737,20 +1742,20 @@ private void removeRunFromParent() { * @see CheckPoint#block() */ /*package*/ static void waitForCheckpoint(@NonNull CheckPoint id, @CheckForNull BuildListener listener, @CheckForNull String waiter) throws InterruptedException { - while(true) { - Run.RunExecution exec = RunnerStack.INSTANCE.peek(); + while (true) { + Run.RunExecution exec = RunnerStack.INSTANCE.peek(); if (exec == null) { return; } Run b = exec.getBuild().getPreviousBuildInProgress(); - if(b==null) return; // no pending earlier build + if (b == null) return; // no pending earlier build Run.RunExecution runner = b.runner; - if(runner==null) { + if (runner == null) { // polled at the wrong moment. try again. Thread.sleep(0); continue; } - if(runner.checkpoints.waitForCheckPoint(id, listener, waiter)) + if (runner.checkpoints.waitForCheckPoint(id, listener, waiter)) return; // confirmed that the previous build reached the check point // the previous build finished without ever reaching the check point. try again. @@ -1770,7 +1775,7 @@ protected abstract class Runner extends RunExecution {} */ public abstract class RunExecution { /** - * Keeps track of the check points attained by a build, and abstracts away the synchronization needed to + * Keeps track of the check points attained by a build, and abstracts away the synchronization needed to * maintain this data structure. */ private final class CheckpointSet { @@ -1817,7 +1822,7 @@ private synchronized void allDone() { private final CheckpointSet checkpoints = new CheckpointSet(); - private final Map attributes = new HashMap<>(); + private final Map attributes = new HashMap<>(); /** * Performs the main build and returns the status code. @@ -1825,7 +1830,7 @@ private synchronized void allDone() { * @throws Exception * exception will be recorded and the build will be considered a failure. */ - public abstract @NonNull Result run(@NonNull BuildListener listener ) throws Exception, RunnerAbortedException; + public abstract @NonNull Result run(@NonNull BuildListener listener) throws Exception; /** * Performs the post-build action. @@ -1837,7 +1842,7 @@ private synchronized void allDone() { * even if the build is successful, this build still won't be picked up * by {@link Job#getLastSuccessfulBuild()}. */ - public abstract void post(@NonNull BuildListener listener ) throws Exception; + public abstract void post(@NonNull BuildListener listener) throws Exception; /** * Performs final clean up action. @@ -1865,7 +1870,7 @@ private synchronized void allDone() { * * @since 1.473 */ - public @NonNull Map getAttributes() { + public @NonNull Map getAttributes() { return attributes; } } @@ -1889,11 +1894,11 @@ protected final void run(@NonNull Runner job) { } protected final void execute(@NonNull RunExecution job) { - if(result!=null) + if (result != null) return; // already built. OutputStream logger = null; - StreamBuildListener listener=null; + StreamBuildListener listener = null; runner = job; onStartBuilding(); @@ -1929,7 +1934,7 @@ protected final void execute(@NonNull RunExecution job) { listener.getLogger().println(Messages.Run_running_as_(id)); } - RunListener.fireStarted(this,listener); + RunListener.fireStarted(this, listener); setResult(job.run(listener)); @@ -1937,21 +1942,21 @@ protected final void execute(@NonNull RunExecution job) { CheckPoint.MAIN_COMPLETED.report(); } catch (ThreadDeath t) { throw t; - } catch( AbortException e ) {// orderly abortion. + } catch (AbortException e) { // orderly abortion. result = Result.FAILURE; listener.error(e.getMessage()); - LOGGER.log(FINE, "Build "+this+" aborted",e); - } catch( RunnerAbortedException e ) {// orderly abortion. + LOGGER.log(FINE, "Build " + this + " aborted", e); + } catch (RunnerAbortedException e) { // orderly abortion. result = Result.FAILURE; - LOGGER.log(FINE, "Build "+this+" aborted",e); - } catch( InterruptedException e) { + LOGGER.log(FINE, "Build " + this + " aborted", e); + } catch (InterruptedException e) { // aborted result = Executor.currentExecutor().abortResult(); listener.getLogger().println(Messages.Run_BuildAborted()); - Executor.currentExecutor().recordCauseOfInterruption(Run.this,listener); + Executor.currentExecutor().recordCauseOfInterruption(Run.this, listener); LOGGER.log(Level.INFO, this + " aborted", e); - } catch( Throwable e ) { - handleFatalBuildProblem(listener,e); + } catch (Throwable e) { + handleFatalBuildProblem(listener, e); result = Result.FAILURE; } @@ -1960,8 +1965,8 @@ protected final void execute(@NonNull RunExecution job) { } catch (ThreadDeath t) { throw t; - } catch( Throwable e ) { - handleFatalBuildProblem(listener,e); + } catch (Throwable e) { + handleFatalBuildProblem(listener, e); result = Result.FAILURE; } finally { long end = System.currentTimeMillis(); @@ -1976,11 +1981,11 @@ protected final void execute(@NonNull RunExecution job) { state = State.POST_PRODUCTION; if (listener != null) { - RunListener.fireCompleted(this,listener); + RunListener.fireCompleted(this, listener); try { job.cleanUp(listener); } catch (Exception e) { - handleFatalBuildProblem(listener,e); + handleFatalBuildProblem(listener, e); // too late to update the result now } listener.finished(result); @@ -1990,14 +1995,14 @@ protected final void execute(@NonNull RunExecution job) { try { save(); } catch (IOException e) { - LOGGER.log(Level.SEVERE, "Failed to save build record",e); + LOGGER.log(Level.SEVERE, "Failed to save build record", e); } } try { getParent().logRotate(); } catch (Exception e) { - LOGGER.log(Level.SEVERE, "Failed to rotate log",e); + LOGGER.log(Level.SEVERE, "Failed to rotate log", e); } } finally { onEndBuilding(); @@ -2038,7 +2043,7 @@ private StreamBuildListener createBuildListener(@NonNull RunExecution job, Outpu } } - return new StreamBuildListener(logger,charset); + return new StreamBuildListener(logger, charset); } /** @@ -2051,15 +2056,15 @@ public final void updateSymlinks(@NonNull TaskListener listener) throws Interrup * Handles a fatal build problem (exception) that occurred during the build. */ private void handleFatalBuildProblem(@NonNull BuildListener listener, @NonNull Throwable e) { - if(listener!=null) { - LOGGER.log(FINE, getDisplayName()+" failed to build",e); + if (listener != null) { + LOGGER.log(FINE, getDisplayName() + " failed to build", e); - if(e instanceof IOException) - Util.displayIOException((IOException)e,listener); + if (e instanceof IOException) + Util.displayIOException((IOException) e, listener); Functions.printStackTrace(e, listener.fatalError(e.getMessage())); } else { - LOGGER.log(SEVERE, getDisplayName()+" failed to build and we don't even have a listener",e); + LOGGER.log(SEVERE, getDisplayName() + " failed to build and we don't even have a listener", e); } } @@ -2070,7 +2075,7 @@ protected void onStartBuilding() { LOGGER.log(FINER, "moving to BUILDING on {0}", this); state = State.BUILDING; startTime = System.currentTimeMillis(); - if (runner!=null) + if (runner != null) RunnerStack.INSTANCE.push(runner); RunListener.fireInitialize(this); } @@ -2082,7 +2087,7 @@ protected void onEndBuilding() { // signal that we've finished building. state = State.COMPLETED; LOGGER.log(FINER, "moving to COMPLETED on {0}", this); - if (runner!=null) { + if (runner != null) { // MavenBuilds may be created without their corresponding runners. runner.checkpoints.allDone(); runner = null; @@ -2101,23 +2106,26 @@ protected void onEndBuilding() { */ @Override public synchronized void save() throws IOException { - if(BulkChange.contains(this)) return; + if (BulkChange.contains(this)) return; getDataFile().write(this); SaveableListener.fireOnChange(this, getDataFile()); } private @NonNull XmlFile getDataFile() { - return new XmlFile(XSTREAM,new File(getRootDir(),"build.xml")); + return new XmlFile(XSTREAM, new File(getRootDir(), "build.xml")); } protected Object writeReplace() { return XmlFile.replaceIfNotAtTopLevel(this, () -> new Replacer(this)); } + private static class Replacer { private final String id; + Replacer(Run r) { id = r.getExternalizableId(); } + private Object readResolve() { return fromExternalizableId(id); } @@ -2132,7 +2140,7 @@ private Object readResolve() { */ @Deprecated public @NonNull String getLog() throws IOException { - return Util.loadFile(getLogFile(),getCharset()); + return Util.loadFile(getLogFile(), getCharset()); } /** @@ -2183,7 +2191,7 @@ private Object readResolve() { // Use set (replaces the first element) rather than add so that // the list doesn't grow beyond the specified maximum number of lines. if (lines == maxLines) { - lastLines.set(0, "[...truncated " + Functions.humanReadableByteSize(filePointer)+ "...]"); + lastLines.set(0, "[...truncated " + Functions.humanReadableByteSize(filePointer) + "...]"); } return ConsoleNote.removeNotes(lastLines); @@ -2195,8 +2203,8 @@ private String convertBytesToString(List bytes) { return new String(ArrayUtils.toPrimitive(byteArray), getCharset()); } - public void doBuildStatus( StaplerRequest req, StaplerResponse rsp ) throws IOException { - rsp.sendRedirect2(req.getContextPath()+"/images/48x48/"+getBuildStatusUrl()); + public void doBuildStatus(StaplerRequest req, StaplerResponse rsp) throws IOException { + rsp.sendRedirect2(req.getContextPath() + "/images/48x48/" + getBuildStatusUrl()); } public @NonNull String getBuildStatusUrl() { @@ -2231,7 +2239,7 @@ public abstract static class StatusSummarizer implements ExtensionPoint { * @param trend the result of {@link ResultTrend#getResultTrend(hudson.model.Run)} on {@code run} (precomputed for efficiency) * @return a summary, or null to fall back to other summarizers or built-in behavior */ - public abstract @CheckForNull Summary summarize(@NonNull Run run, @NonNull ResultTrend trend); + public abstract @CheckForNull Summary summarize(@NonNull Run run, @NonNull ResultTrend trend); } /** @@ -2243,9 +2251,9 @@ public abstract static class StatusSummarizer implements ExtensionPoint { if (isBuilding()) { return new Summary(false, Messages.Run_Summary_Unknown()); } - + ResultTrend trend = ResultTrend.getResultTrend(this); - + for (StatusSummarizer summarizer : ExtensionList.lookup(StatusSummarizer.class)) { Summary summary = summarizer.summarize(this, trend); if (summary != null) { @@ -2254,31 +2262,31 @@ public abstract static class StatusSummarizer implements ExtensionPoint { } switch (trend) { - case ABORTED : return new Summary(false, Messages.Run_Summary_Aborted()); - - case NOT_BUILT : return new Summary(false, Messages.Run_Summary_NotBuilt()); - - case FAILURE : return new Summary(true, Messages.Run_Summary_BrokenSinceThisBuild()); - - case STILL_FAILING : + case ABORTED: return new Summary(false, Messages.Run_Summary_Aborted()); + + case NOT_BUILT: return new Summary(false, Messages.Run_Summary_NotBuilt()); + + case FAILURE: return new Summary(true, Messages.Run_Summary_BrokenSinceThisBuild()); + + case STILL_FAILING: RunT since = getPreviousNotFailedBuild(); - if(since==null) + if (since == null) return new Summary(false, Messages.Run_Summary_BrokenForALongTime()); RunT failedBuild = since.getNextBuild(); return new Summary(false, Messages.Run_Summary_BrokenSince(failedBuild.getDisplayName())); - + case NOW_UNSTABLE: - case STILL_UNSTABLE : + case STILL_UNSTABLE: return new Summary(false, Messages.Run_Summary_Unstable()); - case UNSTABLE : + case UNSTABLE: return new Summary(true, Messages.Run_Summary_Unstable()); - - case SUCCESS : + + case SUCCESS: return new Summary(false, Messages.Run_Summary_Stable()); - - case FIXED : + + case FIXED: return new Summary(false, Messages.Run_Summary_BackToNormal()); - + default: return new Summary(false, Messages.Run_Summary_Unknown()); } @@ -2289,7 +2297,7 @@ public abstract static class StatusSummarizer implements ExtensionPoint { * @throws AccessDeniedException Access denied */ public @NonNull DirectoryBrowserSupport doArtifact() { - if(Functions.isArtifactsPermissionEnabled()) { + if (Functions.isArtifactsPermissionEnabled()) { checkPermission(ARTIFACTS); } return new DirectoryBrowserSupport(this, getArtifactManager().root(), Messages.Run_ArtifactsBrowserTitle(project.getDisplayName(), getDisplayName()), "package.png", true); @@ -2308,13 +2316,13 @@ public void doBuildNumber(StaplerResponse rsp) throws IOException { /** * Returns the build time stamp in the body. */ - public void doBuildTimestamp( StaplerRequest req, StaplerResponse rsp, @QueryParameter String format) throws IOException { + public void doBuildTimestamp(StaplerRequest req, StaplerResponse rsp, @QueryParameter String format) throws IOException { rsp.setContentType("text/plain"); rsp.setCharacterEncoding("US-ASCII"); rsp.setStatus(HttpServletResponse.SC_OK); - DateFormat df = format==null ? - DateFormat.getDateTimeInstance(DateFormat.SHORT,DateFormat.SHORT, Locale.ENGLISH) : - new SimpleDateFormat(format,req.getLocale()); + DateFormat df = format == null ? + DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.ENGLISH) : + new SimpleDateFormat(format, req.getLocale()); rsp.getWriter().print(df.format(getTime())); } @@ -2336,8 +2344,8 @@ public void doConsoleText(StaplerRequest req, StaplerResponse rsp) throws IOExce * Use {@code getLogText().doProgressiveText(req,rsp)} */ @Deprecated - public void doProgressiveLog( StaplerRequest req, StaplerResponse rsp) throws IOException { - getLogText().doProgressText(req,rsp); + public void doProgressiveLog(StaplerRequest req, StaplerResponse rsp) throws IOException { + getLogText().doProgressText(req, rsp); } /** @@ -2358,7 +2366,7 @@ public boolean canToggleLogKeep() { } @RequirePOST - public void doToggleLogKeep( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public void doToggleLogKeep(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { keepLog(!keepLog); rsp.forwardToPreviousPage(req); } @@ -2366,7 +2374,7 @@ public void doToggleLogKeep( StaplerRequest req, StaplerResponse rsp ) throws IO /** * Marks this build to be kept. */ - @CLIMethod(name="keep-build") + @CLIMethod(name = "keep-build") public final void keepLog() throws IOException { keepLog(true); } @@ -2381,27 +2389,27 @@ public void keepLog(boolean newValue) throws IOException { * Deletes the build when the button is pressed. */ @RequirePOST - public void doDoDelete( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public void doDoDelete(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { checkPermission(DELETE); // We should not simply delete the build if it has been explicitly // marked to be preserved, or if the build should not be deleted // due to dependencies! String why = getWhyKeepLog(); - if (why!=null) { + if (why != null) { sendError(Messages.Run_UnableToDelete(getFullDisplayName(), why), req, rsp); return; } - try{ + try { delete(); } - catch(IOException ex){ + catch (IOException ex) { req.setAttribute("stackTraces", Functions.printThrowable(ex)); - req.getView(this, "delete-retry.jelly").forward(req, rsp); + req.getView(this, "delete-retry.jelly").forward(req, rsp); return; } - rsp.sendRedirect2(req.getContextPath()+'/' + getParent().getUrl()); + rsp.sendRedirect2(req.getContextPath() + '/' + getParent().getUrl()); } public void setDescription(String description) throws IOException { @@ -2409,12 +2417,12 @@ public void setDescription(String description) throws IOException { this.description = description; save(); } - + /** * Accepts the new description. */ @RequirePOST - public synchronized void doSubmitDescription( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public synchronized void doSubmitDescription(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { setDescription(req.getParameter("description")); rsp.sendRedirect("."); // go to the top page } @@ -2424,7 +2432,7 @@ public synchronized void doSubmitDescription( StaplerRequest req, StaplerRespons * Use {@link #getEnvironment(TaskListener)} instead. */ @Deprecated - public Map getEnvVars() { + public Map getEnvVars() { LOGGER.log(WARNING, "deprecated call to Run.getEnvVars\n\tat {0}", new Throwable().getStackTrace()[1]); try { return getEnvironment(new LogTaskListener(LOGGER, Level.INFO)); @@ -2454,20 +2462,20 @@ public EnvVars getEnvironment() throws IOException, InterruptedException { *

      * Unlike earlier {@link #getEnvVars()}, this map contains the whole environment, * not just the overrides, so one can introspect values to change its behavior. - * + * * @return the map with the environmental variables. * @since 1.305 */ public @NonNull EnvVars getEnvironment(@NonNull TaskListener listener) throws IOException, InterruptedException { Computer c = Computer.currentComputer(); - Node n = c==null ? null : c.getNode(); + Node n = c == null ? null : c.getNode(); - EnvVars env = getParent().getEnvironment(n,listener); + EnvVars env = getParent().getEnvironment(n, listener); env.putAll(getCharacteristicEnvVars()); // apply them in a reverse order so that higher ordinal ones can modify values added by lower ordinal ones for (EnvironmentContributor ec : EnvironmentContributor.all().reverseView()) - ec.buildEnvironmentFor(this,env,listener); + ec.buildEnvironmentFor(this, env, listener); if (!(this instanceof AbstractBuild)) { for (EnvironmentContributingAction a : getActions(EnvironmentContributingAction.class)) { @@ -2484,9 +2492,9 @@ public EnvVars getEnvironment() throws IOException, InterruptedException { */ public @NonNull final EnvVars getCharacteristicEnvVars() { EnvVars env = getParent().getCharacteristicEnvVars(); - env.put("BUILD_NUMBER",String.valueOf(number)); - env.put("BUILD_ID",getId()); - env.put("BUILD_TAG","jenkins-"+getParent().getFullName().replace('/', '-')+"-"+number); + env.put("BUILD_NUMBER", String.valueOf(number)); + env.put("BUILD_ID", getId()); + env.put("BUILD_TAG", "jenkins-" + getParent().getFullName().replace('/', '-') + "-" + number); return env; } @@ -2506,7 +2514,7 @@ public EnvVars getEnvironment() throws IOException, InterruptedException { * @throws IllegalArgumentException if the ID is malformed * @throws AccessDeniedException as per {@link ItemGroup#getItem} */ - public @CheckForNull static Run fromExternalizableId(String id) throws IllegalArgumentException, AccessDeniedException { + public @CheckForNull static Run fromExternalizableId(String id) throws IllegalArgumentException, AccessDeniedException { int hash = id.lastIndexOf('#'); if (hash <= 0) { throw new IllegalArgumentException("Invalid id"); @@ -2522,7 +2530,7 @@ public EnvVars getEnvironment() throws IOException, InterruptedException { if (j == null) { return null; } - Job job = j.getItemByFullName(jobName, Job.class); + Job job = j.getItemByFullName(jobName, Job.class); if (job == null) { return null; } @@ -2533,7 +2541,7 @@ public EnvVars getEnvironment() throws IOException, InterruptedException { * Returns the estimated duration for this run if it is currently running. * Default to {@link Job#getEstimatedDuration()}, may be overridden in subclasses * if duration may depend on run specific parameters (like incremental Maven builds). - * + * * @return the estimated duration in milliseconds * @since 1.383 */ @@ -2543,7 +2551,7 @@ public long getEstimatedDuration() { } @POST - public @NonNull HttpResponse doConfigSubmit( StaplerRequest req ) throws IOException, ServletException, FormException { + public @NonNull HttpResponse doConfigSubmit(StaplerRequest req) throws IOException, ServletException, FormException { checkPermission(UPDATE); try (BulkChange bc = new BulkChange(this)) { JSONObject json = req.getSubmittedForm(); @@ -2563,17 +2571,17 @@ protected void submit(JSONObject json) throws IOException { /** * Alias to {@link #XSTREAM} so that one can access additional methods on {@link XStream2} more easily. */ - public static final XStream2 XSTREAM2 = (XStream2)XSTREAM; + public static final XStream2 XSTREAM2 = (XStream2) XSTREAM; static { - XSTREAM.alias("build",FreeStyleBuild.class); + XSTREAM.alias("build", FreeStyleBuild.class); XSTREAM.registerConverter(Result.conv); } private static final Logger LOGGER = Logger.getLogger(Run.class.getName()); /** - * Sort by date. Newer ones first. + * Sort by date. Newer ones first. */ public static final Comparator ORDER_BY_DATE = new Comparator() { @Override @@ -2600,7 +2608,7 @@ public int compare(@NonNull Run lhs, @NonNull Run rhs) { @Override public String getEntryID(Run e) { // can't use a meaningful year field unless we remember when the job was created. - return "tag:hudson.dev.java.net,2008:"+e.getParent().getAbsoluteUrl(); + return "tag:hudson.dev.java.net,2008:" + e.getParent().getAbsoluteUrl(); } }; @@ -2610,24 +2618,27 @@ public String getEntryID(Run e) { public final class KeepLogBuildBadge implements BuildBadgeAction { @Override public @CheckForNull String getIconFileName() { return null; } + @Override public @CheckForNull String getDisplayName() { return null; } + @Override public @CheckForNull String getUrlName() { return null; } + public @CheckForNull String getWhyKeepLog() { return Run.this.getWhyKeepLog(); } } - public static final PermissionGroup PERMISSIONS = new PermissionGroup(Run.class,Messages._Run_Permissions_Title()); - public static final Permission DELETE = new Permission(PERMISSIONS,"Delete",Messages._Run_DeletePermission_Description(),Permission.DELETE, PermissionScope.RUN); - public static final Permission UPDATE = new Permission(PERMISSIONS,"Update",Messages._Run_UpdatePermission_Description(),Permission.UPDATE, PermissionScope.RUN); + public static final PermissionGroup PERMISSIONS = new PermissionGroup(Run.class, Messages._Run_Permissions_Title()); + public static final Permission DELETE = new Permission(PERMISSIONS, "Delete", Messages._Run_DeletePermission_Description(), Permission.DELETE, PermissionScope.RUN); + public static final Permission UPDATE = new Permission(PERMISSIONS, "Update", Messages._Run_UpdatePermission_Description(), Permission.UPDATE, PermissionScope.RUN); /** See {@link hudson.Functions#isArtifactsPermissionEnabled} */ - public static final Permission ARTIFACTS = new Permission(PERMISSIONS,"Artifacts",Messages._Run_ArtifactsPermission_Description(), null, + public static final Permission ARTIFACTS = new Permission(PERMISSIONS, "Artifacts", Messages._Run_ArtifactsPermission_Description(), null, Functions.isArtifactsPermissionEnabled(), new PermissionScope[]{PermissionScope.RUN}); private static class DefaultFeedAdapter implements FeedAdapter { @Override public String getEntryTitle(Run entry) { - return entry.getFullDisplayName()+" ("+entry.getBuildStatusSummary().message+")"; + return entry.getFullDisplayName() + " (" + entry.getBuildStatusSummary().message + ")"; } @Override @@ -2639,7 +2650,7 @@ public String getEntryUrl(Run entry) { public String getEntryID(Run entry) { return "tag:" + "hudson.dev.java.net," + entry.getTimestamp().get(Calendar.YEAR) + ":" - + entry.getParent().getFullName()+':'+entry.getId(); + + entry.getParent().getFullName() + ':' + entry.getId(); } @Override @@ -2661,9 +2672,9 @@ public String getEntryAuthor(Run entry) { @Override public Object getDynamic(String token, StaplerRequest req, StaplerResponse rsp) { Object returnedResult = super.getDynamic(token, req, rsp); - if (returnedResult == null){ + if (returnedResult == null) { //check transient actions too - for(Action action: getTransientActions()){ + for (Action action : getTransientActions()) { String urlName = action.getUrlName(); if (urlName == null) { continue; diff --git a/core/src/main/java/hudson/model/RunAction.java b/core/src/main/java/hudson/model/RunAction.java index 995a12d52e2b3..f02008bb5077c 100644 --- a/core/src/main/java/hudson/model/RunAction.java +++ b/core/src/main/java/hudson/model/RunAction.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import jenkins.model.RunAction2; @@ -32,7 +33,7 @@ public interface RunAction extends Action { /** * Called after the build is loaded and the object is added to the build list. - * + * * Because {@link RunAction}s are persisted with {@link Run}, the implementation * can keep a reference to {@link Run} in a field (which is set via {@link #onAttached(Run)}) */ diff --git a/core/src/main/java/hudson/model/RunMap.java b/core/src/main/java/hudson/model/RunMap.java index 6b2ce262acc48..955037ab35556 100644 --- a/core/src/main/java/hudson/model/RunMap.java +++ b/core/src/main/java/hudson/model/RunMap.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,12 +21,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static java.util.logging.Level.FINEST; import static jenkins.model.lazy.AbstractLazyLoadRunMap.Direction.ASC; import static jenkins.model.lazy.AbstractLazyLoadRunMap.Direction.DESC; +import hudson.Util; import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; @@ -43,7 +45,6 @@ import jenkins.model.lazy.AbstractLazyLoadRunMap; import jenkins.model.lazy.BuildReference; import jenkins.model.lazy.LazyBuildMixIn; -import org.apache.commons.collections.comparators.ReverseComparator; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; @@ -57,11 +58,11 @@ * * @author Kohsuke Kawaguchi */ -public final class RunMap> extends AbstractLazyLoadRunMap implements Iterable { +public final class RunMap> extends AbstractLazyLoadRunMap implements Iterable { /** * Read-only view of this map. */ - private final SortedMap view = Collections.unmodifiableSortedMap(this); + private final SortedMap view = Collections.unmodifiableSortedMap(this); private Constructor cons; @@ -106,13 +107,13 @@ public Iterator iterator() { @Override public boolean hasNext() { - return next!=null; + return next != null; } @Override public R next() { last = next; - if (last!=null) + if (last != null) next = last.getPreviousBuild(); else throw new NoSuchElementException(); @@ -121,7 +122,7 @@ public R next() { @Override public void remove() { - if (last==null) + if (last == null) throw new UnsupportedOperationException(); removeValue(last); } @@ -138,7 +139,7 @@ public boolean removeValue(R run) { /** * Gets the read-only view of this map. */ - public SortedMap getView() { + public SortedMap getView() { return view; } @@ -158,7 +159,7 @@ public R oldestValue() { /** * @deprecated as of 1.485 - * Use {@link ReverseComparator} + * Use {@link Comparator#reverseOrder} */ @Deprecated public static final Comparator COMPARATOR = Comparator.reverseOrder(); @@ -166,7 +167,7 @@ public R oldestValue() { /** * {@link Run} factory. */ - public interface Constructor> { + public interface Constructor> { R create(File dir) throws IOException; } @@ -195,7 +196,7 @@ public R put(R r) { proposeNewNumber(r.getNumber()); } try { - Files.createDirectories(rootDir.toPath()); + Util.createDirectories(rootDir.toPath()); } catch (IOException e) { throw new UncheckedIOException(e); } @@ -225,7 +226,7 @@ protected BuildReference createReference(R r) { @Override protected R retrieve(File d) throws IOException { - if(new File(d,"build.xml").exists()) { + if (new File(d, "build.xml").exists()) { // if the build result file isn't in the directory, ignore it. try { R b = cons.create(d); diff --git a/core/src/main/java/hudson/model/RunParameterDefinition.java b/core/src/main/java/hudson/model/RunParameterDefinition.java index 56e6f4e775945..3ac138a8761c8 100644 --- a/core/src/main/java/hudson/model/RunParameterDefinition.java +++ b/core/src/main/java/hudson/model/RunParameterDefinition.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Tom Huybrechts, Geoff Cummings - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,10 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import hudson.util.EnumConverter; import hudson.util.RunList; @@ -59,7 +61,7 @@ public String getName() { Stapler.CONVERT_UTILS.register(new EnumConverter(), RunParameterFilter.class); } } - + private final String projectName; private final String runId; private final RunParameterFilter filter; @@ -78,11 +80,11 @@ public RunParameterDefinition(@NonNull String name, String projectName, @CheckFo /** * @deprecated as of 1.517 - */ + */ @Deprecated public RunParameterDefinition(@NonNull String name, String projectName, @CheckForNull String description) { - // delegate to updated constructor with additional RunParameterFilter parameter defaulted to ALL. - this(name, projectName, description, RunParameterFilter.ALL); + // delegate to updated constructor with additional RunParameterFilter parameter defaulted to ALL. + this(name, projectName, description, RunParameterFilter.ALL); } private RunParameterDefinition(@NonNull String name, String projectName, String runId, @CheckForNull String description, @CheckForNull RunParameterFilter filter) { @@ -117,7 +119,7 @@ public Job getProject() { */ @Exported public RunParameterFilter getFilter() { - // if filter is null, default to RunParameterFilter.ALL + // if filter is null, default to RunParameterFilter.ALL return null == filter ? RunParameterFilter.ALL : filter; } @@ -132,14 +134,14 @@ public RunList getBuilds() { return getProject().getBuilds().overThresholdOnly(Result.ABORTED).completedOnly(); case SUCCESSFUL: return getProject().getBuilds().overThresholdOnly(Result.UNSTABLE).completedOnly(); - case STABLE : + case STABLE: return getProject().getBuilds().overThresholdOnly(Result.SUCCESS).completedOnly(); default: return getProject().getBuilds(); } } - @Extension @Symbol({"run","runParam"}) + @Extension @Symbol({"run", "runParam"}) public static class DescriptorImpl extends ParameterDescriptor { @Override public String getDisplayName() { @@ -155,7 +157,7 @@ public String getHelpFile() { public ParameterDefinition newInstance(StaplerRequest req, JSONObject formData) throws FormException { return req.bindJSON(RunParameterDefinition.class, formData); } - + public AutoCompletionCandidates doAutoCompleteProjectName(@QueryParameter String value) { return AutoCompletionCandidates.ofJobNames(Job.class, value, null, Jenkins.get()); } @@ -168,7 +170,7 @@ public ParameterValue getDefaultParameterValue() { return createValue(runId); } - Run lastBuild; + Run lastBuild; Job project = getProject(); if (project == null) { @@ -183,7 +185,7 @@ public ParameterValue getDefaultParameterValue() { case SUCCESSFUL: lastBuild = project.getLastSuccessfulBuild(); break; - case STABLE : + case STABLE: lastBuild = project.getLastStableBuild(); break; default: @@ -192,9 +194,9 @@ public ParameterValue getDefaultParameterValue() { } if (lastBuild != null) { - return createValue(lastBuild.getExternalizableId()); + return createValue(lastBuild.getExternalizableId()); } else { - return null; + return null; } } @@ -219,6 +221,7 @@ public int hashCode() { } @Override + @SuppressFBWarnings(value = "EQ_GETCLASS_AND_CLASS_CONSTANT", justification = "ParameterDefinitionTest tests that subclasses are not equal to their parent classes, so the behavior appears to be intentional") public boolean equals(Object obj) { if (RunParameterDefinition.class != getClass()) return super.equals(obj); diff --git a/core/src/main/java/hudson/model/RunParameterValue.java b/core/src/main/java/hudson/model/RunParameterValue.java index 1edc798366eef..23e94f66746c3 100644 --- a/core/src/main/java/hudson/model/RunParameterValue.java +++ b/core/src/main/java/hudson/model/RunParameterValue.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Tom Huybrechts, Geoff Cummings - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -63,7 +64,7 @@ private static String check(String runId) { public String getRunId() { return runId; } - + private String[] split() { if (runId == null) { return null; @@ -78,13 +79,13 @@ private String[] split() { @Exported public String getJobName() { String[] r = split(); - return r == null ? null : r[0]; + return r == null ? null : r[0]; } - + @Exported public String getNumber() { String[] r = split(); - return r == null ? null : r[1]; + return r == null ? null : r[1]; } @Override @@ -96,31 +97,31 @@ public Run getValue() { * Exposes the name/value as an environment variable. */ @Override - public void buildEnvironment(Run build, EnvVars env) { + public void buildEnvironment(Run build, EnvVars env) { Run run = getRun(); - + String value = null == run ? "UNKNOWN" : Jenkins.get().getRootUrl() + run.getUrl(); env.put(name, value); env.put(name + ".jobName", getJobName()); // undocumented, left for backward compatibility env.put(name + "_JOBNAME", getJobName()); // prefer this version - env.put(name + ".number" , getNumber ()); // same as above - env.put(name + "_NUMBER" , getNumber ()); - + env.put(name + ".number", getNumber()); // same as above + env.put(name + "_NUMBER", getNumber()); + // if run is null, default to the standard '#1' display name format env.put(name + "_NAME", null == run ? "#" + getNumber() : run.getDisplayName()); // since 1.504 String buildResult = null == run || null == run.getResult() ? "UNKNOWN" : run.getResult().toString(); env.put(name + "_RESULT", buildResult); // since 1.517 - env.put(name.toUpperCase(Locale.ENGLISH),value); // backward compatibility pre 1.345 + env.put(name.toUpperCase(Locale.ENGLISH), value); // backward compatibility pre 1.345 } - + @Override public String toString() { - return "(RunParameterValue) " + getName() + "='" + getRunId() + "'"; + return "(RunParameterValue) " + getName() + "='" + getRunId() + "'"; } @Override public String getShortDescription() { diff --git a/core/src/main/java/hudson/model/RunnerStack.java b/core/src/main/java/hudson/model/RunnerStack.java index ddca4e94016e8..6f4c57b242bfd 100644 --- a/core/src/main/java/hudson/model/RunnerStack.java +++ b/core/src/main/java/hudson/model/RunnerStack.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -37,7 +38,7 @@ * @since 1.319 */ final class RunnerStack { - private final Map> stack = new WeakHashMap<>(); + private final Map> stack = new WeakHashMap<>(); synchronized void push(RunExecution r) { Executor e = Executor.currentExecutor(); @@ -49,7 +50,7 @@ synchronized void pop() { Executor e = Executor.currentExecutor(); Stack s = stack.get(e); s.pop(); - if(s.isEmpty()) stack.remove(e); + if (s.isEmpty()) stack.remove(e); } /** diff --git a/core/src/main/java/hudson/model/SCMedItem.java b/core/src/main/java/hudson/model/SCMedItem.java index 142e4f51535d2..2cfd0dde7079a 100644 --- a/core/src/main/java/hudson/model/SCMedItem.java +++ b/core/src/main/java/hudson/model/SCMedItem.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.scm.PollingResult; @@ -48,7 +49,7 @@ public interface SCMedItem extends BuildableItem { * This method must be always implemented as {@code (AbstractProject)this}, but * defining this method emphasizes the fact that this cast must be doable. */ - AbstractProject asProject(); + AbstractProject asProject(); /** * Checks if there's any update in SCM, and returns true if any is found. @@ -57,7 +58,7 @@ public interface SCMedItem extends BuildableItem { * Use {@link #poll(TaskListener)} instead. */ @Deprecated - boolean pollSCMChanges( TaskListener listener ); + boolean pollSCMChanges(TaskListener listener); /** * Checks if there's any update in SCM, and returns true if any is found. diff --git a/core/src/main/java/hudson/model/Saveable.java b/core/src/main/java/hudson/model/Saveable.java index a2e8b8f9a4344..c98900d99d644 100644 --- a/core/src/main/java/hudson/model/Saveable.java +++ b/core/src/main/java/hudson/model/Saveable.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.BulkChange; diff --git a/core/src/main/java/hudson/model/Slave.java b/core/src/main/java/hudson/model/Slave.java index 90b36b2c2b640..0517e73d7dccf 100644 --- a/core/src/main/java/hudson/model/Slave.java +++ b/core/src/main/java/hudson/model/Slave.java @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -93,7 +94,7 @@ * *

      * TODO: move out more stuff to {@link DumbSlave}. - * + * * On February, 2016 a general renaming was done internally: the "slave" term was replaced by * "Agent". This change was applied in: UI labels/HTML pages, javadocs and log messages. * Java classes, fields, methods, etc were not renamed to avoid compatibility issues. @@ -102,9 +103,9 @@ * @author Kohsuke Kawaguchi */ public abstract class Slave extends Node implements Serializable { - + private static final Logger LOGGER = Logger.getLogger(Slave.class.getName()); - + /** * Name of this agent node. */ @@ -148,9 +149,9 @@ public abstract class Slave extends Node implements Serializable { /** * Whitespace-separated labels. */ - private String label=""; + private String label = ""; - private /*almost final*/ DescribableList,NodePropertyDescriptor> nodeProperties = + private /*almost final*/ DescribableList, NodePropertyDescriptor> nodeProperties = new DescribableList<>(this); /** @@ -166,7 +167,7 @@ public abstract class Slave extends Node implements Serializable { @Deprecated protected Slave(String name, String nodeDescription, String remoteFS, String numExecutors, Mode mode, String labelString, ComputerLauncher launcher, RetentionStrategy retentionStrategy, List> nodeProperties) throws FormException, IOException { - this(name,nodeDescription,remoteFS,Util.tryParseNumber(numExecutors, 1).intValue(),mode,labelString,launcher,retentionStrategy, nodeProperties); + this(name, nodeDescription, remoteFS, Util.tryParseNumber(numExecutors, 1).intValue(), mode, labelString, launcher, retentionStrategy, nodeProperties); } /** @@ -175,7 +176,7 @@ protected Slave(String name, String nodeDescription, String remoteFS, String num @Deprecated protected Slave(String name, String nodeDescription, String remoteFS, int numExecutors, Mode mode, String labelString, ComputerLauncher launcher, RetentionStrategy retentionStrategy) throws FormException, IOException { - this(name, nodeDescription, remoteFS, numExecutors, mode, labelString, launcher, retentionStrategy, new ArrayList()); + this(name, nodeDescription, remoteFS, numExecutors, mode, labelString, launcher, retentionStrategy, new ArrayList()); } protected Slave(@NonNull String name, String remoteFS, ComputerLauncher launcher) throws FormException, IOException { @@ -206,7 +207,7 @@ protected Slave(@NonNull String name, String nodeDescription, String remoteFS, i if (name.equals("")) throw new FormException(Messages.Slave_InvalidConfig_NoName(), null); - if (this.numExecutors<=0) + if (this.numExecutors <= 0) throw new FormException(Messages.Slave_InvalidConfig_Executors(name), null); } @@ -236,7 +237,7 @@ public void setUserId(String userId){ } public ComputerLauncher getLauncher() { - if (launcher == null && !StringUtils.isEmpty(agentCommand)) { + if (launcher == null && agentCommand != null && !agentCommand.isEmpty()) { try { launcher = (ComputerLauncher) Jenkins.get().getPluginManager().uberClassLoader.loadClass("hudson.slaves.CommandLauncher").getConstructor(String.class, EnvVars.class).newInstance(agentCommand, null); agentCommand = null; @@ -305,7 +306,7 @@ public void setMode(Mode mode) { @Override public DescribableList, NodePropertyDescriptor> getNodeProperties() { assert nodeProperties != null; - return nodeProperties; + return nodeProperties; } @DataBoundSetter @@ -336,7 +337,7 @@ public void setLabelString(String labelString) throws IOException { } @Override - public Callable getClockDifferenceCallable() { + public Callable getClockDifferenceCallable() { return new GetClockDifference1(); } @@ -355,7 +356,7 @@ public FilePath getWorkspaceFor(TopLevelItem item) { } FilePath r = getWorkspaceRoot(); - if(r==null) return null; // offline + if (r == null) return null; // offline return r.child(item.getFullName()); } @@ -378,7 +379,7 @@ public FilePath getRootPath() { */ public @CheckForNull FilePath getWorkspaceRoot() { FilePath r = getRootPath(); - if(r==null) return null; + if (r == null) return null; return r.child(WORKSPACE_ROOT); } @@ -392,7 +393,7 @@ public JnlpJar(String fileName) { this.fileName = fileName; } - public void doIndex( StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { + public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { URLConnection con = connect(); // since we end up redirecting users to jnlpJars/foo.jar/, set the content disposition // so that browsers can download them in the right file name. @@ -405,7 +406,7 @@ public void doIndex( StaplerRequest req, StaplerResponse rsp) throws IOException @Override public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException { - doIndex(req,rsp); + doIndex(req, rsp); } private URLConnection connect() throws IOException { @@ -415,7 +416,7 @@ private URLConnection connect() throws IOException { public URL getURL() throws IOException { String name = fileName; - + // Prevent the access to war contents & prevent the folder escaping (SECURITY-195) if (!ALLOWED_JNLPJARS_FILES.contains(name)) { throw new MalformedURLException("The specified file path " + fileName + " is not allowed due to security reasons"); @@ -438,9 +439,9 @@ public URL getURL() throws IOException { } } } - + URL res = Jenkins.get().servletContext.getResource("/WEB-INF/" + name); - if(res==null) { + if (res == null) { throw new FileNotFoundException(name); // giving up } else { LOGGER.log(Level.FINE, "found {0}", res); @@ -492,9 +493,9 @@ public Launcher createLauncher(TaskListener listener) { listener.error("Issue with creating launcher for agent " + name + ". Computer has been disconnected"); return new Launcher.DummyLauncher(listener); } else { - // TODO: ideally all the logic below should be inside the SlaveComputer class with proper locking to prevent race conditions, + // TODO: ideally all the logic below should be inside the SlaveComputer class with proper locking to prevent race conditions, // but so far there is no locks for setNode() hence it requires serious refactoring - + // Ensure that the Computer instance still points to this node // Otherwise we may end up running the command on a wrong (reconnected) Node instance. Slave node = c.getNode(); @@ -505,10 +506,10 @@ public Launcher createLauncher(TaskListener listener) { } return new Launcher.DummyLauncher(listener); } - + // RemoteLauncher requires an active Channel instance to operate correctly final Channel channel = c.getChannel(); - if (channel == null) { + if (channel == null) { reportLauncherCreateError("The agent has not been fully initialized yet", "No remoting channel to the agent OR it has not been fully initialized yet", listener); return new Launcher.DummyLauncher(listener); @@ -523,22 +524,22 @@ public Launcher createLauncher(TaskListener listener) { // isUnix is always set when the channel is not null, so it should never happen reportLauncherCreateError("The agent has not been fully initialized yet", "Cannot determine if the agent is a Unix one, the System status request has not completed yet. " + - "It is an invalid channel state, please report a bug to Jenkins if you see it.", + "It is an invalid channel state, please report a bug to Jenkins if you see it.", listener); return new Launcher.DummyLauncher(listener); } - + return new RemoteLauncher(listener, channel, isUnix).decorateFor(this); } } - + private void reportLauncherCreateError(@NonNull String humanReadableMsg, @CheckForNull String exceptionDetails, @NonNull TaskListener listener) { String message = "Issue with creating launcher for agent " + name + ". " + humanReadableMsg; listener.error(message); if (LOGGER.isLoggable(Level.WARNING)) { // Send stacktrace to the log as well in order to diagnose the root cause of issues like JENKINS-38527 LOGGER.log(Level.WARNING, message - + "Probably there is a race condition with Agent reconnection or disconnection, check other log entries", + + "Probably there is a race condition with Agent reconnection or disconnection, check other log entries", new IllegalStateException(exceptionDetails != null ? exceptionDetails : humanReadableMsg)); } } @@ -552,7 +553,7 @@ private void reportLauncherCreateError(@NonNull String humanReadableMsg, @CheckF */ @CheckForNull public SlaveComputer getComputer() { - return (SlaveComputer)toComputer(); + return (SlaveComputer) toComputer(); } @Override @@ -574,7 +575,7 @@ public int hashCode() { * Invoked by XStream when this object is read into memory. */ protected Object readResolve() { - if(nodeProperties==null) + if (nodeProperties == null) nodeProperties = new DescribableList<>(this); return this; } @@ -584,7 +585,7 @@ public SlaveDescriptor getDescriptor() { Descriptor d = Jenkins.get().getDescriptorOrDie(getClass()); if (d instanceof SlaveDescriptor) return (SlaveDescriptor) d; - throw new IllegalStateException(d.getClass()+" needs to extend from SlaveDescriptor"); + throw new IllegalStateException(d.getClass() + " needs to extend from SlaveDescriptor"); } public abstract static class SlaveDescriptor extends NodeDescriptor { @@ -596,10 +597,10 @@ public FormValidation doCheckNumExecutors(@QueryParameter String value) { * Performs syntactical check on the remote FS for agents. */ public FormValidation doCheckRemoteFS(@QueryParameter String value) throws IOException, ServletException { - if(Util.fixEmptyAndTrim(value)==null) + if (Util.fixEmptyAndTrim(value) == null) return FormValidation.error(Messages.Slave_Remote_Director_Mandatory()); - if(value.startsWith("\\\\") || value.startsWith("/net/")) + if (value.startsWith("\\\\") || value.startsWith("/net/")) return FormValidation.warning(Messages.Slave_Network_Mounted_File_System_Warning()); if (Util.isRelativePath(value)) { @@ -691,7 +692,7 @@ public final List nodePropertyDescriptors(@CheckForNull *

    • When it's read on this side as a return value, it morphs itself into {@link ClockDifference}. * */ - private static final class GetClockDifference1 extends MasterToSlaveCallable { + private static final class GetClockDifference1 extends MasterToSlaveCallable { @Override public ClockDifference call() { // this method must be being invoked locally, which means the clock is in sync @@ -705,7 +706,7 @@ private Object writeReplace() { private static final long serialVersionUID = 1L; } - private static final class GetClockDifference2 extends MasterToSlaveCallable { + private static final class GetClockDifference2 extends MasterToSlaveCallable { /** * Capture the time on the controller when this object is sent to remote, which is when * {@link GetClockDifference1#writeReplace()} is run. @@ -730,14 +731,14 @@ private static final class GetClockDifference3 implements Serializable { private Object readResolve() { long endTime = System.currentTimeMillis(); - return new ClockDifference((startTime + endTime)/2-remoteTime); + return new ClockDifference((startTime + endTime) / 2 - remoteTime); } } /** * Determines the workspace root file name for those who really really need the shortest possible path name. */ - private static final String WORKSPACE_ROOT = SystemProperties.getString(Slave.class.getName()+".workspaceRoot","workspace"); + private static final String WORKSPACE_ROOT = SystemProperties.getString(Slave.class.getName() + ".workspaceRoot", "workspace"); /** * Provides a collection of file names, which are accessible via /jnlpJars link. diff --git a/core/src/main/java/hudson/model/StatusIcon.java b/core/src/main/java/hudson/model/StatusIcon.java index 458955c2bec80..b4c4bc7496284 100644 --- a/core/src/main/java/hudson/model/StatusIcon.java +++ b/core/src/main/java/hudson/model/StatusIcon.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; /** diff --git a/core/src/main/java/hudson/model/StreamBuildListener.java b/core/src/main/java/hudson/model/StreamBuildListener.java index 2ad5192653e8a..efa1204fe11f4 100644 --- a/core/src/main/java/hudson/model/StreamBuildListener.java +++ b/core/src/main/java/hudson/model/StreamBuildListener.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.util.StreamTaskListener; @@ -34,7 +35,7 @@ * {@link BuildListener} that writes to an {@link OutputStream}. * * This class is remotable. - * + * * @author Kohsuke Kawaguchi */ public class StreamBuildListener extends StreamTaskListener implements BuildListener { @@ -46,6 +47,12 @@ public StreamBuildListener(File out, Charset charset) throws IOException { super(out, charset); } + /** + * @deprecated as of TODO + * The caller should use {@link #StreamBuildListener(OutputStream, Charset)} to pass in + * the charset and output stream separately, so that this class can handle encoding correctly. + */ + @Deprecated public StreamBuildListener(OutputStream w) { super(w); } @@ -61,7 +68,7 @@ public StreamBuildListener(PrintStream w) { } public StreamBuildListener(PrintStream w, Charset charset) { - super(w,charset); + super(w, charset); } private static final long serialVersionUID = 1L; diff --git a/core/src/main/java/hudson/model/StringParameterDefinition.java b/core/src/main/java/hudson/model/StringParameterDefinition.java index 23a7c2794bafb..8a5dfa9f1b048 100644 --- a/core/src/main/java/hudson/model/StringParameterDefinition.java +++ b/core/src/main/java/hudson/model/StringParameterDefinition.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Luca Domenico Milanesio, Seiji Sogabe, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,10 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import hudson.Util; import java.util.Objects; @@ -64,7 +66,7 @@ public StringParameterDefinition(@NonNull String name, @CheckForNull String defa setDefaultValue(defaultValue); setDescription(description); } - + public StringParameterDefinition(@NonNull String name, @CheckForNull String defaultValue) { this(name); setDefaultValue(defaultValue); @@ -86,7 +88,7 @@ public String getDefaultValue() { } /** - * + * * @return original or trimmed defaultValue (depending on trim) */ @Restricted(DoNotUse.class) // Jelly @@ -103,7 +105,7 @@ public void setDefaultValue(@CheckForNull String defaultValue) { } /** - * + * * @return trim - {@code true}, if trim options has been selected, else return {@code false}. * Trimming will happen when creating {@link StringParameterValue}s, * the value in the config will not be changed. @@ -120,7 +122,7 @@ public boolean isTrim() { public void setTrim(boolean trim) { this.trim = trim; } - + @Override public StringParameterValue getDefaultParameterValue() { StringParameterValue value = new StringParameterValue(getName(), defaultValue, getDescription()); @@ -130,7 +132,7 @@ public StringParameterValue getDefaultParameterValue() { return value; } - @Extension @Symbol({"string","stringParam"}) + @Extension @Symbol({"string", "stringParam"}) public static class DescriptorImpl extends ParameterDescriptor { @Override @NonNull @@ -147,7 +149,7 @@ public String getHelpFile() { @Override public ParameterValue createValue(StaplerRequest req, JSONObject jo) { StringParameterValue value = req.bindJSON(StringParameterValue.class, jo); - if (isTrim() && value!=null) { + if (isTrim()) { value.doTrim(); } value.setDescription(getDescription()); @@ -172,6 +174,7 @@ public int hashCode() { } @Override + @SuppressFBWarnings(value = "EQ_GETCLASS_AND_CLASS_CONSTANT", justification = "ParameterDefinitionTest tests that subclasses are not equal to their parent classes, so the behavior appears to be intentional") public boolean equals(Object obj) { if (StringParameterDefinition.class != getClass()) return super.equals(obj); diff --git a/core/src/main/java/hudson/model/StringParameterValue.java b/core/src/main/java/hudson/model/StringParameterValue.java index ad7e528ac07fb..f5e0583ed5629 100644 --- a/core/src/main/java/hudson/model/StringParameterValue.java +++ b/core/src/main/java/hudson/model/StringParameterValue.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Luca Domenico Milanesio, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.EnvVars; @@ -37,7 +38,7 @@ * {@link ParameterValue} created from {@link StringParameterDefinition}. */ public class StringParameterValue extends ParameterValue { - @Exported(visibility=4) + @Exported(visibility = 4) @Restricted(NoExternalUse.class) public String value; @@ -55,9 +56,9 @@ public StringParameterValue(String name, String value, String description) { * Exposes the name/value as an environment variable. */ @Override - public void buildEnvironment(Run build, EnvVars env) { - env.put(name,value); - env.put(name.toUpperCase(Locale.ENGLISH),value); // backward compatibility pre 1.345 + public void buildEnvironment(Run build, EnvVars env) { + env.put(name, value); + env.put(name.toUpperCase(Locale.ENGLISH), value); // backward compatibility pre 1.345 } @Override @@ -69,43 +70,43 @@ public VariableResolver createVariableResolver(AbstractBuild build public String getValue() { return value; } - + /** * Trimming for value * @since 2.90 */ public void doTrim() { if (value != null) { - value = value.trim(); - } + value = value.trim(); + } } @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + (value == null ? 0 : value.hashCode()); - return result; - } + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + (value == null ? 0 : value.hashCode()); + return result; + } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - StringParameterValue other = (StringParameterValue) obj; - if (!Objects.equals(value, other.value)) { - return false; - } - return true; - } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + StringParameterValue other = (StringParameterValue) obj; + if (!Objects.equals(value, other.value)) { + return false; + } + return true; + } @Override public String toString() { - return "(StringParameterValue) " + getName() + "='" + value + "'"; + return "(StringParameterValue) " + getName() + "='" + value + "'"; } @Override public String getShortDescription() { diff --git a/core/src/main/java/hudson/model/TaskAction.java b/core/src/main/java/hudson/model/TaskAction.java index 575f35efab5c4..60ca66ac05368 100644 --- a/core/src/main/java/hudson/model/TaskAction.java +++ b/core/src/main/java/hudson/model/TaskAction.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Jorg Heymans - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.console.AnnotatedLargeText; @@ -96,7 +97,7 @@ public LargeText getLog() { */ public AnnotatedLargeText obtainLog() { WeakReference l = log; - if(l==null) return null; + if (l == null) return null; return l.get(); } @@ -112,10 +113,10 @@ public TaskThread getWorkerThread() { /** * Handles incremental log output. */ - public void doProgressiveLog( StaplerRequest req, StaplerResponse rsp) throws IOException { + public void doProgressiveLog(StaplerRequest req, StaplerResponse rsp) throws IOException { AnnotatedLargeText text = obtainLog(); - if(text!=null) { - text.doProgressText(req,rsp); + if (text != null) { + text.doProgressText(req, rsp); return; } rsp.setStatus(HttpServletResponse.SC_OK); @@ -124,10 +125,10 @@ public void doProgressiveLog( StaplerRequest req, StaplerResponse rsp) throws IO /** * Handles incremental log output. */ - public void doProgressiveHtml( StaplerRequest req, StaplerResponse rsp) throws IOException { + public void doProgressiveHtml(StaplerRequest req, StaplerResponse rsp) throws IOException { AnnotatedLargeText text = obtainLog(); - if(text!=null) { - text.doProgressiveHtml(req,rsp); + if (text != null) { + text.doProgressiveHtml(req, rsp); return; } rsp.setStatus(HttpServletResponse.SC_OK); @@ -140,7 +141,7 @@ public void doProgressiveHtml( StaplerRequest req, StaplerResponse rsp) throws I public synchronized void doClearError(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { getACL().checkPermission(getPermission()); - if(workerThread!=null && !workerThread.isRunning()) + if (workerThread != null && !workerThread.isRunning()) workerThread = null; rsp.sendRedirect("."); } diff --git a/core/src/main/java/hudson/model/TaskListener.java b/core/src/main/java/hudson/model/TaskListener.java index a466613d027f7..17269432f9553 100644 --- a/core/src/main/java/hudson/model/TaskListener.java +++ b/core/src/main/java/hudson/model/TaskListener.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.NonNull; @@ -129,7 +130,7 @@ default PrintWriter error(String msg) { */ @NonNull default PrintWriter error(String format, Object... args) { - return error(String.format(format,args)); + return error(String.format(format, args)); } /** diff --git a/core/src/main/java/hudson/model/TaskThread.java b/core/src/main/java/hudson/model/TaskThread.java index 60456f333fab1..2991da6211b06 100644 --- a/core/src/main/java/hudson/model/TaskThread.java +++ b/core/src/main/java/hudson/model/TaskThread.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Red Hat, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.Functions; @@ -40,7 +41,7 @@ *

      * Designed to be used inside {@link TaskAction}. * - * + * * * @author Kohsuke Kawaguchi * @since 1.191 @@ -75,7 +76,7 @@ public abstract class TaskThread extends Thread { */ protected TaskThread(TaskAction owner, ListenerAndText output) { //FIXME this failed to compile super(owner.getBuild().toString()+' '+owner.getDisplayName()); - //Please implement more general way how to get information about action owner, + //Please implement more general way how to get information about action owner, //if you want it in the thread's name. super(owner.getDisplayName()); this.owner = owner; @@ -127,14 +128,14 @@ public final void run() { try { perform(listener); listener.getLogger().println("Completed"); - owner.workerThread = null; + owner.workerThread = null; } catch (InterruptedException e) { listener.getLogger().println("Aborted"); } catch (Exception e) { Functions.printStackTrace(e, listener.getLogger()); } finally { listener = null; - isRunning =false; + isRunning = false; } log.markAsComplete(); } @@ -175,7 +176,7 @@ public static ListenerAndText forMemory() { */ @Deprecated public static ListenerAndText forFile(File f) throws IOException { - return forFile(f,null); + return forFile(f, null); } /** @@ -192,7 +193,7 @@ public static ListenerAndText forMemory(TaskAction context) { } /** - * Creates one that's backed by a file. + * Creates one that's backed by a file. */ public static ListenerAndText forFile(File f, TaskAction context) throws IOException { return new ListenerAndText( diff --git a/core/src/main/java/hudson/model/TextParameterDefinition.java b/core/src/main/java/hudson/model/TextParameterDefinition.java index d639b88b6d923..4db836a7b7e51 100644 --- a/core/src/main/java/hudson/model/TextParameterDefinition.java +++ b/core/src/main/java/hudson/model/TextParameterDefinition.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Luca Domenico Milanesio, Seiji Sogabe, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,10 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import java.util.Objects; import net.sf.json.JSONObject; @@ -51,7 +53,7 @@ public TextParameterDefinition(@NonNull String name, @CheckForNull String defaul setDescription(description); } - @Extension @Symbol({"text","textParam"}) + @Extension @Symbol({"text", "textParam"}) public static class DescriptorImpl extends ParameterDescriptor { @Override public String getDisplayName() { @@ -85,6 +87,7 @@ public int hashCode() { } @Override + @SuppressFBWarnings(value = "EQ_GETCLASS_AND_CLASS_CONSTANT", justification = "ParameterDefinitionTest tests that subclasses are not equal to their parent classes, so the behavior appears to be intentional") public boolean equals(Object obj) { if (TextParameterDefinition.class != getClass()) return super.equals(obj); diff --git a/core/src/main/java/hudson/model/TextParameterValue.java b/core/src/main/java/hudson/model/TextParameterValue.java index 1e2227e303c0c..2830e9128eadd 100644 --- a/core/src/main/java/hudson/model/TextParameterValue.java +++ b/core/src/main/java/hudson/model/TextParameterValue.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import org.kohsuke.stapler.DataBoundConstructor; diff --git a/core/src/main/java/hudson/model/TimeSeries.java b/core/src/main/java/hudson/model/TimeSeries.java index ddc1a644905b6..bcf524b428126 100644 --- a/core/src/main/java/hudson/model/TimeSeries.java +++ b/core/src/main/java/hudson/model/TimeSeries.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.CopyOnWrite; @@ -70,10 +71,10 @@ public TimeSeries(float initialValue, float decay, int historySize) { * the raw data stream. */ public void update(float newData) { - float data = history[0]*decay + newData*(1-decay); + float data = history[0] * decay + newData * (1 - decay); - float[] r = new float[Math.min(history.length+1,historySize)]; - System.arraycopy(history,0,r,1,Math.min(history.length,r.length-1)); + float[] r = new float[Math.min(history.length + 1, historySize)]; + System.arraycopy(history, 0, r, 1, Math.min(history.length, r.length - 1)); r[0] = data; history = r; } diff --git a/core/src/main/java/hudson/model/TimeZoneProperty.java b/core/src/main/java/hudson/model/TimeZoneProperty.java index 620f3129aafe3..bdf39c58527e8 100644 --- a/core/src/main/java/hudson/model/TimeZoneProperty.java +++ b/core/src/main/java/hudson/model/TimeZoneProperty.java @@ -46,6 +46,11 @@ public void setTimeZoneName(@CheckForNull String timeZoneName) { this.timeZoneName = timeZoneName; } + @CheckForNull + public String getTimeZoneName() { + return timeZoneName; + } + @Extension @Symbol("timezone") public static class DescriptorImpl extends UserPropertyDescriptor { diff --git a/core/src/main/java/hudson/model/TopLevelItem.java b/core/src/main/java/hudson/model/TopLevelItem.java index 7af3a732b3f0d..66f3bc7d4a2e8 100644 --- a/core/src/main/java/hudson/model/TopLevelItem.java +++ b/core/src/main/java/hudson/model/TopLevelItem.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.Extension; diff --git a/core/src/main/java/hudson/model/TopLevelItemDescriptor.java b/core/src/main/java/hudson/model/TopLevelItemDescriptor.java index 202e9b79014f3..00a2633df6309 100644 --- a/core/src/main/java/hudson/model/TopLevelItemDescriptor.java +++ b/core/src/main/java/hudson/model/TopLevelItemDescriptor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; diff --git a/core/src/main/java/hudson/model/TransientBuildActionFactory.java b/core/src/main/java/hudson/model/TransientBuildActionFactory.java index dfac20cb07808..c4084b83b4bd2 100644 --- a/core/src/main/java/hudson/model/TransientBuildActionFactory.java +++ b/core/src/main/java/hudson/model/TransientBuildActionFactory.java @@ -27,7 +27,7 @@ public abstract class TransientBuildActionFactory implements ExtensionPoint { */ public Collection createFor(Run target) { if (target instanceof AbstractBuild) - return createFor((AbstractBuild)target); + return createFor((AbstractBuild) target); else return Collections.emptyList(); } diff --git a/core/src/main/java/hudson/model/TransientComputerActionFactory.java b/core/src/main/java/hudson/model/TransientComputerActionFactory.java index d95ac4a680e11..5e7b16ee66df1 100644 --- a/core/src/main/java/hudson/model/TransientComputerActionFactory.java +++ b/core/src/main/java/hudson/model/TransientComputerActionFactory.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.ExtensionList; @@ -62,13 +63,13 @@ public static ExtensionList all() { /** * Creates {@link Action}s for a node, using all registered {@link TransientComputerActionFactory}s. */ - public static List createAllFor(Computer target) { - List result = new ArrayList<>(); - for (TransientComputerActionFactory f: all()) { - result.addAll(f.createFor(target)); - } - return result; - } + public static List createAllFor(Computer target) { + List result = new ArrayList<>(); + for (TransientComputerActionFactory f : all()) { + result.addAll(f.createFor(target)); + } + return result; + } } diff --git a/core/src/main/java/hudson/model/TransientProjectActionFactory.java b/core/src/main/java/hudson/model/TransientProjectActionFactory.java index 55f28f74b5e69..0d8979437646d 100644 --- a/core/src/main/java/hudson/model/TransientProjectActionFactory.java +++ b/core/src/main/java/hudson/model/TransientProjectActionFactory.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.Extension; diff --git a/core/src/main/java/hudson/model/TransientUserActionFactory.java b/core/src/main/java/hudson/model/TransientUserActionFactory.java index ecf3ff26402f5..273a6903efb29 100644 --- a/core/src/main/java/hudson/model/TransientUserActionFactory.java +++ b/core/src/main/java/hudson/model/TransientUserActionFactory.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.Extension; diff --git a/core/src/main/java/hudson/model/TransientViewActionFactory.java b/core/src/main/java/hudson/model/TransientViewActionFactory.java index 498c33c39d355..c1af0fe387d89 100644 --- a/core/src/main/java/hudson/model/TransientViewActionFactory.java +++ b/core/src/main/java/hudson/model/TransientViewActionFactory.java @@ -12,27 +12,27 @@ */ public abstract class TransientViewActionFactory implements ExtensionPoint { - /** - * returns a list of (transient) actions never null, may be empty - */ - public abstract List createFor(View v); - + /** + * returns a list of (transient) actions never null, may be empty + */ + public abstract List createFor(View v); + /** * Returns all the registered {@link TransientViewActionFactory}s. */ - public static ExtensionList all() { - return ExtensionList.lookup(TransientViewActionFactory.class); - } - + public static ExtensionList all() { + return ExtensionList.lookup(TransientViewActionFactory.class); + } + /** * Creates {@link Action}s for a view, using all registered {@link TransientViewActionFactory}s. */ - public static List createAllFor(View v) { - List result = new ArrayList<>(); - for (TransientViewActionFactory f: all()) { - result.addAll(f.createFor(v)); - } - return result; - } + public static List createAllFor(View v) { + List result = new ArrayList<>(); + for (TransientViewActionFactory f : all()) { + result.addAll(f.createFor(v)); + } + return result; + } } diff --git a/core/src/main/java/hudson/model/UnprotectedRootAction.java b/core/src/main/java/hudson/model/UnprotectedRootAction.java index bb5a7b6b5f175..b3ebdc2c3bc49 100644 --- a/core/src/main/java/hudson/model/UnprotectedRootAction.java +++ b/core/src/main/java/hudson/model/UnprotectedRootAction.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.ExtensionPoint; diff --git a/core/src/main/java/hudson/model/UpdateCenter.java b/core/src/main/java/hudson/model/UpdateCenter.java index fdcaa3ada6f45..2611f8033c212 100644 --- a/core/src/main/java/hudson/model/UpdateCenter.java +++ b/core/src/main/java/hudson/model/UpdateCenter.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static hudson.init.InitMilestone.PLUGINS_STARTED; @@ -68,6 +69,7 @@ import java.net.URL; import java.net.URLConnection; import java.net.UnknownHostException; +import java.nio.charset.StandardCharsets; import java.nio.file.AtomicMoveNotSupportedException; import java.nio.file.Files; import java.nio.file.InvalidPathException; @@ -141,13 +143,13 @@ *

      * Extending Update Centers. The update center in {@code Jenkins} can be replaced by defining a * System Property ({@code hudson.model.UpdateCenter.className}). See {@link #createUpdateCenter(hudson.model.UpdateCenter.UpdateCenterConfiguration)}. - * This className should be available on early startup, so it cannot come only from a library + * This className should be available on early startup, so it cannot come only from a library * (e.g. Jenkins module or Extra library dependency in the WAR file project). * Plugins cannot be used for such purpose. - * In order to be correctly instantiated, the class definition must have two constructors: + * In order to be correctly instantiated, the class definition must have two constructors: * {@link #UpdateCenter()} and {@link #UpdateCenter(hudson.model.UpdateCenter.UpdateCenterConfiguration)}. * If the class does not comply with the requirements, a fallback to the default UpdateCenter will be performed. - * + * * @author Kohsuke Kawaguchi * @since 1.220 */ @@ -160,7 +162,7 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas /** * Read timeout when downloading plugins, defaults to 1 minute */ - private static final int PLUGIN_DOWNLOAD_READ_TIMEOUT = (int)TimeUnit.SECONDS.toMillis(SystemProperties.getInteger(UpdateCenter.class.getName()+".pluginDownloadReadTimeoutSeconds", 60)); + private static final int PLUGIN_DOWNLOAD_READ_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(SystemProperties.getInteger(UpdateCenter.class.getName() + ".pluginDownloadReadTimeoutSeconds", 60)); public static final String PREDEFINED_UPDATE_SITE_ID = "default"; @@ -168,7 +170,7 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas * {@linkplain UpdateSite#getId() ID} of the default update site. * @since 1.483; configurable via system property since 2.4 */ - public static final String ID_DEFAULT = SystemProperties.getString(UpdateCenter.class.getName()+".defaultUpdateSiteId", PREDEFINED_UPDATE_SITE_ID); + public static final String ID_DEFAULT = SystemProperties.getString(UpdateCenter.class.getName() + ".defaultUpdateSiteId", PREDEFINED_UPDATE_SITE_ID); @Restricted(NoExternalUse.class) public static final String ID_UPLOAD = "_upload"; @@ -215,7 +217,7 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas static { Logger logger = Logger.getLogger(UpdateCenter.class.getName()); LOGGER = logger; - String ucOverride = SystemProperties.getString(UpdateCenter.class.getName()+".updateCenterUrl"); + String ucOverride = SystemProperties.getString(UpdateCenter.class.getName() + ".updateCenterUrl"); if (ucOverride != null) { logger.log(Level.INFO, "Using a custom update center defined by the system property: {0}", ucOverride); UPDATE_CENTER_URL = ucOverride; @@ -267,7 +269,7 @@ public UpdateCenter() { UpdateCenter(@NonNull UpdateCenterConfiguration configuration) { configure(configuration); } - + /** * Creates an update center. * @param config Requested configuration. May be {@code null} if defaults should be used @@ -276,13 +278,13 @@ public UpdateCenter() { */ @NonNull public static UpdateCenter createUpdateCenter(@CheckForNull UpdateCenterConfiguration config) { - String requiredClassName = SystemProperties.getString(UpdateCenter.class.getName()+".className", null); + String requiredClassName = SystemProperties.getString(UpdateCenter.class.getName() + ".className", null); if (requiredClassName == null) { // Use the default Update Center LOGGER.log(Level.FINE, "Using the default Update Center implementation"); return createDefaultUpdateCenter(config); } - + LOGGER.log(Level.FINE, "Using the custom update center: {0}", requiredClassName); try { final Class clazz = Class.forName(requiredClassName).asSubclass(UpdateCenter.class); @@ -297,17 +299,17 @@ public static UpdateCenter createUpdateCenter(@CheckForNull UpdateCenterConfigur LOGGER.log(Level.FINE, "Using the constructor {0} Update Center configuration for {1}", new Object[] {config != null ? "with" : "without", requiredClassName}); return config != null ? configConstructor.newInstance(config) : defaultConstructor.newInstance(); - } catch(ClassCastException e) { + } catch (ClassCastException e) { // Should never happen LOGGER.log(WARNING, "UpdateCenter class {0} does not extend hudson.model.UpdateCenter. Using default.", requiredClassName); - } catch(NoSuchMethodException e) { + } catch (NoSuchMethodException e) { LOGGER.log(WARNING, String.format("UpdateCenter class %s does not define one of the required constructors. Using default", requiredClassName), e); - } catch(Exception e) { + } catch (Exception e) { LOGGER.log(WARNING, String.format("Unable to instantiate custom plugin manager [%s]. Using default.", requiredClassName), e); } return createDefaultUpdateCenter(config); } - + @NonNull private static UpdateCenter createDefaultUpdateCenter(@CheckForNull UpdateCenterConfiguration config) { return config != null ? new UpdateCenter(config) : new UpdateCenter(); @@ -326,7 +328,7 @@ public Api getApi() { * @see UpdateCenterConfiguration */ public void configure(UpdateCenterConfiguration config) { - if (config!=null) { + if (config != null) { this.config = config; } } @@ -353,7 +355,7 @@ public List getJobs() { public UpdateCenterJob getJob(int id) { synchronized (jobs) { for (UpdateCenterJob job : jobs) { - if (job.id==id) + if (job.id == id) return job; } } @@ -369,7 +371,7 @@ public InstallationJob getJob(Plugin plugin) { Collections.reverse(jobList); for (UpdateCenterJob job : jobList) if (job instanceof InstallationJob) { - InstallationJob ij = (InstallationJob)job; + InstallationJob ij = (InstallationJob) job; if (ij.plugin.name.equals(plugin.name) && ij.plugin.sourceId.equals(plugin.sourceId)) return ij; } @@ -405,7 +407,7 @@ public HttpResponse doConnectionStatus(StaplerRequest request) { if (checkJob != null) { boolean isOffline = false; for (ConnectionStatus status : checkJob.connectionStates.values()) { - if(ConnectionStatus.FAILED.equals(status)) { + if (ConnectionStatus.FAILED.equals(status)) { isOffline = true; break; } @@ -415,12 +417,12 @@ public HttpResponse doConnectionStatus(StaplerRequest request) { checkJob.run(); isOffline = false; for (ConnectionStatus status : checkJob.connectionStates.values()) { - if(ConnectionStatus.FAILED.equals(status)) { + if (ConnectionStatus.FAILED.equals(status)) { isOffline = true; break; } } - if(!isOffline) { // also need to download the metadata + if (!isOffline) { // also need to download the metadata updateAllSites(); } } @@ -440,8 +442,8 @@ public HttpResponse doConnectionStatus(StaplerRequest request) { @Restricted(DoNotUse.class) // WebOnly public HttpResponse doIncompleteInstallStatus() { try { - Map jobs = InstallUtil.getPersistedInstallStatus(); - if(jobs == null) { + Map jobs = InstallUtil.getPersistedInstallStatus(); + if (jobs == null) { jobs = Collections.emptyMap(); } return HttpResponses.okJSON(jobs); @@ -463,13 +465,13 @@ public synchronized void persistInstallStatus() { for (UpdateCenterJob job : jobs) { if (job instanceof InstallationJob) { InstallationJob installationJob = (InstallationJob) job; - if(!installationJob.status.isSuccess()) { + if (!installationJob.status.isSuccess()) { activeInstalls = true; } } } - if(activeInstalls) { + if (activeInstalls) { InstallUtil.persistInstallStatus(jobs); // save this info } else { @@ -490,7 +492,7 @@ public synchronized void persistInstallStatus() { public HttpResponse doInstallStatus(StaplerRequest request) { try { String correlationId = request.getParameter("correlationId"); - Map response = new HashMap<>(); + Map response = new HashMap<>(); response.put("state", Jenkins.get().getInstallState().name()); List> installStates = new ArrayList<>(); response.put("jobs", installStates); @@ -529,7 +531,7 @@ public HudsonUpgradeJob getHudsonJob() { Collections.reverse(jobList); for (UpdateCenterJob job : jobList) if (job instanceof HudsonUpgradeJob) - return (HudsonUpgradeJob)job; + return (HudsonUpgradeJob) job; return null; } @@ -569,7 +571,7 @@ public boolean isSiteDataReady() { /** * The same as {@link #getSites()} but for REST API. */ - @Exported(name="sites") + @Exported(name = "sites") public List getSiteList() { return sites.toList(); } @@ -591,14 +593,14 @@ public UpdateSite getSite(String id) { public String getLastUpdatedString() { long newestTs = 0; for (UpdateSite s : sites) { - if (s.getDataTimestamp()>newestTs) { + if (s.getDataTimestamp() > newestTs) { newestTs = s.getDataTimestamp(); } } if (newestTs == 0) { return Messages.UpdateCenter_n_a(); } - return Util.getTimeSpanString(System.currentTimeMillis()-newestTs); + return Util.getTimeSpanString(System.currentTimeMillis() - newestTs); } /** @@ -627,7 +629,7 @@ public UpdateSite getById(String id) { public UpdateSite getCoreSource() { for (UpdateSite s : sites) { Data data = s.getData(); - if (data!=null && data.core!=null) + if (data != null && data.core != null) return s; } return null; @@ -652,7 +654,7 @@ public String getDefaultBaseUrl() { public @CheckForNull Plugin getPlugin(String artifactId) { for (UpdateSite s : sites) { Plugin p = s.getPlugin(artifactId); - if (p!=null) return p; + if (p != null) return p; } return null; } @@ -694,16 +696,16 @@ public String getDefaultBaseUrl() { private boolean checkMinVersion(@CheckForNull Plugin p, @CheckForNull VersionNumber minVersion) { return p != null && (minVersion == null || !minVersion.isNewerThan(new VersionNumber(p.version))); - } + } - /** + /** * Schedules a Jenkins upgrade. */ @RequirePOST public void doUpgrade(StaplerResponse rsp) throws IOException, ServletException { Jenkins.get().checkPermission(Jenkins.ADMINISTER); HudsonUpgradeJob job = new HudsonUpgradeJob(getCoreSource(), Jenkins.getAuthentication2()); - if(!Lifecycle.get().canRewriteHudsonWar()) { + if (!Lifecycle.get().canRewriteHudsonWar()) { sendError("Jenkins upgrade not supported in this running mode"); return; } @@ -808,7 +810,7 @@ public boolean isDowngradable() { @RequirePOST public void doDowngrade(StaplerResponse rsp) throws IOException, ServletException { Jenkins.get().checkPermission(Jenkins.ADMINISTER); - if(!isDowngradable()) { + if (!isDowngradable()) { sendError("Jenkins downgrade is not possible, probably backup does not exist"); return; } @@ -846,7 +848,8 @@ public String getBackupVersion() { } } catch (IOException e) { LOGGER.log(Level.WARNING, "Failed to read backup version ", e); - return null;} + return null; + } } @@ -923,12 +926,12 @@ public String getSearchUrl() { */ @Override public synchronized void save() { - if(BulkChange.contains(this)) return; + if (BulkChange.contains(this)) return; try { getConfigFile().write(sites); SaveableListener.fireOnChange(this, getConfigFile()); } catch (IOException e) { - LOGGER.log(Level.WARNING, "Failed to save "+getConfigFile(),e); + LOGGER.log(Level.WARNING, "Failed to save " + getConfigFile(), e); } } @@ -937,11 +940,11 @@ public synchronized void save() { */ public synchronized void load() throws IOException { XmlFile file = getConfigFile(); - if(file.exists()) { + if (file.exists()) { try { - sites.replaceBy(((PersistedList)file.unmarshal(sites)).toList()); + sites.replaceBy(((PersistedList) file.unmarshal(sites)).toList()); } catch (IOException e) { - LOGGER.log(Level.WARNING, "Failed to load "+file, e); + LOGGER.log(Level.WARNING, "Failed to load " + file, e); } boolean defaultSiteExists = false; for (UpdateSite site : sites) { @@ -970,15 +973,15 @@ protected UpdateSite createDefaultUpdateSite() { } private XmlFile getConfigFile() { - return new XmlFile(XSTREAM,new File(Jenkins.get().root, - UpdateCenter.class.getName()+".xml")); + return new XmlFile(XSTREAM, new File(Jenkins.get().root, + UpdateCenter.class.getName() + ".xml")); } @Exported public List getAvailables() { - Map pluginMap = new LinkedHashMap<>(); + Map pluginMap = new LinkedHashMap<>(); for (UpdateSite site : sites) { - for (Plugin plugin: site.getAvailables()) { + for (Plugin plugin : site.getAvailables()) { final Plugin existing = pluginMap.get(plugin.name); if (existing == null) { pluginMap.put(plugin.name, plugin); @@ -1005,7 +1008,7 @@ public List getAvailables() { public PluginEntry[] getCategorizedAvailables() { TreeSet entries = new TreeSet<>(); for (Plugin p : getAvailables()) { - if (p.categories==null || p.categories.length==0) + if (p.categories == null || p.categories.length == 0) entries.add(new PluginEntry(p, getCategoryDisplayName(null))); else for (String c : p.categories) @@ -1016,7 +1019,7 @@ public PluginEntry[] getCategorizedAvailables() { @Restricted(NoExternalUse.class) // Jelly only public static String getCategoryDisplayName(String category) { - if (category==null) + if (category == null) return Messages.UpdateCenter_PluginCategory_misc(); try { return (String) Messages.class.getMethod( @@ -1029,12 +1032,12 @@ public static String getCategoryDisplayName(String category) { } public List getUpdates() { - Map pluginMap = new LinkedHashMap<>(); + Map pluginMap = new LinkedHashMap<>(); final Map> incompatiblePluginMap = new LinkedHashMap<>(); final PluginManager.MetadataCache cache = new PluginManager.MetadataCache(); for (UpdateSite site : sites) { - for (Plugin plugin: site.getUpdates()) { + for (Plugin plugin : site.getUpdates()) { final Plugin existing = pluginMap.get(plugin.name); if (existing == null) { pluginMap.put(plugin.name, plugin); @@ -1065,7 +1068,7 @@ public List getUpdates() { @Restricted(NoExternalUse.class) public List getPluginsWithUnavailableUpdates() { - Map pluginMap = new LinkedHashMap<>(); + Map pluginMap = new LinkedHashMap<>(); for (PluginWrapper wrapper : Jenkins.get().getPluginManager().getPlugins()) { for (UpdateSite site : sites) { UpdateSite.Plugin plugin = site.getPlugin(wrapper.getShortName()); @@ -1093,7 +1096,7 @@ public List getPluginsWithUnavailableUpdates() { * @since 1.501 */ public List updateAllSites() throws InterruptedException, ExecutionException { - List > futures = new ArrayList<>(); + List> futures = new ArrayList<>(); for (UpdateSite site : getSites()) { Future future = site.updateDirectly(); if (future != null) { @@ -1126,12 +1129,12 @@ public boolean isActivated() { return false; } Data data = getData(); - return data!=null && data.hasCoreUpdates(); + return data != null && data.hasCoreUpdates(); } public Data getData() { UpdateSite cs = Jenkins.get().getUpdateCenter().getCoreSource(); - if (cs!=null) return cs.getData(); + if (cs != null) return cs.getData(); return null; } @@ -1240,6 +1243,7 @@ public void postValidate(DownloadJob job, File src) throws IOException { * @throws IOException if there were problems downloading the resource. * @see DownloadJob */ + @SuppressFBWarnings(value = "WEAK_MESSAGE_DIGEST_SHA1", justification = "SHA-1 is only used as a fallback if SHA-256/SHA-512 are not available") public File download(DownloadJob job, URL src) throws IOException { MessageDigest sha1 = null; MessageDigest sha256 = null; @@ -1255,7 +1259,7 @@ public File download(DownloadJob job, URL src) throws IOException { URLConnection con = null; try { - con = connect(job,src); + con = connect(job, src); //JENKINS-34174 - set timeout for downloads, may hang indefinitely // particularly noticeable during 2.0 install when downloading // many plugins @@ -1273,9 +1277,9 @@ public File download(DownloadJob job, URL src) throws IOException { int len; File dst = job.getDestination(); - File tmp = new File(dst.getPath()+".tmp"); + File tmp = new File(dst.getPath() + ".tmp"); - LOGGER.info("Downloading "+job.getName()); + LOGGER.info("Downloading " + job.getName()); Thread t = Thread.currentThread(); String oldName = t.getName(); t.setName(oldName + ": " + src); @@ -1287,7 +1291,7 @@ public File download(DownloadJob job, URL src) throws IOException { InputStream in = con.getInputStream(); CountingInputStream cin = new CountingInputStream(in)) { while ((len = cin.read(buf)) >= 0) { - out.write(buf,0,len); + out.write(buf, 0, len); final int count = cin.getCount(); job.status = job.new Installing(total == -1 ? -1 : ((int) (count * 100 / total))); if (total != -1 && total < count) { @@ -1295,16 +1299,16 @@ public File download(DownloadJob job, URL src) throws IOException { } } } catch (IOException | InvalidPathException e) { - throw new IOException("Failed to load "+src+" to "+tmp,e); + throw new IOException("Failed to load " + src + " to " + tmp, e); } finally { t.setName(oldName); } - if (total!=-1 && total!=tmp.length()) { + if (total != -1 && total != tmp.length()) { // don't know exactly how this happens, but report like // http://www.ashlux.com/wordpress/2009/08/14/hudson-and-the-sonar-plugin-fail-maveninstallation-nosuchmethoderror/ // indicates that this kind of inconsistency can happen. So let's be defensive - throw new IOException("Inconsistent file length: expected "+total+" but only got "+tmp.length()); + throw new IOException("Inconsistent file length: expected " + total + " but only got " + tmp.length()); } if (sha1 != null) { @@ -1329,7 +1333,7 @@ public File download(DownloadJob job, URL src) throws IOException { // Also, since it involved name resolution, it'd be an expensive operation. extraMessage = " (redirected to: " + con.getURL() + ")"; } - throw new IOException("Failed to download from "+src+extraMessage,e); + throw new IOException("Failed to download from " + src + extraMessage, e); } } @@ -1412,9 +1416,9 @@ private void testConnection(URL url) throws IOException { try { URLConnection connection = ProxyConfiguration.open(url); - if(connection instanceof HttpURLConnection) { - int responseCode = ((HttpURLConnection)connection).getResponseCode(); - if(HttpURLConnection.HTTP_OK != responseCode) { + if (connection instanceof HttpURLConnection) { + int responseCode = ((HttpURLConnection) connection).getResponseCode(); + if (HttpURLConnection.HTTP_OK != responseCode) { throw new HttpRetryException("Invalid response code (" + responseCode + ") from URL: " + url, responseCode); } } else { @@ -1425,7 +1429,7 @@ private void testConnection(URL url) throws IOException { } catch (SSLHandshakeException e) { if (e.getMessage().contains("PKIX path building failed")) // fix up this crappy error message from JDK - throw new IOException("Failed to validate the SSL certificate of "+url,e); + throw new IOException("Failed to validate the SSL certificate of " + url, e); } } } @@ -1500,11 +1504,11 @@ public String getType() { * {@link Future} to keeps track of the status of the execution. */ public Future submit() { - LOGGER.fine("Scheduling "+this+" to installerService"); + LOGGER.fine("Scheduling " + this + " to installerService"); // TODO: seems like this access to jobs should be synchronized, no? // It might get synch'd accidentally via the addJob method, but that wouldn't be good. jobs.add(this); - return installerService.submit(this,this); + return installerService.submit(this, this); } @Exported @@ -1524,7 +1528,7 @@ public class RestartJenkinsJob extends UpdateCenterJob { /** * Immutable state of this job. */ - @Exported(inline=true) + @Exported(inline = true) public volatile RestartJenkinsJobStatus status = new RestartJenkinsJob.Pending(); /** @@ -1597,7 +1601,7 @@ public class Canceled extends RestartJenkinsJobStatus { * Tests the internet connectivity. */ public final class ConnectionCheckJob extends UpdateCenterJob { - private final Vector statuses= new Vector<>(); + private final Vector statuses = new Vector<>(); final Map connectionStates = new ConcurrentHashMap<>(); @@ -1618,7 +1622,7 @@ public void run() { Future internetCheck = null; try { final String connectionCheckUrl = site.getConnectionCheckUrl(); - if (connectionCheckUrl!=null) { + if (connectionCheckUrl != null) { connectionStates.put(ConnectionStatus.INTERNET, ConnectionStatus.CHECKING); statuses.add(Messages.UpdateCenter_Status_CheckingInternet()); // Run the internet check in parallel @@ -1628,7 +1632,7 @@ public void run() { try { config.checkConnection(ConnectionCheckJob.this, connectionCheckUrl); } catch (Exception e) { - if(e.getMessage().contains("Connection timed out")) { + if (e.getMessage().contains("Connection timed out")) { // Google can't be down, so this is probably a proxy issue connectionStates.put(ConnectionStatus.INTERNET, ConnectionStatus.FAILED); statuses.add(Messages.UpdateCenter_Status_ConnectionFailed(Functions.xmlEscape(connectionCheckUrl))); @@ -1661,8 +1665,8 @@ public void run() { addStatus(e); error = e; } - - if(internetCheck != null) { + + if (internetCheck != null) { try { // Wait for internet check to complete internetCheck.get(); @@ -1673,7 +1677,7 @@ public void run() { } private void addStatus(Throwable e) { - statuses.add("

      "+ Functions.xmlEscape(Functions.printThrowable(e))+"
      "); + statuses.add("
      " + Functions.xmlEscape(Functions.printThrowable(e)) + "
      "); } public String[] getStatuses() { @@ -1684,7 +1688,7 @@ public String[] getStatuses() { } - + /** * Enables a required plugin, provides feedback in the update center */ @@ -1692,16 +1696,16 @@ public class EnableJob extends InstallationJob { public EnableJob(UpdateSite site, Authentication auth, @NonNull Plugin plugin, boolean dynamicLoad) { super(plugin, site, auth, dynamicLoad); } - + public Plugin getPlugin() { return plugin; } - + @Override public void run() { try { PluginWrapper installed = plugin.getInstalled(); - synchronized(installed) { + synchronized (installed) { if (!installed.isEnabled()) { try { installed.enable(); @@ -1710,7 +1714,7 @@ public void run() { error = e; status = new DownloadJob.Failure(e); } - + if (dynamicLoad) { try { // remove the existing, disabled inactive plugin to force a new one to load @@ -1726,18 +1730,18 @@ public void run() { } } } - } catch(Throwable e) { + } catch (Throwable e) { LOGGER.log(Level.SEVERE, "An unexpected error occurred while attempting to enable " + plugin.getDisplayName(), e); error = e; requiresRestart = true; status = new DownloadJob.Failure(e); } - if(status instanceof DownloadJob.Pending) { + if (status instanceof DownloadJob.Pending) { status = new DownloadJob.Success(); } } } - + /** * A no-op, e.g. this plugin is already installed */ @@ -1745,6 +1749,7 @@ public class NoOpJob extends EnableJob { public NoOpJob(UpdateSite site, Authentication auth, @NonNull Plugin plugin) { super(site, auth, plugin, false); } + @Override public void run() { // do nothing @@ -1755,10 +1760,12 @@ public void run() { @Restricted(NoExternalUse.class) /*package*/ interface WithComputedChecksums { String getComputedSHA1(); + String getComputedSHA256(); + String getComputedSHA512(); } - + /** * Base class for a job that downloads a file from the Jenkins project. */ @@ -1766,7 +1773,7 @@ public abstract class DownloadJob extends UpdateCenterJob implements WithCompute /** * Immutable object representing the current state of this job. */ - @Exported(inline=true) + @Exported(inline = true) public volatile InstallationStatus status = new DownloadJob.Pending(); /** @@ -1855,11 +1862,11 @@ protected DownloadJob(UpdateSite site, Authentication authentication) { @Override public void run() { try { - LOGGER.info("Starting the installation of "+getName()+" on behalf of "+getUser().getName()); + LOGGER.info("Starting the installation of " + getName() + " on behalf of " + getUser().getName()); _run(); - LOGGER.info("Installation successful: "+getName()); + LOGGER.info("Installation successful: " + getName()); status = new DownloadJob.Success(); onSuccess(); } catch (InstallationStatus e) { @@ -1871,7 +1878,7 @@ public void run() { status = new DownloadJob.Failure(e); error = e; } catch (Throwable e) { - LOGGER.log(Level.SEVERE, "Failed to install "+getName(),e); + LOGGER.log(Level.SEVERE, "Failed to install " + getName(), e); status = new DownloadJob.Failure(e); error = e; } @@ -1894,7 +1901,7 @@ protected void _run() throws IOException, InstallationStatus { * the old file with the new file. */ protected synchronized void replace(File dst, File src) throws IOException { - File bak = Util.changeExtension(dst,".bak"); + File bak = Util.changeExtension(dst, ".bak"); moveAtomically(dst, bak); moveAtomically(src, dst); } @@ -1904,7 +1911,7 @@ protected synchronized void replace(File dst, File src) throws IOException { * metadata. * * @return the expected size, or -1 if unknown. - * @since TODO + * @since 2.325 */ public long getContentLength() { return -1; @@ -1918,10 +1925,12 @@ public long getContentLength() { @ExportedBean public abstract class InstallationStatus extends Throwable { public final int id = iota.incrementAndGet(); + @Exported public boolean isSuccess() { return false; } + @Exported public final String getType() { return getClass().getSimpleName(); @@ -2024,11 +2033,11 @@ private static VerificationResult verifyChecksums(String expectedDigest, String } if (caseSensitive) { - if (MessageDigest.isEqual(expectedDigest.getBytes(), actualDigest.getBytes())) { + if (MessageDigest.isEqual(expectedDigest.getBytes(StandardCharsets.US_ASCII), actualDigest.getBytes(StandardCharsets.US_ASCII))) { return VerificationResult.PASS; } } else { - if (MessageDigest.isEqual(expectedDigest.toLowerCase().getBytes(), actualDigest.toLowerCase().getBytes())) { + if (MessageDigest.isEqual(expectedDigest.toLowerCase().getBytes(StandardCharsets.US_ASCII), actualDigest.toLowerCase().getBytes(StandardCharsets.US_ASCII))) { return VerificationResult.PASS; } } @@ -2135,7 +2144,7 @@ public class InstallationJob extends DownloadJob { */ @Deprecated public InstallationJob(Plugin plugin, UpdateSite site, Authentication auth) { - this(plugin,site,auth,false); + this(plugin, site, auth, false); } /** @@ -2197,7 +2206,7 @@ public void _run() throws IOException, InstallationStatus { // if this is a bundled plugin, make sure it won't get overwritten PluginWrapper pw = plugin.getInstalled(); - if (pw!=null && pw.isBundled()) { + if (pw != null && pw.isBundled()) { try (ACLContext ctx = ACL.as2(ACL.SYSTEM2)) { pw.doPin(); } @@ -2209,13 +2218,13 @@ public void _run() throws IOException, InstallationStatus { } catch (RestartRequiredException e) { throw new DownloadJob.SuccessButRequiresRestart(e.message); } catch (Exception e) { - throw new IOException("Failed to dynamically deploy this plugin",e); + throw new IOException("Failed to dynamically deploy this plugin", e); } } else { throw new DownloadJob.SuccessButRequiresRestart(Messages._UpdateCenter_DownloadButNotActivated()); } } finally { - synchronized(this) { + synchronized (this) { // There may be other threads waiting on completion LOGGER.fine("Install complete for: " + plugin.getDisplayName() + "@" + plugin.version); // some status other than Installing or Downloading needs to be set here @@ -2231,7 +2240,7 @@ public void _run() throws IOException, InstallationStatus { * @since 2.1 */ protected boolean wasInstalled() { - synchronized(UpdateCenter.this) { + synchronized (UpdateCenter.this) { for (UpdateCenterJob job : getJobs()) { if (job == this) { // oldest entries first, if we reach this instance, @@ -2239,11 +2248,11 @@ protected boolean wasInstalled() { return false; } if (job instanceof InstallationJob) { - InstallationJob ij = (InstallationJob)job; + InstallationJob ij = (InstallationJob) job; if (ij.plugin.equals(plugin) && ij.plugin.version.equals(plugin.version)) { // wait until other install is completed - synchronized(ij) { - if(ij.status instanceof DownloadJob.Installing || ij.status instanceof DownloadJob.Pending) { + synchronized (ij) { + if (ij.status instanceof DownloadJob.Installing || ij.status instanceof DownloadJob.Pending) { try { LOGGER.fine("Waiting for other plugin install of: " + plugin.getDisplayName() + "@" + plugin.version); ij.wait(); @@ -2270,7 +2279,7 @@ protected void onSuccess() { @Override public String toString() { - return super.toString()+"[plugin="+plugin.title+"]"; + return super.toString() + "[plugin=" + plugin.title + "]"; } /** @@ -2310,6 +2319,7 @@ public final class CompleteBatchJob extends UpdateCenterJob { private final List batch; private final long start; @Exported(inline = true) + @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", justification = "read by Stapler") public volatile CompleteBatchJobStatus status = new CompleteBatchJob.Pending(); public CompleteBatchJob(List batch, long start, UUID correlationId) { @@ -2349,6 +2359,7 @@ public class Failure extends CompleteBatchJobStatus { Failure(Throwable problemStackTrace) { this.problemStackTrace = problemStackTrace; } + public final Throwable problemStackTrace; } @@ -2388,7 +2399,7 @@ protected URL getURL() throws MalformedURLException { protected File getDestination() { File baseDir = pm.rootDir; final File legacy = new File(baseDir, plugin.name + ".hpi"); - if(legacy.exists()){ + if (legacy.exists()) { return legacy; } return new File(baseDir, plugin.name + ".jpi"); @@ -2412,15 +2423,15 @@ public String getDisplayName() { @Override public void run() { try { - LOGGER.info("Starting the downgrade of "+getName()+" on behalf of "+getUser().getName()); + LOGGER.info("Starting the downgrade of " + getName() + " on behalf of " + getUser().getName()); _run(); - LOGGER.info("Downgrade successful: "+getName()); + LOGGER.info("Downgrade successful: " + getName()); status = new Success(); onSuccess(); } catch (Throwable e) { - LOGGER.log(Level.SEVERE, "Failed to downgrade "+getName(),e); + LOGGER.log(Level.SEVERE, "Failed to downgrade " + getName(), e); status = new DownloadJob.Failure(e); error = e; } @@ -2450,7 +2461,7 @@ protected void onSuccess() { @Override public String toString() { - return super.toString()+"[plugin="+plugin.title+"]"; + return super.toString() + "[plugin=" + plugin.title + "]"; } } @@ -2535,22 +2546,24 @@ protected File getDestination() { public String getName() { return "jenkins.war"; } + @Override protected void onSuccess() { status = new DownloadJob.Success(); } + @Override public void run() { try { - LOGGER.info("Starting the downgrade of "+getName()+" on behalf of "+getUser().getName()); + LOGGER.info("Starting the downgrade of " + getName() + " on behalf of " + getUser().getName()); _run(); - LOGGER.info("Downgrading successful: "+getName()); + LOGGER.info("Downgrading successful: " + getName()); status = new DownloadJob.Success(); onSuccess(); } catch (Throwable e) { - LOGGER.log(Level.SEVERE, "Failed to downgrade "+getName(),e); + LOGGER.log(Level.SEVERE, "Failed to downgrade " + getName(), e); status = new DownloadJob.Failure(e); error = e; } @@ -2575,6 +2588,7 @@ protected void replace(File dst, File src) throws IOException { public static final class PluginEntry implements Comparable { public Plugin plugin; public String category; + private PluginEntry(Plugin p, String c) { plugin = p; category = c; @@ -2583,8 +2597,8 @@ private PluginEntry(Plugin p, String c) { @Override public int compareTo(PluginEntry o) { int r = category.compareTo(o.category); - if (r==0) r = plugin.name.compareToIgnoreCase(o.plugin.name); - if (r==0) r = new VersionNumber(plugin.version).compareTo(new VersionNumber(o.plugin.version)); + if (r == 0) r = plugin.name.compareToIgnoreCase(o.plugin.name); + if (r == 0) r = new VersionNumber(plugin.version).compareTo(new VersionNumber(o.plugin.version)); return r; } @@ -2622,7 +2636,7 @@ public int hashCode() { * * This has to wait until after all plugins load, to let custom UpdateCenterConfiguration take effect first. */ - @Initializer(after=PLUGINS_STARTED, fatal=false) + @Initializer(after = PLUGINS_STARTED, fatal = false) public static void init(Jenkins h) throws IOException { h.getUpdateCenter().load(); } @@ -2684,13 +2698,13 @@ public Object getTarget() { * Use {@link UpdateSite#neverUpdate} */ @Deprecated - public static boolean neverUpdate = SystemProperties.getBoolean(UpdateCenter.class.getName()+".never"); + public static boolean neverUpdate = SystemProperties.getBoolean(UpdateCenter.class.getName() + ".never"); public static final XStream2 XSTREAM = new XStream2(); static { - XSTREAM.alias("site",UpdateSite.class); - XSTREAM.alias("sites",PersistedList.class); + XSTREAM.alias("site", UpdateSite.class); + XSTREAM.alias("sites", PersistedList.class); } private static void moveAtomically(File src, File target) throws IOException { diff --git a/core/src/main/java/hudson/model/UpdateSite.java b/core/src/main/java/hudson/model/UpdateSite.java index cf56d13bea443..72966f873b06d 100644 --- a/core/src/main/java/hudson/model/UpdateSite.java +++ b/core/src/main/java/hudson/model/UpdateSite.java @@ -1,19 +1,19 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Yahoo! Inc., Seiji Sogabe, * Andrew Bayer - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -28,9 +28,7 @@ import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.HOURS; import static java.util.concurrent.TimeUnit.SECONDS; -import static jenkins.util.MemoryReductionUtil.EMPTY_STRING_ARRAY; import static jenkins.util.MemoryReductionUtil.getPresizedMutableMap; -import static jenkins.util.MemoryReductionUtil.internInPlace; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; @@ -80,6 +78,7 @@ import jenkins.security.UpdateSiteWarningsConfiguration; import jenkins.security.UpdateSiteWarningsMonitor; import jenkins.util.JSONSignatureValidator; +import jenkins.util.PluginLabelUtil; import jenkins.util.SystemProperties; import jenkins.util.java.JavaUtils; import net.sf.json.JSONArray; @@ -219,7 +218,7 @@ public long getDataTimestamp() { public @NonNull FormValidation updateDirectlyNow(boolean signatureCheck) throws IOException { return updateData(DownloadService.loadJSON(new URL(getUrl() + "?id=" + URLEncoder.encode(getId(), "UTF-8") + "&version=" + URLEncoder.encode(Jenkins.VERSION, "UTF-8"))), signatureCheck); } - + private FormValidation updateData(String json, boolean signatureCheck) throws IOException { @@ -238,7 +237,7 @@ private FormValidation updateData(String json, boolean signatureCheck) if (signatureCheck) { FormValidation e = verifySignatureInternal(o); - if (e.kind!=FormValidation.Kind.OK) { + if (e.kind != FormValidation.Kind.OK) { LOGGER.severe(e.toString()); return e; } @@ -308,17 +307,17 @@ protected JSONSignatureValidator getJsonSignatureValidator(@CheckForNull String * Returns true if it's time for us to check for new version. */ public synchronized boolean isDue() { - if(neverUpdate) return false; - if(dataTimestamp == 0) + if (neverUpdate) return false; + if (dataTimestamp == 0) dataTimestamp = getDataFile().file.lastModified(); long now = System.currentTimeMillis(); - retryWindow = Math.max(retryWindow,SECONDS.toMillis(15)); - + retryWindow = Math.max(retryWindow, SECONDS.toMillis(15)); + boolean due = now - dataTimestamp > DAY && now - lastAttempt > retryWindow; - if(due) { + if (due) { lastAttempt = now; - retryWindow = Math.min(retryWindow*2, HOURS.toMillis(1)); // exponential back off but at most 1 hour + retryWindow = Math.min(retryWindow * 2, HOURS.toMillis(1)); // exponential back off but at most 1 hour } return due; } @@ -365,14 +364,14 @@ boolean hasUnparsedData() { */ public JSONObject getJSONObject() { TextFile df = getDataFile(); - if(df.exists()) { + if (df.exists()) { long start = System.nanoTime(); try { JSONObject o = JSONObject.fromObject(df.read()); LOGGER.fine(() -> String.format("Loaded and parsed %s in %.01fs", df, (System.nanoTime() - start) / 1_000_000_000.0)); return o; } catch (JSONException | IOException e) { - LOGGER.log(Level.SEVERE,"Failed to parse "+df,e); + LOGGER.log(Level.SEVERE, "Failed to parse " + df, e); try { df.delete(); // if we keep this file, it will cause repeated failures } catch (IOException e2) { @@ -393,9 +392,9 @@ public JSONObject getJSONObject() { public List getAvailables() { List r = new ArrayList<>(); Data data = getData(); - if(data==null) return Collections.emptyList(); + if (data == null) return Collections.emptyList(); for (Plugin p : data.plugins.values()) { - if(p.getInstalled()==null) + if (p.getInstalled() == null) r.add(p); } r.sort((plugin, t1) -> { @@ -420,7 +419,7 @@ public List getAvailables() { @CheckForNull public Plugin getPlugin(String artifactId) { Data dt = getData(); - if(dt==null) return null; + if (dt == null) return null; return dt.plugins.get(artifactId); } @@ -436,7 +435,7 @@ public Api getApi() { @CheckForNull public String getConnectionCheckUrl() { Data dt = getData(); - if(dt==null) return "http://www.google.com/"; + if (dt == null) return "http://www.google.com/"; return dt.connectionCheckUrl; } @@ -445,9 +444,9 @@ public String getConnectionCheckUrl() { */ private TextFile getDataFile() { return new TextFile(new File(Jenkins.get().getRootDir(), - "updates/" + getId()+".json")); + "updates/" + getId() + ".json")); } - + /** * Returns the list of plugins that are updates to currently installed ones. * @@ -457,35 +456,35 @@ private TextFile getDataFile() { @Exported public List getUpdates() { Data data = getData(); - if(data==null) return Collections.emptyList(); // fail to determine - + if (data == null) return Collections.emptyList(); // fail to determine + List r = new ArrayList<>(); for (PluginWrapper pw : Jenkins.get().getPluginManager().getPlugins()) { Plugin p = pw.getUpdateInfo(); - if(p!=null) r.add(p); + if (p != null) r.add(p); } - + return r; } - + /** * Does any of the plugin has updates? */ @Exported public boolean hasUpdates() { Data data = getData(); - if(data==null) return false; - + if (data == null) return false; + for (PluginWrapper pw : Jenkins.get().getPluginManager().getPlugins()) { - if(!pw.isBundled() && pw.getUpdateInfo()!=null) + if (!pw.isBundled() && pw.getUpdateInfo() != null) // do not advertize updates to bundled plugins, since we generally want users to get them - // as a part of jenkins.war updates. This also avoids unnecessary pinning of plugins. + // as a part of jenkins.war updates. This also avoids unnecessary pinning of plugins. return true; } return false; } - - + + /** * Exposed to get rid of hardcoding of the URL that serves up update-center.json * in JavaScript. @@ -559,7 +558,7 @@ public final class Data { /** * Plugins in the repository, keyed by their artifact IDs. */ - public final Map plugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + public final Map plugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); /** * List of warnings (mostly security) published with the update site. * @@ -581,9 +580,9 @@ public final class Data { public final String connectionCheckUrl; Data(JSONObject o) { - this.sourceId = Util.intern((String)o.get("id")); + this.sourceId = Util.intern((String) o.get("id")); JSONObject c = o.optJSONObject("core"); - if (c!=null) { + if (c != null) { core = new Entry(sourceId, c, url); } else { core = null; @@ -618,13 +617,13 @@ public final class Data { } } - for(Map.Entry e : (Set>)o.getJSONObject("plugins").entrySet()) { + for (Map.Entry e : (Set>) o.getJSONObject("plugins").entrySet()) { Plugin p = new Plugin(sourceId, e.getValue()); // JENKINS-33308 - include implied dependencies for older plugins that may need them List implicitDeps = DetachedPluginsUtil.getImpliedDependencies(p.name, p.requiredCore); - if(!implicitDeps.isEmpty()) { - for(PluginWrapper.Dependency dep : implicitDeps) { - if(!p.dependencies.containsKey(dep.shortName)) { + if (!implicitDeps.isEmpty()) { + for (PluginWrapper.Dependency dep : implicitDeps) { + if (!p.dependencies.containsKey(dep.shortName)) { p.dependencies.put(dep.shortName, dep.version); } } @@ -640,7 +639,7 @@ public final class Data { } } - connectionCheckUrl = (String)o.get("connectionCheckUrl"); + connectionCheckUrl = (String) o.get("connectionCheckUrl"); } /** @@ -802,7 +801,7 @@ public Api getApi() { * Size of the file being advertised in bytes, or {@code null} if unspecified/unknown. * @return size of the file if known, {@code null} otherwise. * - * @since TODO + * @since 2.325 */ // @Exported -- TODO unsure @Restricted(NoExternalUse.class) @@ -879,6 +878,7 @@ public static final class Deprecation { * Jenkins will show a link to this URL when displaying the deprecation message. */ public final String url; + public Deprecation(String url) { this.url = url; } @@ -1069,7 +1069,7 @@ public boolean isRelevantToVersion(@NonNull VersionNumber version) { } private static String get(JSONObject o, String prop) { - if(o.has(prop)) + if (o.has(prop)) return o.getString(prop); else return null; @@ -1163,13 +1163,13 @@ public final class Plugin extends Entry { * Dependencies of this plugin, a name -> version mapping. */ @Exported - public final Map dependencies; - + public final Map dependencies; + /** * Optional dependencies of this plugin. */ @Exported - public final Map optionalDependencies; + public final Map optionalDependencies; /** * Set of plugins, this plugin is a incompatible dependency to. @@ -1210,13 +1210,13 @@ public final class Plugin extends Entry { @DataBoundConstructor public Plugin(String sourceId, JSONObject o) { super(sourceId, o, UpdateSite.this.url); - this.wiki = get(o,"wiki"); - this.title = get(o,"title"); - this.excerpt = get(o,"excerpt"); - this.compatibleSinceVersion = Util.intern(get(o,"compatibleSinceVersion")); + this.wiki = get(o, "wiki"); + this.title = get(o, "title"); + this.excerpt = get(o, "excerpt"); + this.compatibleSinceVersion = Util.intern(get(o, "compatibleSinceVersion")); this.minimumJavaVersion = Util.intern(get(o, "minimumJavaVersion")); this.latest = get(o, "latest"); - this.requiredCore = Util.intern(get(o,"requiredCore")); + this.requiredCore = Util.intern(get(o, "requiredCore")); final String releaseTimestamp = get(o, "releaseTimestamp"); Date date = null; if (releaseTimestamp != null) { @@ -1237,20 +1237,20 @@ public Plugin(String sourceId, JSONObject o) { } this.popularity = popularity; this.releaseTimestamp = date; - this.categories = o.has("labels") ? internInPlace((String[])o.getJSONArray("labels").toArray(EMPTY_STRING_ARRAY)) : null; + this.categories = o.has("labels") ? PluginLabelUtil.canonicalLabels(o.getJSONArray("labels")) : null; this.issueTrackers = o.has("issueTrackers") ? o.getJSONArray("issueTrackers").stream().map(IssueTracker::createFromJSONObject).filter(Objects::nonNull).toArray(IssueTracker[]::new) : null; JSONArray ja = o.getJSONArray("dependencies"); - int depCount = (int)ja.stream().filter(IS_DEP_PREDICATE.and(IS_NOT_OPTIONAL)).count(); - int optionalDepCount = (int)ja.stream().filter(IS_DEP_PREDICATE.and(IS_NOT_OPTIONAL.negate())).count(); + int depCount = (int) ja.stream().filter(IS_DEP_PREDICATE.and(IS_NOT_OPTIONAL)).count(); + int optionalDepCount = (int) ja.stream().filter(IS_DEP_PREDICATE.and(IS_NOT_OPTIONAL.negate())).count(); dependencies = getPresizedMutableMap(depCount); optionalDependencies = getPresizedMutableMap(optionalDepCount); - for(Object jo : o.getJSONArray("dependencies")) { + for (Object jo : o.getJSONArray("dependencies")) { JSONObject depObj = (JSONObject) jo; // Make sure there's a name attribute and that the optional value isn't true. - String depName = Util.intern(get(depObj,"name")); - if (depName!=null) { + String depName = Util.intern(get(depObj, "name")); + if (depName != null) { if (get(depObj, "optional").equals("false")) { dependencies.put(depName, Util.intern(get(depObj, "version"))); } else { @@ -1273,7 +1273,7 @@ public UpdateSite.Deprecation getDeprecation() { public String getDisplayName() { String displayName; - if(title!=null) + if (title != null) displayName = title; else displayName = name; @@ -1337,7 +1337,7 @@ public boolean isCompatibleWithInstalledVersion() { public List getNeededDependencies() { List deps = new ArrayList<>(); - for(Map.Entry e : dependencies.entrySet()) { + for (Map.Entry e : dependencies.entrySet()) { VersionNumber requiredVersion = e.getValue() != null ? new VersionNumber(e.getValue()) : null; Plugin depPlugin = Jenkins.get().getUpdateCenter().getPlugin(e.getKey(), requiredVersion); if (depPlugin == null) { @@ -1348,7 +1348,7 @@ public List getNeededDependencies() { // Is the plugin installed already? If not, add it. PluginWrapper current = depPlugin.getInstalled(); - if (current ==null) { + if (current == null) { deps.add(depPlugin); } // If the dependency plugin is installed, is the version we depend on newer than @@ -1362,7 +1362,7 @@ else if (!current.isEnabled()) { } } - for(Map.Entry e : optionalDependencies.entrySet()) { + for (Map.Entry e : optionalDependencies.entrySet()) { VersionNumber requiredVersion = e.getValue() != null ? new VersionNumber(e.getValue()) : null; Plugin depPlugin = Jenkins.get().getUpdateCenter().getPlugin(e.getKey(), requiredVersion); if (depPlugin == null) { @@ -1383,7 +1383,7 @@ else if (!current.isEnabled()) { public boolean isForNewerHudson() { try { - return requiredCore!=null && new VersionNumber(requiredCore).isNewerThan( + return requiredCore != null && new VersionNumber(requiredCore).isNewerThan( new VersionNumber(Jenkins.VERSION.replaceFirst("SHOT *\\(private.*\\)", "SHOT"))); } catch (NumberFormatException nfe) { return true; // If unable to parse version @@ -1412,7 +1412,7 @@ public VersionNumber getNeededDependenciesRequiredCore() { } catch (NumberFormatException nfe) { // unable to parse version } - for (Plugin p: getNeededDependencies()) { + for (Plugin p : getNeededDependencies()) { VersionNumber v = p.getNeededDependenciesRequiredCore(); if (versionNumber == null || v.isNewerThan(versionNumber)) versionNumber = v; } @@ -1432,7 +1432,7 @@ public VersionNumber getNeededDependenciesMinimumJavaVersion() { } catch (NumberFormatException nfe) { logBadMinJavaVersion(); } - for (Plugin p: getNeededDependencies()) { + for (Plugin p : getNeededDependencies()) { VersionNumber v = p.getNeededDependenciesMinimumJavaVersion(); if (v == null) { continue; @@ -1471,7 +1471,7 @@ public boolean isNeededDependenciesForNewerJenkins(PluginManager.MetadataCache c * @since 2.158 */ public boolean isNeededDependenciesForNewerJava() { - for (Plugin p: getNeededDependencies()) { + for (Plugin p : getNeededDependencies()) { if (p.isForNewerJava() || p.isNeededDependenciesForNewerJava()) { return true; } @@ -1564,7 +1564,7 @@ public Set getWarnings() { UpdateSiteWarningsConfiguration configuration = ExtensionList.lookupSingleton(UpdateSiteWarningsConfiguration.class); Set warnings = new HashSet<>(); - for (Warning warning: configuration.getAllWarnings()) { + for (Warning warning : configuration.getAllWarnings()) { if (configuration.isIgnored(warning)) { // warning is currently being ignored continue; @@ -1669,14 +1669,14 @@ public Future deploy(boolean dynamicLoad, @CheckForNull UUID co } } PluginWrapper pw = getInstalled(); - if(pw != null) { // JENKINS-34494 - check for this plugin being disabled + if (pw != null) { // JENKINS-34494 - check for this plugin being disabled Future enableJob = null; - if(!pw.isEnabled()) { + if (!pw.isEnabled()) { UpdateCenter.EnableJob job = uc.new EnableJob(UpdateSite.this, null, this, dynamicLoad); job.setCorrelationId(correlationId); enableJob = uc.addJob(job); } - if(pw.getVersionNumber().equals(new VersionNumber(version))) { + if (pw.getVersionNumber().equals(new VersionNumber(version))) { return enableJob != null ? enableJob : uc.addJob(uc.new NoOpJob(UpdateSite.this, null, this)); } } @@ -1697,6 +1697,7 @@ public Future deployBackup() { /** * Making the installation web bound. */ + @RequirePOST public HttpResponse doInstall() throws IOException { deploy(false); @@ -1725,6 +1726,6 @@ public HttpResponse doDowngrade() throws IOException { // The name uses UpdateCenter for compatibility reason. @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "for script console") - public static boolean neverUpdate = SystemProperties.getBoolean(UpdateCenter.class.getName()+".never"); + public static boolean neverUpdate = SystemProperties.getBoolean(UpdateCenter.class.getName() + ".never"); } diff --git a/core/src/main/java/hudson/model/UsageStatistics.java b/core/src/main/java/hudson/model/UsageStatistics.java index bc292db26c361..0a13c0983b160 100644 --- a/core/src/main/java/hudson/model/UsageStatistics.java +++ b/core/src/main/java/hudson/model/UsageStatistics.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static java.util.concurrent.TimeUnit.DAYS; @@ -73,7 +74,7 @@ @Extension public class UsageStatistics extends PageDecorator implements PersistentDescriptor { private static final Logger LOG = Logger.getLogger(UsageStatistics.class.getName()); - + private final String keyImage; /** @@ -102,10 +103,10 @@ public UsageStatistics(String keyImage) { */ public boolean isDue() { // user opted out. no data collection. - if(!Jenkins.get().isUsageStatisticsCollected() || DISABLED) return false; - + if (!Jenkins.get().isUsageStatisticsCollected() || DISABLED) return false; + long now = System.currentTimeMillis(); - if(now - lastAttempt > DAY) { + if (now - lastAttempt > DAY) { lastAttempt = now; return true; } @@ -116,7 +117,7 @@ private RSAPublicKey getKey() { try { if (key == null) { KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - key = (RSAPublicKey)keyFactory.generatePublic(new X509EncodedKeySpec(Util.fromHexString(keyImage))); + key = (RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(Util.fromHexString(keyImage))); } return key; } catch (GeneralSecurityException e) { @@ -125,50 +126,50 @@ private RSAPublicKey getKey() { } /** - * Gets the encrypted usage stat data to be sent to the Hudson server. + * Gets the encrypted usage stat data to be sent to the Hudson server. * Used exclusively by jelly: resources/hudson/model/UsageStatistics/footer.jelly */ public String getStatData() throws IOException { Jenkins j = Jenkins.get(); JSONObject o = new JSONObject(); - o.put("stat",1); + o.put("stat", 1); o.put("install", j.getLegacyInstanceId()); o.put("servletContainer", j.servletContext.getServerInfo()); o.put("version", Jenkins.VERSION); List nodes = new ArrayList<>(); - for( Computer c : j.getComputers() ) { + for (Computer c : j.getComputers()) { JSONObject n = new JSONObject(); - if(c.getNode()==j) { - n.put("master",true); + if (c.getNode() == j) { + n.put("master", true); n.put("jvm-vendor", System.getProperty("java.vm.vendor")); n.put("jvm-name", System.getProperty("java.vm.name")); n.put("jvm-version", System.getProperty("java.version")); } - n.put("executors",c.getNumExecutors()); + n.put("executors", c.getNumExecutors()); ArchitectureMonitor.DescriptorImpl descriptor = j.getDescriptorByType(ArchitectureMonitor.DescriptorImpl.class); n.put("os", descriptor.get(c)); nodes.add(n); } - o.put("nodes",nodes); + o.put("nodes", nodes); List plugins = new ArrayList<>(); - for( PluginWrapper pw : j.getPluginManager().getPlugins() ) { - if(!pw.isActive()) continue; // treat disabled plugins as if they are uninstalled + for (PluginWrapper pw : j.getPluginManager().getPlugins()) { + if (!pw.isActive()) continue; // treat disabled plugins as if they are uninstalled JSONObject p = new JSONObject(); - p.put("name",pw.getShortName()); - p.put("version",pw.getVersion()); + p.put("name", pw.getShortName()); + p.put("version", pw.getVersion()); plugins.add(p); } - o.put("plugins",plugins); + o.put("plugins", plugins); JSONObject jobs = new JSONObject(); // capture the descriptors as these should be small compared with the number of items // so we will walk all items only once and we can short-cut the search of descriptors TopLevelItemDescriptor[] descriptors = Items.all().toArray(new TopLevelItemDescriptor[0]); int[] counts = new int[descriptors.length]; - for (TopLevelItem item: j.allItems(TopLevelItem.class)) { + for (TopLevelItem item : j.allItems(TopLevelItem.class)) { TopLevelItemDescriptor d = item.getDescriptor(); for (int i = 0; i < descriptors.length; i++) { if (d == descriptors[i]) { @@ -181,19 +182,19 @@ public String getStatData() throws IOException { for (int i = 0; i < descriptors.length; i++) { jobs.put(descriptors[i].getJsonSafeClassName(), counts[i]); } - o.put("jobs",jobs); + o.put("jobs", jobs); try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); // json -> UTF-8 encode -> gzip -> encrypt -> base64 -> string - try (OutputStream cipheros = new CombinedCipherOutputStream(baos,getKey(),"AES"); + try (OutputStream cipheros = new CombinedCipherOutputStream(baos, getKey(), "AES"); OutputStream zipos = new GZIPOutputStream(cipheros); OutputStreamWriter w = new OutputStreamWriter(zipos, StandardCharsets.UTF_8)) { o.write(w); } - return new String(Base64.getEncoder().encode(baos.toByteArray())); + return Base64.getEncoder().encodeToString(baos.toByteArray()); } catch (Throwable e) { // the exception could be GeneralSecurityException, InvalidParameterException or any other depending on the security provider you have installed LOG.log(Level.INFO, "Usage statistics could not be sent ({0})", e.getMessage()); LOG.log(Level.FINE, "Error sending usage statistics", e); @@ -214,7 +215,7 @@ public boolean configure(StaplerRequest req, JSONObject json) throws FormExcepti Jenkins.get().setNoUsageStatistics(json.has("usageStatisticsCollected") ? null : true); return true; } catch (IOException e) { - throw new FormException(e,"usageStatisticsCollected"); + throw new FormException(e, "usageStatisticsCollected"); } } @@ -237,12 +238,12 @@ public CombinedCipherOutputStream(OutputStream out, Cipher asym, String algorith // the rest of the data will be encrypted by this symmetric cipher Cipher sym = Secret.getCipher(algorithm); - sym.init(Cipher.ENCRYPT_MODE,symKey, keyAlgorithm.equals(algorithm) ? null : new IvParameterSpec(symKey.getEncoded())); - super.out = new CipherOutputStream(out,sym); + sym.init(Cipher.ENCRYPT_MODE, symKey, keyAlgorithm.equals(algorithm) ? null : new IvParameterSpec(symKey.getEncoded())); + super.out = new CipherOutputStream(out, sym); } public CombinedCipherOutputStream(OutputStream out, RSAKey key, String algorithm) throws IOException, GeneralSecurityException { - this(out,toCipher(key,Cipher.ENCRYPT_MODE),algorithm); + this(out, toCipher(key, Cipher.ENCRYPT_MODE), algorithm); } } @@ -261,18 +262,18 @@ public CombinedCipherInputStream(InputStream in, Cipher asym, String algorithm, String keyAlgorithm = getKeyAlgorithm(algorithm); // first read the symmetric key cipher - byte[] symKeyBytes = new byte[keyLength/8]; + byte[] symKeyBytes = new byte[keyLength / 8]; new DataInputStream(in).readFully(symKeyBytes); - SecretKey symKey = new SecretKeySpec(asym.doFinal(symKeyBytes),keyAlgorithm); + SecretKey symKey = new SecretKeySpec(asym.doFinal(symKeyBytes), keyAlgorithm); // the rest of the data will be decrypted by this symmetric cipher Cipher sym = Secret.getCipher(algorithm); - sym.init(Cipher.DECRYPT_MODE,symKey, keyAlgorithm.equals(algorithm) ? null : new IvParameterSpec(symKey.getEncoded())); - super.in = new CipherInputStream(in,sym); + sym.init(Cipher.DECRYPT_MODE, symKey, keyAlgorithm.equals(algorithm) ? null : new IvParameterSpec(symKey.getEncoded())); + super.in = new CipherInputStream(in, sym); } public CombinedCipherInputStream(InputStream in, RSAKey key, String algorithm) throws IOException, GeneralSecurityException { - this(in,toCipher(key,Cipher.DECRYPT_MODE),algorithm,key.getModulus().bitLength()); + this(in, toCipher(key, Cipher.DECRYPT_MODE), algorithm, key.getModulus().bitLength()); } } @@ -283,7 +284,7 @@ private static String getKeyAlgorithm(String algorithm) { private static Cipher toCipher(RSAKey key, int mode) throws GeneralSecurityException { Cipher cipher = Cipher.getInstance("RSA"); - cipher.init(mode, (Key)key); + cipher.init(mode, (Key) key); return cipher; } @@ -300,5 +301,5 @@ private static Cipher toCipher(RSAKey key, int mode) throws GeneralSecurityExcep private static final long DAY = DAYS.toMillis(1); @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "for script console") - public static boolean DISABLED = SystemProperties.getBoolean(UsageStatistics.class.getName()+".disabled"); + public static boolean DISABLED = SystemProperties.getBoolean(UsageStatistics.class.getName() + ".disabled"); } diff --git a/core/src/main/java/hudson/model/User.java b/core/src/main/java/hudson/model/User.java index bc998b48be4f4..758ca080549c7 100644 --- a/core/src/main/java/hudson/model/User.java +++ b/core/src/main/java/hudson/model/User.java @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import com.infradna.tool.bridge_method_injector.WithBridgeMethods; @@ -224,7 +225,7 @@ private void removeNullsThatFailedToLoad() { private void loadFromUserConfigFile(String userId) { XmlFile config = getConfigFile(); try { - if ( config != null && config.exists()) { + if (config != null && config.exists()) { config.unmarshal(this); this.id = userId; } @@ -758,19 +759,20 @@ public static void clear() { private static File getConfigFileFor(String id) { return new File(getUserFolderFor(id), "config.xml"); } - - private static File getUserFolderFor(String id){ + + private static File getUserFolderFor(String id) { return new File(getRootDir(), idStrategy().filenameOf(id)); } /** * Returns the folder that store all the user information. * Useful for plugins to save a user-specific file aside the config.xml. * Exposes implementation details that may be subject to change. - * + * * @return The folder containing the user configuration files or {@code null} if the user was not yet saved. * * @since 2.129 */ + public @CheckForNull File getUserFolder() { return getExistingUserFolder(); } diff --git a/core/src/main/java/hudson/model/UserIdMapper.java b/core/src/main/java/hudson/model/UserIdMapper.java index d84042a589066..93e6a03fd0f5c 100644 --- a/core/src/main/java/hudson/model/UserIdMapper.java +++ b/core/src/main/java/hudson/model/UserIdMapper.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; diff --git a/core/src/main/java/hudson/model/UserIdMigrator.java b/core/src/main/java/hudson/model/UserIdMigrator.java index b3e42d394ef6e..4af152b6acb48 100644 --- a/core/src/main/java/hudson/model/UserIdMigrator.java +++ b/core/src/main/java/hudson/model/UserIdMigrator.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import java.io.File; diff --git a/core/src/main/java/hudson/model/UserProperties.java b/core/src/main/java/hudson/model/UserProperties.java index 2f521b31f401d..cb840e40752da 100644 --- a/core/src/main/java/hudson/model/UserProperties.java +++ b/core/src/main/java/hudson/model/UserProperties.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.Extension; diff --git a/core/src/main/java/hudson/model/UserProperty.java b/core/src/main/java/hudson/model/UserProperty.java index f0d7ce5b3ed74..a9b9dbae7acd9 100644 --- a/core/src/main/java/hudson/model/UserProperty.java +++ b/core/src/main/java/hudson/model/UserProperty.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.DescriptorExtensionList; @@ -70,12 +71,12 @@ public UserPropertyDescriptor getDescriptor() { /** * Returns all the registered {@link UserPropertyDescriptor}s. */ - public static DescriptorExtensionList all() { + public static DescriptorExtensionList all() { return Jenkins.get().getDescriptorList(UserProperty.class); } @Override public UserProperty reconfigure(StaplerRequest req, JSONObject form) throws FormException { - return form==null ? null : getDescriptor().newInstance(req, form); + return form == null ? null : getDescriptor().newInstance(req, form); } } diff --git a/core/src/main/java/hudson/model/UserPropertyDescriptor.java b/core/src/main/java/hudson/model/UserPropertyDescriptor.java index 5367c7c01451d..22e05ea59afff 100644 --- a/core/src/main/java/hudson/model/UserPropertyDescriptor.java +++ b/core/src/main/java/hudson/model/UserPropertyDescriptor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Daniel Dyer - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,11 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; /** * {@link Descriptor} for {@link UserProperty}. - * + * * @author Kohsuke Kawaguchi */ public abstract class UserPropertyDescriptor extends Descriptor { @@ -67,7 +68,7 @@ protected UserPropertyDescriptor() { * *

      * This mechanism is useful if the availability of the property is - * contingent of some other settings. + * contingent of some other settings. */ public boolean isEnabled() { return true; diff --git a/core/src/main/java/hudson/model/View.java b/core/src/main/java/hudson/model/View.java index 33d9d000c7b97..37fe1a64a8541 100644 --- a/core/src/main/java/hudson/model/View.java +++ b/core/src/main/java/hudson/model/View.java @@ -1,19 +1,19 @@ /* * The MIT License - * + * * Copyright (c) 2004-2011, Sun Microsystems, Inc., Kohsuke Kawaguchi, Tom Huybrechts, * Yahoo!, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; @@ -43,8 +44,6 @@ import hudson.scm.ChangeLogSet; import hudson.search.CollectionSearchIndex; import hudson.search.SearchIndexBuilder; -import hudson.search.SearchItemCategory; -import hudson.search.Icon; import hudson.security.ACL; import hudson.security.AccessControlled; import hudson.security.Permission; @@ -107,9 +106,8 @@ import net.sf.json.JSON; import net.sf.json.JSONArray; import net.sf.json.JSONObject; -import org.apache.commons.jelly.JellyContext; import org.apache.commons.lang.StringUtils; -import org.apache.tools.ant.filters.StringInputStream; +import org.jenkins.ui.icon.Icon; import org.jenkins.ui.icon.IconSet; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.DoNotUse; @@ -141,7 +139,7 @@ *

    • * {@link View} subtypes need the {@code newViewDetail.jelly} page, * which is included in the "new view" page. This page should have some - * description of what the view is about. + * description of what the view is about. *
    * * @author Kohsuke Kawaguchi @@ -166,7 +164,7 @@ public abstract class View extends AbstractModelObject implements AccessControll * Message displayed in the view page. */ protected String description; - + /** * If true, only show relevant executors */ @@ -176,12 +174,12 @@ public abstract class View extends AbstractModelObject implements AccessControll * If true, only show relevant queue items */ protected boolean filterQueue; - + /** * List of {@link ViewProperty}s configured for this view. * @since 1.406 */ - private volatile DescribableList properties = new PropertyList(this); + private volatile DescribableList properties = new PropertyList(this); protected View(String name) { this.name = name; @@ -196,7 +194,7 @@ protected View(String name, ViewGroup owner) { * Gets all the items in this collection in a read-only view. */ @NonNull - @Exported(name="jobs") + @Exported(name = "jobs") public abstract Collection getItems(); /** @@ -212,7 +210,7 @@ public Collection getAllItems() { if (this instanceof ViewGroup) { final Collection items = new LinkedHashSet<>(getItems()); - for(View view: ((ViewGroup) this).getViews()) { + for (View view : ((ViewGroup) this).getViews()) { items.addAll(view.getAllItems()); } return Collections.unmodifiableCollection(items); @@ -245,7 +243,7 @@ public final TopLevelItem getJob(String name) { * * @see #rename(String) */ - @Exported(visibility=2,name="name") + @Exported(visibility = 2, name = "name") @NonNull public String getViewName() { return name; @@ -255,13 +253,13 @@ public String getViewName() { * Renames this view. */ public void rename(String newName) throws Failure, FormException { - if(name.equals(newName)) return; // noop + if (name.equals(newName)) return; // noop Jenkins.checkGoodName(newName); - if(owner.getView(newName)!=null) - throw new FormException(Messages.Hudson_ViewAlreadyExists(newName),"name"); + if (owner.getView(newName) != null) + throw new FormException(Messages.Hudson_ViewAlreadyExists(newName), "name"); String oldName = name; name = newName; - owner.onViewRenamed(this,oldName,newName); + owner.onViewRenamed(this, oldName, newName); } /** @@ -306,7 +304,7 @@ public synchronized void setDescription(String description) { * Gets the view properties configured for this view. * @since 1.406 */ - public DescribableList getProperties() { + public DescribableList getProperties() { // readResolve was the best place to do this, but for compatibility reasons, // this class can no longer have readResolve() (the mechanism itself isn't suitable for class hierarchy) // see JENKINS-9431 @@ -358,7 +356,7 @@ public void save() throws IOException { * List of all {@link ViewProperty}s exposed primarily for the remoting API. * @since 1.406 */ - @Exported(name="property",inline=true) + @Exported(name = "property", inline = true) public List getAllProperties() { return getProperties().toList(); } @@ -387,7 +385,7 @@ public String getNewPronoun() { public boolean isEditable() { return true; } - + /** * Used to enable or disable automatic refreshes of the view. * @@ -399,14 +397,14 @@ public boolean isEditable() { public boolean isAutomaticRefreshEnabled() { return false; } - + /** * If true, only show relevant executors */ public boolean isFilterExecutors() { return filterExecutors; } - + /** * If true, only show relevant queue items */ @@ -443,9 +441,9 @@ public Indenter getIndenter() { * If true, this is a view that renders the top page of Hudson. */ public boolean isDefault() { - return getOwner().getPrimaryView()==this; + return getOwner().getPrimaryView() == this; } - + public List getComputers() { Computer[] computers = Jenkins.get().getComputers(); @@ -517,7 +515,7 @@ private boolean filterQueueItemTest(Queue.Item item, Collection vi } // Check root project for sub-job projects (e.g. matrix jobs). if (item.task instanceof AbstractProject) { - AbstractProject project = (AbstractProject) item.task; + AbstractProject project = (AbstractProject) item.task; if (viewItems.contains(project.getRootProject())) { return true; } @@ -545,7 +543,7 @@ public List getApproximateQueueItemsQuickly() { * empty string when this is the default view). */ public String getUrl() { - return isDefault() ? (owner!=null ? owner.getUrl() : "") : getViewUrl(); + return isDefault() ? (owner != null ? owner.getUrl() : "") : getViewUrl(); } /** @@ -553,7 +551,7 @@ public String getUrl() { * even for the default view. */ public String getViewUrl() { - return (owner!=null ? owner.getUrl() : "") + "view/" + Util.rawEncode(getViewName()) + '/'; + return (owner != null ? owner.getUrl() : "") + "view/" + Util.rawEncode(getViewName()) + '/'; } @Override public String toString() { @@ -565,16 +563,6 @@ public String getSearchUrl() { return getUrl(); } - @Override - public SearchItemCategory getSearchItemCategory() { - return SearchItemCategory.VIEWS; - } - - @Override - public Icon getSearchItemIcon() { - return Icon.fromSvg(IconSet.getIonicon("albums-outline", null)); - } - /** * Returns the transient {@link Action}s associated with the top page. * @@ -602,7 +590,7 @@ public void updateTransientActions() {} public Object getDynamic(String token) { for (Action a : getActions()) { String url = a.getUrlName(); - if (url==null) continue; + if (url == null) continue; if (url.equals(token)) return a; } @@ -612,9 +600,9 @@ public Object getDynamic(String token) { /** * Gets the absolute URL of this view. */ - @Exported(visibility=2,name="url") + @Exported(visibility = 2, name = "url") public String getAbsoluteUrl() { - return Jenkins.get().getRootUrl()+getUrl(); + return Jenkins.get().getRootUrl() + getUrl(); } public Api getApi() { @@ -643,7 +631,7 @@ public ACL getACL() { @Deprecated public void onJobRenamed(Item item, String oldName, String newName) {} - @ExportedBean(defaultVisibility=2) + @ExportedBean(defaultVisibility = 2) public static final class UserInfo implements Comparable { private final User user; /** @@ -653,12 +641,12 @@ public static final class UserInfo implements Comparable { /** * Which project did this user commit? Can be null. */ - private Job project; + private Job project; /** @see UserAvatarResolver */ String avatar; - UserInfo(User user, Job p, Calendar lastChange) { + UserInfo(User user, Job p, Calendar lastChange) { this.user = user; this.project = p; this.lastChange = lastChange; @@ -676,11 +664,11 @@ public Calendar getLastChange() { @Deprecated public AbstractProject getProject() { - return project instanceof AbstractProject ? (AbstractProject)project : null; + return project instanceof AbstractProject ? (AbstractProject) project : null; } - @Exported(name="project") - public Job getJob() { + @Exported(name = "project") + public Job getJob() { return project; } @@ -688,13 +676,13 @@ public Job getJob() { * Returns a human-readable string representation of when this user was last active. */ public String getLastChangeTimeString() { - if(lastChange==null) return "N/A"; - long duration = new GregorianCalendar().getTimeInMillis()- ordinal(); + if (lastChange == null) return "N/A"; + long duration = new GregorianCalendar().getTimeInMillis() - ordinal(); return Util.getTimeSpanString(duration); } public String getTimeSortKey() { - if(lastChange==null) return "-"; + if (lastChange == null) return "-"; return Util.XS_DATETIME_FORMATTER.format(lastChange.getTime()); } @@ -706,7 +694,7 @@ public int compareTo(UserInfo that) { } private long ordinal() { - if(lastChange==null) return 0; + if (lastChange == null) return 0; return lastChange.getTimeInMillis(); } } @@ -745,12 +733,12 @@ public static final class People { public People(Jenkins parent) { this.parent = parent; // for Hudson, really load all users - Map users = getUserInfo(parent.getItems()); + Map users = getUserInfo(parent.getItems()); User unknown = User.getUnknown(); for (User u : User.getAll()) { - if(u==unknown) continue; // skip the special 'unknown' user - if(!users.containsKey(u)) - users.put(u,new UserInfo(u,null,null)); + if (u == unknown) continue; // skip the special 'unknown' user + if (!users.containsKey(u)) + users.put(u, new UserInfo(u, null, null)); } this.users = toList(users); } @@ -760,14 +748,14 @@ public People(View parent) { this.users = toList(getUserInfo(parent.getItems())); } - private Map getUserInfo(Collection items) { - Map users = new HashMap<>(); + private Map getUserInfo(Collection items) { + Map users = new HashMap<>(); for (Item item : items) { for (Job job : item.getAllJobs()) { RunList> runs = job.getBuilds(); for (Run r : runs) { if (r instanceof RunWithSCM) { - RunWithSCM runWithSCM = (RunWithSCM) r; + RunWithSCM runWithSCM = (RunWithSCM) r; for (ChangeLogSet c : runWithSCM.getChangeSets()) { for (ChangeLogSet.Entry entry : c) { @@ -789,7 +777,7 @@ else if (info.getLastChange().before(r.getTimestamp())) { return users; } - private List toList(Map users) { + private List toList(Map users) { ArrayList list = new ArrayList<>(users.values()); Collections.sort(list); return Collections.unmodifiableList(list); @@ -808,9 +796,9 @@ public static boolean isApplicable(Collection items) { for (Job job : item.getAllJobs()) { RunList> runs = job.getBuilds(); - for (Run r : runs) { + for (Run r : runs) { if (r instanceof RunWithSCM) { - RunWithSCM runWithSCM = (RunWithSCM) r; + RunWithSCM runWithSCM = (RunWithSCM) r; for (ChangeLogSet c : runWithSCM.getChangeSets()) { for (ChangeLogSet.Entry entry : c) { User user = entry.getAuthor(); @@ -834,7 +822,7 @@ public static final class AsynchPeople extends ProgressiveRendering { // JENKINS private final Collection items; private final User unknown; - private final Map users = new HashMap<>(); + private final Map users = new HashMap<>(); private final Set modified = new HashSet<>(); private final String iconSize; public final ModelObject parent; @@ -861,7 +849,7 @@ public AsynchPeople(View parent) { @Override protected void compute() throws Exception { int itemCount = 0; for (Item item : items) { - for (Job job : item.getAllJobs()) { + for (Job job : item.getAllJobs()) { RunList> builds = job.getBuilds(); int buildCount = 0; for (Run r : builds) { @@ -933,11 +921,11 @@ public AsynchPeople(View parent) { JSONObject entry = new JSONObject(). accumulate("id", u.getId()). accumulate("fullName", u.getFullName()). - accumulate("url", u.getUrl()). + accumulate("url", u.getUrl() + "/"). accumulate("avatar", i.avatar != null ? i.avatar : Stapler.getCurrentRequest().getContextPath() + Functions.getResourcePath() + "/images/svgs/person.svg"). accumulate("timeSortKey", i.getTimeSortKey()). accumulate("lastChangeTimeString", i.getLastChangeTimeString()); - Job p = i.getJob(); + Job p = i.getJob(); if (p != null) { entry.accumulate("projectUrl", p.getUrl()).accumulate("projectFullDisplayName", p.getFullDisplayName()); } @@ -969,14 +957,14 @@ public final class People { } void addDisplayNamesToSearchIndex(SearchIndexBuilder sib, Collection items) { - for(TopLevelItem item : items) { - - if(LOGGER.isLoggable(Level.FINE)) { + for (TopLevelItem item : items) { + + if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(String.format("Adding url=%s,displayName=%s", item.getSearchUrl(), item.getDisplayName())); } sib.add(item.getSearchUrl(), item.getDisplayName()); - } + } } /** @@ -986,11 +974,13 @@ void addDisplayNamesToSearchIndex(SearchIndexBuilder sib, Collection() {// for jobs in the view + sib.add(new CollectionSearchIndex() { // for jobs in the view @Override protected TopLevelItem get(String key) { return getItem(key); } + @Override protected Collection all() { return getItems(); } + @Override protected String getName(TopLevelItem o) { // return the name instead of the display for suggestion searching @@ -1003,7 +993,7 @@ protected String getName(TopLevelItem o) { public SearchIndexBuilder makeSearchIndex() { SearchIndexBuilder sib = super.makeSearchIndex(); makeSearchIndex(sib); - + // add the display name for each item in the search index addDisplayNamesToSearchIndex(sib, getItems()); @@ -1014,7 +1004,7 @@ public SearchIndexBuilder makeSearchIndex() { * Accepts the new description. */ @RequirePOST - public synchronized void doSubmitDescription( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public synchronized void doSubmitDescription(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { checkPermission(CONFIGURE); description = req.getParameter("description"); @@ -1028,7 +1018,7 @@ public synchronized void doSubmitDescription( StaplerRequest req, StaplerRespons * Subtypes should override the {@link #submit(StaplerRequest)} method. */ @POST - public final synchronized void doConfigSubmit( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, FormException { + public final synchronized void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException { checkPermission(CONFIGURE); submit(req); @@ -1043,7 +1033,7 @@ public final synchronized void doConfigSubmit( StaplerRequest req, StaplerRespon save(); - FormApply.success("../" + Util.rawEncode(name)).generateResponse(req,rsp,this); + FormApply.success("../" + Util.rawEncode(name)).generateResponse(req, rsp, this); } /** @@ -1062,7 +1052,7 @@ public synchronized void doDoDelete(StaplerRequest req, StaplerResponse rsp) thr owner.deleteView(this); - rsp.sendRedirect2(req.getContextPath()+"/" + owner.getUrl()); + rsp.sendRedirect2(req.getContextPath() + "/" + owner.getUrl()); } @@ -1072,11 +1062,11 @@ public synchronized void doDoDelete(StaplerRequest req, StaplerResponse rsp) thr *

    * This method should call {@link ModifiableItemGroup#doCreateItem(StaplerRequest, StaplerResponse)} * and then add the newly created item to this view. - * + * * @return * null if fails. */ - public abstract Item doCreateItem( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException; + public abstract Item doCreateItem(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException; /** * Makes sure that the given name is good as a job name. @@ -1122,13 +1112,12 @@ public Categories doItemCategories(StaplerRequest req, StaplerResponse rsp, @Que rsp.addHeader("Expires", "0"); Categories categories = new Categories(); int order = 0; - JellyContext ctx; + String resUrl; if (StringUtils.isNotBlank(iconStyle)) { - ctx = new JellyContext(); - ctx.setVariable("resURL", req.getContextPath() + Jenkins.RESOURCE_PATH); + resUrl = req.getContextPath() + Jenkins.RESOURCE_PATH; } else { - ctx = null; + resUrl = null; } for (TopLevelItemDescriptor descriptor : DescriptorVisibilityFilter.apply(getOwner().getItemGroup(), Items.all2(Jenkins.getAuthentication2(), getOwner().getItemGroup()))) { ItemCategory ic = ItemCategory.getCategory(descriptor); @@ -1143,11 +1132,11 @@ public Categories doItemCategories(StaplerRequest req, StaplerResponse rsp, @Que String iconClassName = descriptor.getIconClassName(); if (StringUtils.isNotBlank(iconClassName)) { metadata.put("iconClassName", iconClassName); - if (ctx != null) { - org.jenkins.ui.icon.Icon icon = IconSet.icons + if (resUrl != null) { + Icon icon = IconSet.icons .getIconByClassSpec(String.join(" ", iconClassName, iconStyle)); if (icon != null) { - metadata.put("iconQualifiedUrl", icon.getQualifiedUrl(ctx)); + metadata.put("iconQualifiedUrl", icon.getQualifiedUrl(resUrl)); } } } @@ -1165,29 +1154,29 @@ public Categories doItemCategories(StaplerRequest req, StaplerResponse rsp, @Que return categories; } - public void doRssAll( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public void doRssAll(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { RSS.rss(req, rsp, "Jenkins:" + getDisplayName() + " (all builds)", getUrl(), getBuilds().newBuilds()); } - public void doRssFailed( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public void doRssFailed(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { RSS.rss(req, rsp, "Jenkins:" + getDisplayName() + " (failed builds)", getUrl(), getBuilds().failureOnly().newBuilds()); } - + public RunList getBuilds() { return new RunList(this); } - + public BuildTimelineWidget getTimeline() { return new BuildTimelineWidget(getBuilds()); } - public void doRssLatest( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public void doRssLatest(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { List lastBuilds = new ArrayList<>(); for (TopLevelItem item : getItems()) { if (item instanceof Job) { Job job = (Job) item; Run lb = job.getLastBuild(); - if(lb!=null) lastBuilds.add(lb); + if (lb != null) lastBuilds.add(lb); } } RSS.rss(req, rsp, "Jenkins:" + getDisplayName() + " (latest builds)", getUrl(), RunList.fromRuns(lastBuilds), Run.FEED_ADAPTER_LATEST); @@ -1244,12 +1233,12 @@ public void updateByXml(Source source) throws IOException { // data XMLUtils.safeTransform(source, new StreamResult(out)); out.close(); - } catch (TransformerException|SAXException e) { + } catch (TransformerException | SAXException e) { throw new IOException("Failed to persist configuration.xml", e); } // try to reflect the changes by reloading - try (InputStream in = new BufferedInputStream(new ByteArrayInputStream(out.toString().getBytes(StandardCharsets.UTF_8)))){ + try (InputStream in = new BufferedInputStream(new ByteArrayInputStream(out.toString().getBytes(StandardCharsets.UTF_8)))) { // Do not allow overwriting view name as it might collide with another // view in same ViewGroup and might not satisfy Jenkins.checkGoodName. String oldname = name; @@ -1258,14 +1247,14 @@ public void updateByXml(Source source) throws IOException { if (!o.getClass().equals(getClass())) { // ensure that we've got the same view type. extending this code to support updating // to different view type requires destroying & creating a new view type - throw new IOException("Expecting view type: "+this.getClass()+" but got: "+o.getClass()+" instead." + + throw new IOException("Expecting view type: " + this.getClass() + " but got: " + o.getClass() + " instead." + "\nShould you needed to change to a new view type, you must first delete and then re-create " + "the view with the new view type."); } name = oldname; owner = oldOwner; - } catch (StreamException | ConversionException | Error e) {// mostly reflection errors - throw new IOException("Unable to read",e); + } catch (StreamException | ConversionException | Error e) { // mostly reflection errors + throw new IOException("Unable to read", e); } save(); } @@ -1274,7 +1263,7 @@ public void updateByXml(Source source) throws IOException { public ModelObjectWithContextMenu.ContextMenu doChildrenContextMenu(StaplerRequest request, StaplerResponse response) throws Exception { ModelObjectWithContextMenu.ContextMenu m = new ModelObjectWithContextMenu.ContextMenu(); for (TopLevelItem i : getItems()) - m.add(i.getShortUrl(),i.getDisplayName()); + m.add(i.getShortUrl(), i.getDisplayName()); return m; } @@ -1289,7 +1278,7 @@ public ModelObjectWithContextMenu.ContextMenu doChildrenContextMenu(StaplerReque /** * Returns all the registered {@link ViewDescriptor}s. */ - public static DescriptorExtensionList all() { + public static DescriptorExtensionList all() { return Jenkins.get().getDescriptorList(View.class); } @@ -1322,14 +1311,14 @@ public static List allInstantiable() { public static final Comparator SORTER = Comparator.comparing(View::getViewName); - public static final PermissionGroup PERMISSIONS = new PermissionGroup(View.class,Messages._View_Permissions_Title()); + public static final PermissionGroup PERMISSIONS = new PermissionGroup(View.class, Messages._View_Permissions_Title()); /** * Permission to create new views. */ - public static final Permission CREATE = new Permission(PERMISSIONS,"Create", Messages._View_CreatePermission_Description(), Permission.CREATE, PermissionScope.ITEM_GROUP); - public static final Permission DELETE = new Permission(PERMISSIONS,"Delete", Messages._View_DeletePermission_Description(), Permission.DELETE, PermissionScope.ITEM_GROUP); - public static final Permission CONFIGURE = new Permission(PERMISSIONS,"Configure", Messages._View_ConfigurePermission_Description(), Permission.CONFIGURE, PermissionScope.ITEM_GROUP); - public static final Permission READ = new Permission(PERMISSIONS,"Read", Messages._View_ReadPermission_Description(), Permission.READ, PermissionScope.ITEM_GROUP); + public static final Permission CREATE = new Permission(PERMISSIONS, "Create", Messages._View_CreatePermission_Description(), Permission.CREATE, PermissionScope.ITEM_GROUP); + public static final Permission DELETE = new Permission(PERMISSIONS, "Delete", Messages._View_DeletePermission_Description(), Permission.DELETE, PermissionScope.ITEM_GROUP); + public static final Permission CONFIGURE = new Permission(PERMISSIONS, "Configure", Messages._View_ConfigurePermission_Description(), Permission.CONFIGURE, PermissionScope.ITEM_GROUP); + public static final Permission READ = new Permission(PERMISSIONS, "Read", Messages._View_ReadPermission_Description(), Permission.READ, PermissionScope.ITEM_GROUP); @SuppressFBWarnings(value = "RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT", justification = "to guard against potential future compiler optimizations") @Initializer(before = InitMilestone.SYSTEM_CONFIG_LOADED) @@ -1348,7 +1337,7 @@ public static void registerPermissions() { public static Permission getItemCreatePermission() { return Item.CREATE; } - + public static View create(StaplerRequest req, StaplerResponse rsp, ViewGroup owner) throws FormException, IOException, ServletException { String mode = req.getParameter("mode"); @@ -1364,11 +1353,11 @@ public static View create(StaplerRequest req, StaplerResponse rsp, ViewGroup own String name = req.getParameter("name"); Jenkins.checkGoodName(name); - if(owner.getView(name)!=null) + if (owner.getView(name) != null) throw new Failure(Messages.Hudson_ViewAlreadyExists(name)); - if (mode==null || mode.length()==0) { - if(isXmlSubmission) { + if (mode == null || mode.length() == 0) { + if (isXmlSubmission) { View v = createViewFromXML(name, req.getInputStream()); owner.getACL().checkCreatePermission(owner, v.getDescriptor()); v.owner = owner; @@ -1396,7 +1385,7 @@ public static View create(StaplerRequest req, StaplerResponse rsp, ViewGroup own v.owner = owner; // redirect to the config screen - rsp.sendRedirect2(req.getContextPath()+'/'+v.getUrl()+v.getPostConstructLandingPage()); + rsp.sendRedirect2(req.getContextPath() + '/' + v.getUrl() + v.getPostConstructLandingPage()); return v; } @@ -1406,11 +1395,11 @@ private static View copy(StaplerRequest req, ViewGroup owner, String name) throw String from = req.getParameter("from"); View src = owner.getView(from); - if(src==null) { - if(Util.fixEmpty(from)==null) + if (src == null) { + if (Util.fixEmpty(from) == null) throw new Failure("Specify which view to copy"); else - throw new Failure("No such view: "+from); + throw new Failure("No such view: " + from); } String xml = Jenkins.XSTREAM.toXML(src); v = createViewFromXML(name, new ByteArrayInputStream(xml.getBytes(Charset.defaultCharset()))); @@ -1429,12 +1418,12 @@ public static View createViewFromXML(String name, InputStream xml) throws IOExce if (name != null) v.name = name; Jenkins.checkGoodName(v.name); return v; - } catch(StreamException|ConversionException|Error e) {// mostly reflection errors - throw new IOException("Unable to read",e); + } catch (StreamException | ConversionException | Error e) { // mostly reflection errors + throw new IOException("Unable to read", e); } } - public static class PropertyList extends DescribableList { + public static class PropertyList extends DescribableList { private PropertyList(View owner) { super(owner); } @@ -1443,7 +1432,7 @@ public PropertyList() {// needed for XStream deserialization } public View getOwner() { - return (View)owner; + return (View) owner; } @Override diff --git a/core/src/main/java/hudson/model/ViewDescriptor.java b/core/src/main/java/hudson/model/ViewDescriptor.java index 3b31a2f710635..7d4417e024c39 100644 --- a/core/src/main/java/hudson/model/ViewDescriptor.java +++ b/core/src/main/java/hudson/model/ViewDescriptor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -31,6 +32,7 @@ import hudson.views.ViewJobFilter; import java.util.Iterator; import java.util.List; +import java.util.Objects; import jenkins.model.DirectlyModifiableTopLevelItemGroup; import jenkins.model.Jenkins; import org.apache.commons.lang.StringUtils; @@ -70,7 +72,7 @@ public boolean isInstantiable() { * Jelly fragment included in the "new view" page. */ public final String getNewViewDetailPage() { - return '/'+clazz.getName().replace('.','/').replace('$','/')+"/newViewDetail.jelly"; + return '/' + clazz.getName().replace('.', '/').replace('$', '/') + "/newViewDetail.jelly"; } protected ViewDescriptor(Class clazz) { @@ -142,11 +144,11 @@ protected FormValidation checkDisplayName(@NonNull View view, @CheckForNull Stri // no custom name, no need to check return FormValidation.ok(); } - for (View v: view.owner.getViews()) { + for (View v : view.owner.getViews()) { if (v.getViewName().equals(view.getViewName())) { continue; } - if (StringUtils.equals(v.getDisplayName(), value)) { + if (Objects.equals(v.getDisplayName(), value)) { return FormValidation.warning(Messages.View_DisplayNameNotUniqueWarning(value)); } } diff --git a/core/src/main/java/hudson/model/ViewGroup.java b/core/src/main/java/hudson/model/ViewGroup.java index d0e9f95cdbb9d..1072f394322be 100644 --- a/core/src/main/java/hudson/model/ViewGroup.java +++ b/core/src/main/java/hudson/model/ViewGroup.java @@ -1,19 +1,19 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, * Tom Huybrechts, Alan Harder - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.NonNull; @@ -157,5 +158,5 @@ default ItemGroup getItemGroup() { default List getViewActions() { return Jenkins.get().getActions(); } - + } diff --git a/core/src/main/java/hudson/model/ViewGroupMixIn.java b/core/src/main/java/hudson/model/ViewGroupMixIn.java index 9505e47cb5c6f..0494758071528 100644 --- a/core/src/main/java/hudson/model/ViewGroupMixIn.java +++ b/core/src/main/java/hudson/model/ViewGroupMixIn.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -132,7 +133,7 @@ public View getView(@CheckForNull String name) { // Fallback to subview of primary view if it is a ViewGroup View pv = getPrimaryView(); if (pv instanceof ViewGroup) - return ((ViewGroup)pv).getView(name); + return ((ViewGroup) pv).getView(name); if (pv instanceof AllView && AllView.DEFAULT_VIEW_NAME.equals(pv.name)) { // JENKINS-38606: primary view is the default AllView, is somebody using an old link to localized form? for (Locale l : Locale.getAvailableLocales()) { @@ -169,7 +170,7 @@ public Collection getViews() { @CheckForNull public View getPrimaryView() { View v = getView(primaryView()); - if(v==null && !views().isEmpty()) // fallback + if (v == null && !views().isEmpty()) // fallback v = views().get(0); return v; } diff --git a/core/src/main/java/hudson/model/ViewJob.java b/core/src/main/java/hudson/model/ViewJob.java index 1a69809e154b6..5e8227450bde5 100644 --- a/core/src/main/java/hudson/model/ViewJob.java +++ b/core/src/main/java/hudson/model/ViewJob.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -47,8 +48,8 @@ * * @author Kohsuke Kawaguchi */ -public abstract class ViewJob, RunT extends Run> - extends Job { +public abstract class ViewJob, RunT extends Run> + extends Job { private static final Logger LOGGER = Logger.getLogger(ViewJob.class.getName()); @@ -84,11 +85,11 @@ static synchronized void interruptReloadThread() { */ @Deprecated protected ViewJob(Jenkins parent, String name) { - super(parent,name); + super(parent, name); } protected ViewJob(ItemGroup parent, String name) { - super(parent,name); + super(parent, name); } @Override @@ -103,20 +104,20 @@ public void onLoad(ItemGroup parent, String name) throws IOExcep } @Override - protected SortedMap _getRuns() { - if(notLoaded || runs==null) { + protected SortedMap _getRuns() { + if (notLoaded || runs == null) { // if none is loaded yet, do so immediately. - synchronized(this) { - if(runs==null) + synchronized (this) { + if (runs == null) runs = new RunMap<>(); - if(notLoaded) { + if (notLoaded) { notLoaded = false; - _reload(); + _reload(); } } } - if(nextUpdate _getRuns() { } reloadQueue = reloadThread.reloadQueue; } - synchronized(reloadQueue) { + synchronized (reloadQueue) { reloadQueue.add(this); reloadQueue.notify(); } @@ -150,7 +151,7 @@ private void _reload() { reload(); } finally { reloadingInProgress = false; - nextUpdate = reloadPeriodically ? System.currentTimeMillis()+TimeUnit.MINUTES.toMillis(1) : Long.MAX_VALUE; + nextUpdate = reloadPeriodically ? System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(1) : Long.MAX_VALUE; } } @@ -163,8 +164,8 @@ private void _reload() { protected abstract void reload(); @Override - protected void submit( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, FormException { - super.submit(req,rsp); + protected void submit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException { + super.submit(req, rsp); // make sure to reload to reflect this config change. nextUpdate = 0; } @@ -188,12 +189,12 @@ private ReloadThread() { } private ViewJob getNext() throws InterruptedException { - synchronized(reloadQueue) { + synchronized (reloadQueue) { // reload operations might eat InterruptException, // so check the status every so often - while(reloadQueue.isEmpty() && !terminating()) + while (reloadQueue.isEmpty() && !terminating()) reloadQueue.wait(TimeUnit.MINUTES.toMillis(1)); - if(terminating()) + if (terminating()) throw new InterruptedException(); // terminate now ViewJob job = reloadQueue.iterator().next(); reloadQueue.remove(job); @@ -230,8 +231,8 @@ public void run() { *

    * We then switched to submission via HTTP, so this reloading is no longer necessary, so only do this * when explicitly requested. - * + * */ @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "for script console") - public static boolean reloadPeriodically = SystemProperties.getBoolean(ViewJob.class.getName()+".reloadPeriodically"); + public static boolean reloadPeriodically = SystemProperties.getBoolean(ViewJob.class.getName() + ".reloadPeriodically"); } diff --git a/core/src/main/java/hudson/model/ViewProperty.java b/core/src/main/java/hudson/model/ViewProperty.java index 04d3fc4fd7674..31ad3078d449e 100644 --- a/core/src/main/java/hudson/model/ViewProperty.java +++ b/core/src/main/java/hudson/model/ViewProperty.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import hudson.DescriptorExtensionList; @@ -63,12 +64,12 @@ public ViewPropertyDescriptor getDescriptor() { return (ViewPropertyDescriptor) Jenkins.get().getDescriptorOrDie(getClass()); } - public static DescriptorExtensionList all() { + public static DescriptorExtensionList all() { return Jenkins.get().getDescriptorList(ViewProperty.class); } @Override public ViewProperty reconfigure(StaplerRequest req, JSONObject form) throws Descriptor.FormException { - return form==null ? null : getDescriptor().newInstance(req, form); + return form == null ? null : getDescriptor().newInstance(req, form); } } diff --git a/core/src/main/java/hudson/model/ViewPropertyDescriptor.java b/core/src/main/java/hudson/model/ViewPropertyDescriptor.java index da0e0bbb516c5..a8d9b40082a05 100644 --- a/core/src/main/java/hudson/model/ViewPropertyDescriptor.java +++ b/core/src/main/java/hudson/model/ViewPropertyDescriptor.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; /** diff --git a/core/src/main/java/hudson/model/WorkspaceCleanupThread.java b/core/src/main/java/hudson/model/WorkspaceCleanupThread.java index e73d1976a47cf..00ef65c4a92e9 100644 --- a/core/src/main/java/hudson/model/WorkspaceCleanupThread.java +++ b/core/src/main/java/hudson/model/WorkspaceCleanupThread.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import edu.umd.cs.findbugs.annotations.NonNull; @@ -103,40 +104,40 @@ private boolean shouldBeDeleted(@NonNull TopLevelItem item, FilePath dir, @NonNu // TODO: the use of remoting is not optimal. // One remoting can execute "exists", "lastModified", and "delete" all at once. // (Could even invert master loop so that one FileCallable takes care of all known items.) - if(!dir.exists()) { + if (!dir.exists()) { LOGGER.log(Level.FINE, "Directory {0} does not exist", dir); return false; } // if younger than a month, keep it long now = new Date().getTime(); - if(dir.lastModified() + retainForDays * DAY > now) { - LOGGER.log(Level.FINE, "Directory {0} is only {1} old, so not deleting", new Object[] {dir, Util.getTimeSpanString(now-dir.lastModified())}); + if (dir.lastModified() + retainForDays * DAY > now) { + LOGGER.log(Level.FINE, "Directory {0} is only {1} old, so not deleting", new Object[] {dir, Util.getTimeSpanString(now - dir.lastModified())}); return false; } // TODO could also be good to add checkbox that lets users configure a workspace to never be auto-cleaned. // TODO check instead for SCMTriggerItem: - if (item instanceof AbstractProject) { - AbstractProject p = (AbstractProject) item; + if (item instanceof AbstractProject) { + AbstractProject p = (AbstractProject) item; Node lb = p.getLastBuiltOn(); LOGGER.log(Level.FINER, "Directory {0} is last built on {1}", new Object[] {dir, lb}); - if(lb!=null && lb.equals(n)) { + if (lb != null && lb.equals(n)) { // this is the active workspace. keep it. LOGGER.log(Level.FINE, "Directory {0} is the last workspace for {1}", new Object[] {dir, p}); return false; } - - if(!p.getScm().processWorkspaceBeforeDeletion((Job) p,dir,n)) { + + if (!p.getScm().processWorkspaceBeforeDeletion((Job) p, dir, n)) { LOGGER.log(Level.FINE, "Directory deletion of {0} is vetoed by SCM", dir); return false; } } // TODO this may only check the last build in fact: - if (item instanceof Job) { - Job j = (Job) item; + if (item instanceof Job) { + Job j = (Job) item; if (j.isBuilding()) { LOGGER.log(Level.FINE, "Job {0} is building, so not deleting", item.getFullDisplayName()); return false; @@ -153,16 +154,16 @@ private boolean shouldBeDeleted(@NonNull TopLevelItem item, FilePath dir, @NonNu * Can be used to disable workspace clean up. */ @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "Accessible via System Groovy Scripts") - public static boolean disabled = SystemProperties.getBoolean(WorkspaceCleanupThread.class.getName()+".disabled"); + public static boolean disabled = SystemProperties.getBoolean(WorkspaceCleanupThread.class.getName() + ".disabled"); /** * How often the clean up should run. This is final as Jenkins will not reflect changes anyway. */ - public static final int recurrencePeriodHours = SystemProperties.getInteger(WorkspaceCleanupThread.class.getName()+".recurrencePeriodHours", 24); + public static final int recurrencePeriodHours = SystemProperties.getInteger(WorkspaceCleanupThread.class.getName() + ".recurrencePeriodHours", 24); /** * Number of days workspaces should be retained. */ @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "Accessible via System Groovy Scripts") - public static int retainForDays = SystemProperties.getInteger(WorkspaceCleanupThread.class.getName()+".retainForDays", 30); + public static int retainForDays = SystemProperties.getInteger(WorkspaceCleanupThread.class.getName() + ".retainForDays", 30); } diff --git a/core/src/main/java/hudson/model/WorkspaceListener.java b/core/src/main/java/hudson/model/WorkspaceListener.java index 1fce5b907d177..4a6089164a16b 100644 --- a/core/src/main/java/hudson/model/WorkspaceListener.java +++ b/core/src/main/java/hudson/model/WorkspaceListener.java @@ -5,21 +5,21 @@ import hudson.FilePath; public abstract class WorkspaceListener implements ExtensionPoint { - + /** * Called after a workspace is deleted successfully. */ public void afterDelete(AbstractProject project) { - + } /** * Called before a build uses a workspace. IE, before any SCM checkout. */ public void beforeUse(AbstractBuild b, FilePath workspace, BuildListener listener) { - + } - + /** * All registered {@link WorkspaceListener}s. */ diff --git a/core/src/main/java/hudson/model/labels/LabelAtom.java b/core/src/main/java/hudson/model/labels/LabelAtom.java index cca9b29ed753d..52779eb6fce1e 100644 --- a/core/src/main/java/hudson/model/labels/LabelAtom.java +++ b/core/src/main/java/hudson/model/labels/LabelAtom.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.labels; import com.thoughtworks.xstream.converters.MarshallingContext; @@ -28,6 +29,7 @@ import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import edu.umd.cs.findbugs.annotations.CheckForNull; +import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import hudson.BulkChange; import hudson.CopyOnWrite; @@ -67,7 +69,7 @@ /** * Atomic single token label, like "foo" or "bar". - * + * * @author Kohsuke Kawaguchi * @since 1.372 */ @@ -78,7 +80,7 @@ public class LabelAtom extends Label implements Saveable { private static /* Script Console modifiable */ boolean ALLOW_FOLDER_TRAVERSAL = SystemProperties.getBoolean(LabelAtom.class.getName() + ".allowFolderTraversal"); - private DescribableList properties = + private DescribableList properties = new DescribableList<>(this); @CopyOnWrite @@ -86,7 +88,7 @@ public class LabelAtom extends Label implements Saveable { private String description; - public LabelAtom(String name) { + public LabelAtom(@NonNull String name) { super(name); } @@ -110,6 +112,7 @@ public String getExpression() { * should do so by implementing {@link LabelAtomProperty#getActions(LabelAtom)}. */ @SuppressWarnings("deprecation") + @NonNull @Override public List getActions() { // add all the transient actions, too @@ -162,7 +165,7 @@ public boolean matches(VariableResolver resolver) { @Override public V accept(LabelVisitor visitor, P param) { - return visitor.onAtom(this,param); + return visitor.onAtom(this, param); } @Override @@ -176,7 +179,7 @@ public LabelOperatorPrecedence precedence() { } /*package*/ XmlFile getConfigFile() { - return new XmlFile(XSTREAM, new File(Jenkins.get().root, "labels/"+name+".xml")); + return new XmlFile(XSTREAM, new File(Jenkins.get().root, "labels/" + name + ".xml")); } @Override @@ -184,22 +187,22 @@ public void save() throws IOException { if (isInvalidName()) { throw new IOException("Invalid label"); } - if(BulkChange.contains(this)) return; + if (BulkChange.contains(this)) return; try { getConfigFile().write(this); SaveableListener.fireOnChange(this, getConfigFile()); } catch (IOException e) { - LOGGER.log(Level.WARNING, "Failed to save "+getConfigFile(),e); + LOGGER.log(Level.WARNING, "Failed to save " + getConfigFile(), e); } } public void load() { XmlFile file = getConfigFile(); - if(file.exists()) { + if (file.exists()) { try { file.unmarshal(this); } catch (IOException e) { - LOGGER.log(Level.WARNING, "Failed to load "+file, e); + LOGGER.log(Level.WARNING, "Failed to load " + file, e); } } properties.setOwner(this); @@ -218,7 +221,7 @@ public List getApplicablePropertyDescriptors() { * Accepts the update to the node configuration. */ @POST - public void doConfigSubmit( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, FormException { + public void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException { final Jenkins app = Jenkins.get(); app.checkPermission(Jenkins.ADMINISTER); @@ -246,7 +249,7 @@ private boolean isInvalidName() { */ @RequirePOST @Restricted(DoNotUse.class) - public synchronized void doSubmitDescription( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + public synchronized void doSubmitDescription(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { Jenkins.get().checkPermission(Jenkins.ADMINISTER); setDescription(req.getParameter("description")); @@ -273,9 +276,9 @@ public static boolean needsEscape(String name) { try { Jenkins.checkGoodName(name); // additional restricted chars - for( int i=0; i getActions(LabelAtom atom) { /** * Lists up all the registered {@link LabelAtomPropertyDescriptor}s in the system. */ - public static DescriptorExtensionList all() { + public static DescriptorExtensionList all() { return Jenkins.get().getDescriptorList(LabelAtomProperty.class); } } diff --git a/core/src/main/java/hudson/model/labels/LabelAtomPropertyDescriptor.java b/core/src/main/java/hudson/model/labels/LabelAtomPropertyDescriptor.java index b9b9312939f1c..3c45b2e0a76e4 100644 --- a/core/src/main/java/hudson/model/labels/LabelAtomPropertyDescriptor.java +++ b/core/src/main/java/hudson/model/labels/LabelAtomPropertyDescriptor.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.labels; import hudson.Extension; @@ -31,7 +32,7 @@ * *

    * Put {@link Extension} on your descriptor implementation to have it auto-registered. - * + * *

    * When extending this class, override {@link Descriptor#getDisplayName()}. In the * context of LabelAtomPropertyDescriptor, this function is used to determine the label of diff --git a/core/src/main/java/hudson/model/labels/LabelExpression.java b/core/src/main/java/hudson/model/labels/LabelExpression.java index 00a81c2715557..40a7fc6f80db0 100644 --- a/core/src/main/java/hudson/model/labels/LabelExpression.java +++ b/core/src/main/java/hudson/model/labels/LabelExpression.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.labels; import antlr.ANTLRException; @@ -36,6 +37,7 @@ import hudson.util.FormValidation; import hudson.util.VariableResolver; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Set; import jenkins.model.Jenkins; @@ -44,7 +46,7 @@ /** * Boolean expression of labels. - * + * * @author Kohsuke Kawaguchi * @since 1.372 */ @@ -62,7 +64,7 @@ public static class Not extends LabelExpression { public final Label base; public Not(Label base) { - super('!'+paren(LabelOperatorPrecedence.NOT,base)); + super('!' + paren(LabelOperatorPrecedence.NOT, base)); this.base = base; } @@ -89,7 +91,7 @@ public static class Paren extends LabelExpression { public final Label base; public Paren(Label base) { - super('('+base.getExpression()+')'); + super('(' + base.getExpression() + ')'); this.base = base; } @@ -113,13 +115,13 @@ public LabelOperatorPrecedence precedence() { * Puts the label name into a parenthesis if the given operator will have a higher precedence. */ static String paren(LabelOperatorPrecedence op, Label l) { - if (op.compareTo(l.precedence())<0) - return '('+l.getExpression()+')'; + if (op.compareTo(l.precedence()) < 0) + return '(' + l.getExpression() + ')'; return l.getExpression(); } public abstract static class Binary extends LabelExpression { - public final Label lhs,rhs; + public final Label lhs, rhs; protected Binary(Label lhs, Label rhs, LabelOperatorPrecedence op) { super(combine(lhs, rhs, op)); @@ -128,7 +130,7 @@ protected Binary(Label lhs, Label rhs, LabelOperatorPrecedence op) { } private static String combine(Label lhs, Label rhs, LabelOperatorPrecedence op) { - return paren(op,lhs)+op.str+paren(op,rhs); + return paren(op, lhs) + op.str + paren(op, rhs); } /** @@ -137,7 +139,7 @@ private static String combine(Label lhs, Label rhs, LabelOperatorPrecedence op) */ @Override public boolean matches(VariableResolver resolver) { - return op(lhs.matches(resolver),rhs.matches(resolver)); + return op(lhs.matches(resolver), rhs.matches(resolver)); } protected abstract boolean op(boolean a, boolean b); @@ -285,14 +287,15 @@ public static FormValidation validate(@Nullable String expression, @CheckForNull } final Jenkins j = Jenkins.get(); Label l = j.getLabel(expression); - if (l.isEmpty()) { + if (l == null || l.isEmpty()) { final LabelAtom masterLabel = LabelAtom.get("master"); - if (!masterLabel.equals(Jenkins.get().getSelfLabel()) && l.listAtoms().contains(masterLabel) && masterLabel.isEmpty()) { + final Set labelAtoms = (l == null ? Collections.emptySet() : l.listAtoms()); + if (!masterLabel.equals(Jenkins.get().getSelfLabel()) && labelAtoms.contains(masterLabel) && masterLabel.isEmpty()) { // Show a warning if this expression's lack of nodes and clouds is likely caused by the built-in node name migration. // This can probably be done better (e.g. also when `!l.isEmpty()`), but it's a start. return FormValidation.warningWithMarkup(Messages.LabelExpression_ObsoleteMasterLabel()); } - for (LabelAtom a : l.listAtoms()) { + for (LabelAtom a : labelAtoms) { if (a.isEmpty()) { LabelAtom nearest = LabelAtom.findNearest(a.getName()); return FormValidation.warning(Messages.LabelExpression_NoMatch_DidYouMean(a.getName(), nearest.getDisplayName())); diff --git a/core/src/main/java/hudson/model/labels/LabelOperatorPrecedence.java b/core/src/main/java/hudson/model/labels/LabelOperatorPrecedence.java index a917d97b0563c..b70f0036af76e 100644 --- a/core/src/main/java/hudson/model/labels/LabelOperatorPrecedence.java +++ b/core/src/main/java/hudson/model/labels/LabelOperatorPrecedence.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.labels; /** diff --git a/core/src/main/java/hudson/model/labels/LabelVisitor.java b/core/src/main/java/hudson/model/labels/LabelVisitor.java index fcb2f9b58eab6..0fb8114f32c0c 100644 --- a/core/src/main/java/hudson/model/labels/LabelVisitor.java +++ b/core/src/main/java/hudson/model/labels/LabelVisitor.java @@ -7,7 +7,7 @@ * @see LabelExpression#accept(LabelVisitor, Object) * @since 1.420 */ -public abstract class LabelVisitor { +public abstract class LabelVisitor { public abstract V onAtom(LabelAtom a, P param); public abstract V onParen(LabelExpression.Paren p, P param); diff --git a/core/src/main/java/hudson/model/listeners/ItemListener.java b/core/src/main/java/hudson/model/listeners/ItemListener.java index 13522ef500a65..aef431c3207b4 100644 --- a/core/src/main/java/hudson/model/listeners/ItemListener.java +++ b/core/src/main/java/hudson/model/listeners/ItemListener.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.listeners; import hudson.Extension; @@ -231,7 +232,7 @@ public static void fireLocationChange(final Item rootItem, final String oldFullN } Listeners.notify(ItemListener.class, false, l -> l.onLocationChanged(rootItem, oldFullName, newFullName)); if (rootItem instanceof ItemGroup) { - for (final Item child : Items.allItems2(ACL.SYSTEM2, (ItemGroup)rootItem, Item.class)) { + for (final Item child : Items.allItems2(ACL.SYSTEM2, (ItemGroup) rootItem, Item.class)) { final String childNew = child.getFullName(); assert childNew.startsWith(newFullName); assert childNew.charAt(newFullName.length()) == '/'; diff --git a/core/src/main/java/hudson/model/listeners/RunListener.java b/core/src/main/java/hudson/model/listeners/RunListener.java index 148f419908399..0ecbf725c792d 100644 --- a/core/src/main/java/hudson/model/listeners/RunListener.java +++ b/core/src/main/java/hudson/model/listeners/RunListener.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.listeners; import edu.umd.cs.findbugs.annotations.NonNull; @@ -57,7 +58,7 @@ * *

    * This is an abstract class so that methods added in the future won't break existing listeners. - * + * * @author Kohsuke Kawaguchi * @since 1.145 */ @@ -71,9 +72,9 @@ protected RunListener(Class targetType) { protected RunListener() { Type type = Types.getBaseClass(getClass(), RunListener.class); if (type instanceof ParameterizedType) - targetType = Types.erasure(Types.getTypeArgument(type,0)); + targetType = Types.erasure(Types.getTypeArgument(type, 0)); else - throw new IllegalStateException(getClass()+" uses the raw type for extending RunListener"); + throw new IllegalStateException(getClass() + " uses the raw type for extending RunListener"); } /** @@ -156,8 +157,8 @@ public void onStarted(R r, TaskListener listener) {} * to suppress a stack trace by the receiver. * @since 1.410 */ - public Environment setUpEnvironment( AbstractBuild build, Launcher launcher, BuildListener listener ) throws IOException, InterruptedException, RunnerAbortedException { - return new Environment() {}; + public Environment setUpEnvironment(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException, RunnerAbortedException { + return new Environment() {}; } /** diff --git a/core/src/main/java/hudson/model/listeners/SCMListener.java b/core/src/main/java/hudson/model/listeners/SCMListener.java index 02cd62e34038e..afb93bf2c7ab9 100644 --- a/core/src/main/java/hudson/model/listeners/SCMListener.java +++ b/core/src/main/java/hudson/model/listeners/SCMListener.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.listeners; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -51,7 +52,7 @@ * This is an abstract class so that methods added in the future won't break existing listeners. * *

    - * Once instantiated, use the {@link #register()} method to start receiving events. + * Once instantiated, use the {@link #register()} method to start receiving events. * * @author Kohsuke Kawaguchi * @see jenkins.model.Jenkins#getSCMListeners() @@ -65,7 +66,7 @@ public abstract class SCMListener implements ExtensionPoint { * @throws Exception if the checkout should be considered failed * @since 1.568 */ - public void onCheckout(Run build, SCM scm, FilePath workspace, TaskListener listener, @CheckForNull File changelogFile, @CheckForNull SCMRevisionState pollingBaseline) throws Exception {} + public void onCheckout(Run build, SCM scm, FilePath workspace, TaskListener listener, @CheckForNull File changelogFile, @CheckForNull SCMRevisionState pollingBaseline) throws Exception {} /** * Called once the changelog is determined. @@ -79,7 +80,7 @@ public void onCheckout(Run build, SCM scm, FilePath workspace, TaskListener *

    * If a build failed before we successfully determine changelog, this method * will not be invoked (for example, if "cvs update" failed.) OTOH, this method - * is invoked before the actual build (like ant invocation) happens. + * is invoked before the actual build (like ant invocation) happens. * *

    * This is an opportunity for SCM-related plugins to act on changelog. @@ -105,17 +106,17 @@ public void onCheckout(Run build, SCM scm, FilePath workspace, TaskListener * * @throws Exception * If any exception is thrown from this method, it will be recorded - * and causes the build to fail. + * and causes the build to fail. * @since 1.568 */ - public void onChangeLogParsed(Run build, SCM scm, TaskListener listener, ChangeLogSet changelog) throws Exception { + public void onChangeLogParsed(Run build, SCM scm, TaskListener listener, ChangeLogSet changelog) throws Exception { if (build instanceof AbstractBuild && listener instanceof BuildListener && Util.isOverridden(SCMListener.class, getClass(), "onChangeLogParsed", AbstractBuild.class, BuildListener.class, ChangeLogSet.class)) { onChangeLogParsed((AbstractBuild) build, (BuildListener) listener, changelog); } } @Deprecated - public void onChangeLogParsed(AbstractBuild build, BuildListener listener, ChangeLogSet changelog) throws Exception { + public void onChangeLogParsed(AbstractBuild build, BuildListener listener, ChangeLogSet changelog) throws Exception { if (Util.isOverridden(SCMListener.class, getClass(), "onChangeLogParsed", Run.class, SCM.class, TaskListener.class, ChangeLogSet.class)) { onChangeLogParsed(build, build.getProject().getScm(), listener, changelog); } diff --git a/core/src/main/java/hudson/model/listeners/SCMPollListener.java b/core/src/main/java/hudson/model/listeners/SCMPollListener.java index 48fa919117909..341f91ac79b88 100644 --- a/core/src/main/java/hudson/model/listeners/SCMPollListener.java +++ b/core/src/main/java/hudson/model/listeners/SCMPollListener.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.listeners; import hudson.ExtensionList; @@ -48,7 +49,7 @@ public abstract class SCMPollListener implements ExtensionPoint { * Connected to the polling log. */ // TODO switch to Job - public void onBeforePolling( AbstractProject project, TaskListener listener ) {} + public void onBeforePolling(AbstractProject project, TaskListener listener) {} /** * Called when the polling successfully concluded. @@ -56,7 +57,7 @@ public void onBeforePolling( AbstractProject project, TaskListener listene * @param result * The result of the polling. */ - public void onPollingSuccess( AbstractProject project, TaskListener listener, PollingResult result) {} + public void onPollingSuccess(AbstractProject project, TaskListener listener, PollingResult result) {} /** * Called when the polling concluded with an error. @@ -65,24 +66,24 @@ public void onPollingSuccess( AbstractProject project, TaskListener listen * The problem reported. This can include {@link InterruptedException} (that corresponds to the user cancelling it), * some anticipated problems like {@link IOException}, or bug in the code ({@link RuntimeException}) */ - public void onPollingFailed( AbstractProject project, TaskListener listener, Throwable exception) {} + public void onPollingFailed(AbstractProject project, TaskListener listener, Throwable exception) {} - public static void fireBeforePolling( AbstractProject project, TaskListener listener ) { + public static void fireBeforePolling(AbstractProject project, TaskListener listener) { Listeners.notify(SCMPollListener.class, true, l -> l.onBeforePolling(project, listener)); } - public static void firePollingSuccess( AbstractProject project, TaskListener listener, PollingResult result ) { + public static void firePollingSuccess(AbstractProject project, TaskListener listener, PollingResult result) { Listeners.notify(SCMPollListener.class, true, l -> l.onPollingSuccess(project, listener, result)); - } + } - public static void firePollingFailed( AbstractProject project, TaskListener listener, Throwable exception ) { + public static void firePollingFailed(AbstractProject project, TaskListener listener, Throwable exception) { Listeners.notify(SCMPollListener.class, true, l -> l.onPollingFailed(project, listener, exception)); - } + } - /** - * Returns all the registered {@link SCMPollListener}s. - */ - public static ExtensionList all() { - return ExtensionList.lookup( SCMPollListener.class ); - } + /** + * Returns all the registered {@link SCMPollListener}s. + */ + public static ExtensionList all() { + return ExtensionList.lookup(SCMPollListener.class); + } } diff --git a/core/src/main/java/hudson/model/listeners/SaveableListener.java b/core/src/main/java/hudson/model/listeners/SaveableListener.java index 5df4f298284d8..51cac4861a578 100644 --- a/core/src/main/java/hudson/model/listeners/SaveableListener.java +++ b/core/src/main/java/hudson/model/listeners/SaveableListener.java @@ -1,19 +1,19 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Tom Huybrechts, * Andrew Bayer - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.listeners; import hudson.Extension; @@ -78,7 +79,7 @@ public void unregister() { public static void fireOnChange(Saveable o, XmlFile file) { for (SaveableListener l : all()) { try { - l.onChange(o,file); + l.onChange(o, file); } catch (ThreadDeath t) { throw t; } catch (Throwable t) { diff --git a/core/src/main/java/hudson/model/queue/AbstractQueueSorterImpl.java b/core/src/main/java/hudson/model/queue/AbstractQueueSorterImpl.java index 486bd4c96b3a9..99ac92828bb5e 100644 --- a/core/src/main/java/hudson/model/queue/AbstractQueueSorterImpl.java +++ b/core/src/main/java/hudson/model/queue/AbstractQueueSorterImpl.java @@ -31,7 +31,7 @@ public void sortBuildableItems(List buildables) { */ @Override public int compare(BuildableItem lhs, BuildableItem rhs) { - return Long.compare(lhs.buildableStartMilliseconds,rhs.buildableStartMilliseconds); + return Long.compare(lhs.buildableStartMilliseconds, rhs.buildableStartMilliseconds); } /** diff --git a/core/src/main/java/hudson/model/queue/AbstractSubTask.java b/core/src/main/java/hudson/model/queue/AbstractSubTask.java index b8de10e02ce1e..8888eaab72c93 100644 --- a/core/src/main/java/hudson/model/queue/AbstractSubTask.java +++ b/core/src/main/java/hudson/model/queue/AbstractSubTask.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.queue; /** diff --git a/core/src/main/java/hudson/model/queue/BackFiller.java b/core/src/main/java/hudson/model/queue/BackFiller.java deleted file mode 100644 index ec59903ea51b3..0000000000000 --- a/core/src/main/java/hudson/model/queue/BackFiller.java +++ /dev/null @@ -1,209 +0,0 @@ -package hudson.model.queue; - -import hudson.Extension; -import hudson.model.Computer; -import hudson.model.Executor; -import hudson.model.InvisibleAction; -import hudson.model.Queue.BuildableItem; -import hudson.model.queue.MappingWorksheet.ExecutorChunk; -import hudson.model.queue.MappingWorksheet.ExecutorSlot; -import hudson.model.queue.MappingWorksheet.Mapping; -import hudson.model.queue.MappingWorksheet.WorkChunk; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.stream.StreamSupport; -import jenkins.model.Jenkins; -import jenkins.util.SystemProperties; - -/** - * Experimental. - * - * @author Kohsuke Kawaguchi - */ -public class BackFiller extends LoadPredictor { - private boolean recursion = false; - - @Override - public Iterable predict(MappingWorksheet plan, Computer computer, long start, long end) { - TimeRange timeRange = new TimeRange(start, end - start); - List loads = new ArrayList<>(); - - for (BuildableItem bi : Jenkins.get().getQueue().getBuildableItems()) { - TentativePlan tp = bi.getAction(TentativePlan.class); - if (tp==null) {// do this even for bi==plan.item ensures that we have FIFO semantics in tentative plans. - tp = makeTentativePlan(bi); - if (tp==null) continue; // no viable plan. - } - - if (tp.isStale()) { - // if the tentative plan is stale, just keep on pushing it to the current time - // (if we recreate the plan, it'll be put at the end of the queue, whereas this job - // should actually get priority over others) - tp.range.shiftTo(System.currentTimeMillis()); - } - - // don't let its own tentative plan count when considering a scheduling for a job - if (plan.item==bi) continue; - - - // no overlap in the time span, meaning this plan is for a distant future - if (!timeRange.overlapsWith(tp.range)) continue; - - // if this tentative plan has no baring on this computer, that's ignorable - Integer i = tp.footprint.get(computer); - if (i==null) continue; - - return Collections.singleton(tp.range.toFutureLoad(i)); - } - - return loads; - } - - private static final class PseudoExecutorSlot extends ExecutorSlot { - private Executor executor; - - private PseudoExecutorSlot(Executor executor) { - this.executor = executor; - } - - @Override - public Executor getExecutor() { - return executor; - } - - @Override - public boolean isAvailable() { - return true; - } - - // this slot isn't executable - @Override - protected void set(WorkUnit p) { - throw new UnsupportedOperationException(); - } - } - - private TentativePlan makeTentativePlan(BuildableItem bi) { - if (recursion) return null; - recursion = true; - try { - // pretend for now that all executors are available and decide some assignment that's executable. - List slots = new ArrayList<>(); - for (Computer c : Jenkins.get().getComputers()) { - if (c.isOffline()) continue; - for (Executor e : c.getExecutors()) { - slots.add(new PseudoExecutorSlot(e)); - } - } - - // also ignore all load predictions as we just want to figure out some executable assignment - // and we are not trying to figure out if this task is executable right now. - MappingWorksheet worksheet = new MappingWorksheet(bi, slots, Collections.emptyList()); - Mapping m = Jenkins.get().getQueue().getLoadBalancer().map(bi.task, worksheet); - if (m==null) return null; - - // figure out how many executors we need on each computer? - Map footprint = new HashMap<>(); - for (Map.Entry e : m.toMap().entrySet()) { - Computer c = e.getValue().computer; - Integer v = footprint.get(c); - if (v==null) v = 0; - v += e.getKey().size(); - footprint.put(c,v); - } - - // the point of a tentative plan is to displace other jobs to create a point in time - // where this task can start executing. An incorrectly estimated duration is not - // a problem in this regard, as we just need enough idle executors in the right moment. - // The downside of guessing the duration wrong is that we can end up creating tentative plans - // afterward that may be incorrect, but those plans will be rebuilt. - long d = bi.task.getEstimatedDuration(); - if (d<=0) d = TimeUnit.MINUTES.toMillis(5); - - TimeRange slot = new TimeRange(System.currentTimeMillis(), d); - - // now, based on the real predicted loads, figure out the approximation of when we can - // start executing this guy. - for (Map.Entry e : footprint.entrySet()) { - Computer computer = e.getKey(); - Timeline timeline = new Timeline(); - for (LoadPredictor lp : LoadPredictor.all()) { - StreamSupport.stream(lp.predict(worksheet, computer, slot.start, slot.end).spliterator(), false).limit(100).forEach(fl -> - timeline.insert(fl.startTime, fl.startTime + fl.duration, fl.numExecutors)); - } - - Long x = timeline.fit(slot.start, slot.duration, computer.countExecutors()-e.getValue()); - // if no suitable range was found in [slot.start,slot.end), slot.end would be a good approximation - if (x==null) x = slot.end; - slot = slot.shiftTo(x); - } - - TentativePlan tp = new TentativePlan(footprint, slot); - bi.addAction(tp); - return tp; - } finally { - recursion = false; - } - } - - /** - * Represents a duration in time. - */ - private static final class TimeRange { - public final long start; - public final long duration; - public final long end; - - private TimeRange(long start, long duration) { - this.start = start; - this.duration = duration; - this.end = start+duration; - } - - public boolean overlapsWith(TimeRange that) { - return (this.start <= that.start && that.start <=this.end) - || (that.start <= this.start && this.start <=that.end); - } - - public FutureLoad toFutureLoad(int size) { - return new FutureLoad(start,duration,size); - } - - public TimeRange shiftTo(long newStart) { - if (newStart==start) return this; - return new TimeRange(newStart,duration); - } - } - - public static final class TentativePlan extends InvisibleAction { - private final Map footprint; - public final TimeRange range; - - public TentativePlan(Map footprint, TimeRange range) { - this.footprint = footprint; - this.range = range; - } - - public Object writeReplace() {// don't persist - return null; - } - - public boolean isStale() { - return range.end < System.currentTimeMillis(); - } - } - - /** - * Once this feature stabilizes, move it to the heavyjob plugin - */ - @Extension - public static BackFiller newInstance() { - if (SystemProperties.getBoolean(BackFiller.class.getName())) - return new BackFiller(); - return null; - } -} diff --git a/core/src/main/java/hudson/model/queue/CauseOfBlockage.java b/core/src/main/java/hudson/model/queue/CauseOfBlockage.java index 9aad22d4ddc64..a991948830851 100644 --- a/core/src/main/java/hudson/model/queue/CauseOfBlockage.java +++ b/core/src/main/java/hudson/model/queue/CauseOfBlockage.java @@ -102,7 +102,7 @@ public String getShortDescription() { String name = node.toComputer() != null ? node.toComputer().getDisplayName() : node.getDisplayName(); return Messages.Queue_NodeOffline(name); } - + @Override public void print(TaskListener listener) { listener.getLogger().println( @@ -182,7 +182,7 @@ public String getShortDescription() { String name = node.toComputer() != null ? node.toComputer().getDisplayName() : node.getDisplayName(); return Messages.Queue_WaitingForNextAvailableExecutorOn(name); } - + @Override public void print(TaskListener listener) { listener.getLogger().println(Messages.Queue_WaitingForNextAvailableExecutorOn(ModelHyperlinkNote.encodeTo(node))); diff --git a/core/src/main/java/hudson/model/queue/Executables.java b/core/src/main/java/hudson/model/queue/Executables.java index 3da70ed2aab4c..396133fe4d336 100644 --- a/core/src/main/java/hudson/model/queue/Executables.java +++ b/core/src/main/java/hudson/model/queue/Executables.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.queue; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -35,13 +36,13 @@ * @author Kohsuke Kawaguchi */ public class Executables { - + /** * Due to the return type change in {@link Executable} in 1.377, the caller needs a special precaution now. * @param e Executable * @return Discovered subtask */ - public static @NonNull SubTask getParentOf(@NonNull Executable e) + public static @NonNull SubTask getParentOf(@NonNull Executable e) throws Error, RuntimeException { try { return e.getParent(); @@ -51,13 +52,13 @@ public class Executables { m.setAccessible(true); return (SubTask) m.invoke(e); } catch (IllegalAccessException x) { - throw (Error)new IllegalAccessError().initCause(x); + throw (Error) new IllegalAccessError().initCause(x); } catch (NoSuchMethodException x) { - throw (Error)new NoSuchMethodError().initCause(x); + throw (Error) new NoSuchMethodError().initCause(x); } catch (InvocationTargetException x) { Throwable y = x.getTargetException(); - if (y instanceof Error) throw (Error)y; - if (y instanceof RuntimeException) throw (RuntimeException)y; + if (y instanceof Error) throw (Error) y; + if (y instanceof RuntimeException) throw (RuntimeException) y; throw new Error(x); } } diff --git a/core/src/main/java/hudson/model/queue/FoldableAction.java b/core/src/main/java/hudson/model/queue/FoldableAction.java index dff6a610a283b..4b368a2b9d15d 100644 --- a/core/src/main/java/hudson/model/queue/FoldableAction.java +++ b/core/src/main/java/hudson/model/queue/FoldableAction.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.queue; import hudson.model.Action; diff --git a/core/src/main/java/hudson/model/queue/FutureImpl.java b/core/src/main/java/hudson/model/queue/FutureImpl.java index 6009b2fe700ce..f6bba013f2cc4 100644 --- a/core/src/main/java/hudson/model/queue/FutureImpl.java +++ b/core/src/main/java/hudson/model/queue/FutureImpl.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.queue; import edu.umd.cs.findbugs.annotations.NonNull; @@ -73,8 +74,8 @@ public Executable waitForStart() throws InterruptedException, ExecutionException public boolean cancel(boolean mayInterruptIfRunning) { Queue q = Jenkins.get().getQueue(); synchronized (this) { - if(!executors.isEmpty()) { - if(mayInterruptIfRunning) + if (!executors.isEmpty()) { + if (mayInterruptIfRunning) for (Executor e : executors) e.interrupt(); return mayInterruptIfRunning; diff --git a/core/src/main/java/hudson/model/queue/FutureLoad.java b/core/src/main/java/hudson/model/queue/FutureLoad.java index a46ef6f223294..1d3046d09288c 100644 --- a/core/src/main/java/hudson/model/queue/FutureLoad.java +++ b/core/src/main/java/hudson/model/queue/FutureLoad.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.queue; /** @@ -51,6 +52,6 @@ public FutureLoad(long startTime, long duration, int numExecutors) { @Override public String toString() { - return "startTime="+startTime+",#executors="+numExecutors+",duration="+duration; + return "startTime=" + startTime + ",#executors=" + numExecutors + ",duration=" + duration; } } diff --git a/core/src/main/java/hudson/model/queue/Latch.java b/core/src/main/java/hudson/model/queue/Latch.java index c8b3619589405..3479c0599c387 100644 --- a/core/src/main/java/hudson/model/queue/Latch.java +++ b/core/src/main/java/hudson/model/queue/Latch.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.queue; import hudson.AbortException; @@ -36,7 +37,7 @@ */ class Latch { private final int n; - private int i=0; + private int i = 0; /** * If the synchronization on the latch is aborted/interrupted, * point to the stack trace where that happened. If null, @@ -55,7 +56,7 @@ class Latch { public synchronized void abort(Throwable cause) { interrupted = new AbortException(); - if (cause!=null) + if (cause != null) interrupted.initCause(cause); notifyAll(); } @@ -79,15 +80,15 @@ public synchronized void synchronize() throws InterruptedException { throw e; } - check(n*2); + check(n * 2); } private void check(int threshold) throws InterruptedException { i++; - if (i==threshold) { + if (i == threshold) { notifyAll(); } else { - while (i predict(MappingWorksheet plan, Computer computer, long start, long end) { // maintain backward compatibility by calling the old signature. - return predict(computer,start,end); + return predict(computer, start, end); } /** @@ -96,9 +97,9 @@ public Iterable predict(MappingWorksheet plan, final Computer comput if (e.isIdle()) continue; long eta = e.getEstimatedRemainingTimeMillis(); - long end = eta<0 ? eternity : now + eta; // when does this task end? + long end = eta < 0 ? eternity : now + eta; // when does this task end? if (end < start) continue; // should be over by the 'start' time. - fl.add(new FutureLoad(start, end-start, 1)); + fl.add(new FutureLoad(start, end - start, 1)); } return fl; } diff --git a/core/src/main/java/hudson/model/queue/MappingWorksheet.java b/core/src/main/java/hudson/model/queue/MappingWorksheet.java index 02492a81f6756..54829ec0dac20 100644 --- a/core/src/main/java/hudson/model/queue/MappingWorksheet.java +++ b/core/src/main/java/hudson/model/queue/MappingWorksheet.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.queue; import static java.lang.Math.max; @@ -128,10 +129,10 @@ private ExecutorChunk(List base, int index) { * Is this executor chunk and the given work chunk compatible? Can the latter be run on the former? */ public boolean canAccept(WorkChunk c) { - if (this.size() base, int index) { Node lbo = base.get(0).getLastBuiltOn(); for (ExecutorChunk ec : executors) { - if (ec.node==lbo) { + if (ec.node == lbo) { lastBuiltOn = ec; return; } @@ -206,7 +207,7 @@ private WorkChunk(List base, int index) { private Label getAssignedLabel(SubTask task) { for (LabelAssignmentAction laa : item.getActions(LabelAssignmentAction.class)) { Label l = laa.getAssignedLabel(task); - if (l!=null) return l; + if (l != null) return l; } return task.getAssignedLabel(); } @@ -263,10 +264,10 @@ public int size() { /** * Returns the assignment as a map. */ - public Map toMap() { - Map r = new HashMap<>(); - for (int i=0; i toMap() { + Map r = new HashMap<>(); + for (int i = 0; i < size(); i++) + r.put(get(i), assigned(i)); return r; } @@ -275,9 +276,9 @@ public Map toMap() { */ public boolean isPartiallyValid() { int[] used = new int[executors.size()]; - for (int i=0; i ec.capacity()) @@ -291,7 +292,7 @@ public boolean isPartiallyValid() { */ public boolean isCompletelyValid() { for (ExecutorChunk ec : mapping) - if (ec==null) return false; // unassigned + if (ec == null) return false; // unassigned return isPartiallyValid(); } @@ -303,27 +304,27 @@ public void execute(WorkUnitContext wuc) { if (!isCompletelyValid()) throw new IllegalStateException(); - for (int i=0; i offers) { - this(item,offers,LoadPredictor.all()); + this(item, offers, LoadPredictor.all()); } public MappingWorksheet(BuildableItem item, List offers, Collection loadPredictors) { this.item = item; - + // group executors by their computers - Map> j = new HashMap<>(); + Map> j = new HashMap<>(); for (ExecutorSlot o : offers) { Computer c = o.getExecutor().getOwner(); List l = j.computeIfAbsent(c, k -> new ArrayList<>()); l.add(o); } - {// take load prediction into account and reduce the available executor pool size accordingly + { // take load prediction into account and reduce the available executor pool size accordingly long duration = item.task.getEstimatedDuration(); if (duration > 0) { long now = System.currentTimeMillis(); @@ -336,20 +337,20 @@ public MappingWorksheet(BuildableItem item, List offers, int peak = 0; OUTER: for (LoadPredictor lp : loadPredictors) { - for (FutureLoad fl : Iterables.limit(lp.predict(this,e.getKey(), now, now + duration),100)) { - peak = max(peak,timeline.insert(fl.startTime, fl.startTime+fl.duration, fl.numExecutors)); - if (peak>=max) break OUTER; + for (FutureLoad fl : Iterables.limit(lp.predict(this, e.getKey(), now, now + duration), 100)) { + peak = max(peak, timeline.insert(fl.startTime, fl.startTime + fl.duration, fl.numExecutors)); + if (peak >= max) break OUTER; } } - int minIdle = max-peak; // minimum number of idle nodes during this time period + int minIdle = max - peak; // minimum number of idle nodes during this time period // total predicted load could exceed available executors [JENKINS-8882] - if (minIdle<0) { + if (minIdle < 0) { // Should we toss a warning/info message? minIdle = 0; } - if (minIdle offers, for (List group : j.values()) { if (group.isEmpty()) continue; // evict empty group ExecutorChunk ec = new ExecutorChunk(group, executors.size()); - if (ec.node==null) continue; // evict out of sync node + if (ec.node == null) continue; // evict out of sync node executors.add(ec); } this.executors = Collections.unmodifiableList(executors); // group execution units into chunks. use of LinkedHashMap ensures that the main work comes at the top - Map> m = new LinkedHashMap<>(); + Map> m = new LinkedHashMap<>(); for (SubTask meu : item.task.getSubTasks()) { Object c = meu.getSameNodeConstraint(); - if (c==null) c = new Object(); + if (c == null) c = new Object(); List l = m.computeIfAbsent(c, k -> new ArrayList<>()); l.add(meu); @@ -377,7 +378,7 @@ public MappingWorksheet(BuildableItem item, List offers, // build into the final shape List works = new ArrayList<>(); for (List group : m.values()) { - works.add(new WorkChunk(group,works.size())); + works.add(new WorkChunk(group, works.size())); } this.works = Collections.unmodifiableList(works); } diff --git a/core/src/main/java/hudson/model/queue/QueueSorter.java b/core/src/main/java/hudson/model/queue/QueueSorter.java index a6cd487a767c1..939d1c6fdff5a 100644 --- a/core/src/main/java/hudson/model/queue/QueueSorter.java +++ b/core/src/main/java/hudson/model/queue/QueueSorter.java @@ -62,17 +62,17 @@ public static ExtensionList all() { * * {@link Queue#Queue(LoadBalancer)} is too early to do this */ - @Initializer(after=JOB_CONFIG_ADAPTED) + @Initializer(after = JOB_CONFIG_ADAPTED) public static void installDefaultQueueSorter() { ExtensionList all = all(); if (all.isEmpty()) return; Queue q = Jenkins.get().getQueue(); - if (q.getSorter()!=null) return; // someone has already installed something. leave that alone. + if (q.getSorter() != null) return; // someone has already installed something. leave that alone. q.setSorter(all.get(0)); - if (all.size()>1) - LOGGER.warning("Multiple QueueSorters are registered. Only the first one is used and the rest are ignored: "+all); + if (all.size() > 1) + LOGGER.warning("Multiple QueueSorters are registered. Only the first one is used and the rest are ignored: " + all); } private static final Logger LOGGER = Logger.getLogger(QueueSorter.class.getName()); diff --git a/core/src/main/java/hudson/model/queue/QueueTaskDispatcher.java b/core/src/main/java/hudson/model/queue/QueueTaskDispatcher.java index eaa0ec18f34ba..9b51bedb36a8d 100644 --- a/core/src/main/java/hudson/model/queue/QueueTaskDispatcher.java +++ b/core/src/main/java/hudson/model/queue/QueueTaskDispatcher.java @@ -98,7 +98,7 @@ public abstract class QueueTaskDispatcher implements ExtensionPoint { * @since 1.413 */ public @CheckForNull CauseOfBlockage canTake(Node node, BuildableItem item) { - return canTake(node,item.task); // backward compatible behaviour + return canTake(node, item.task); // backward compatible behaviour } /** diff --git a/core/src/main/java/hudson/model/queue/ScheduleResult.java b/core/src/main/java/hudson/model/queue/ScheduleResult.java index 91ef54ddb17a9..ed43b651917e1 100644 --- a/core/src/main/java/hudson/model/queue/ScheduleResult.java +++ b/core/src/main/java/hudson/model/queue/ScheduleResult.java @@ -58,6 +58,7 @@ public final boolean isAccepted() { public static final class Created extends ScheduleResult { private final WaitingItem item; + private Created(WaitingItem item) { this.item = item; } diff --git a/core/src/main/java/hudson/model/queue/SubTask.java b/core/src/main/java/hudson/model/queue/SubTask.java index 80d4528efcc36..98c9e0bacbafe 100644 --- a/core/src/main/java/hudson/model/queue/SubTask.java +++ b/core/src/main/java/hudson/model/queue/SubTask.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.queue; import edu.umd.cs.findbugs.annotations.CheckForNull; diff --git a/core/src/main/java/hudson/model/queue/SubTaskContributor.java b/core/src/main/java/hudson/model/queue/SubTaskContributor.java index ccd92ec79a45b..72bfb80a397a4 100644 --- a/core/src/main/java/hudson/model/queue/SubTaskContributor.java +++ b/core/src/main/java/hudson/model/queue/SubTaskContributor.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.queue; import hudson.Extension; @@ -40,7 +41,7 @@ * @since 1.377 */ public abstract class SubTaskContributor implements ExtensionPoint { - public Collection forProject(AbstractProject p) { + public Collection forProject(AbstractProject p) { return Collections.emptyList(); } diff --git a/core/src/main/java/hudson/model/queue/Tasks.java b/core/src/main/java/hudson/model/queue/Tasks.java index 5fdadcfb2f746..fe007200f1b4f 100644 --- a/core/src/main/java/hudson/model/queue/Tasks.java +++ b/core/src/main/java/hudson/model/queue/Tasks.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.queue; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -76,7 +77,7 @@ public static hudson.model.Item getItemOf(@NonNull SubTask t) { } p = o; } - return p instanceof hudson.model.Item ? (hudson.model.Item)p : null; + return p instanceof hudson.model.Item ? (hudson.model.Item) p : null; } /** @deprecated call {@link Queue.Task#getDefaultAuthentication()} directly */ diff --git a/core/src/main/java/hudson/model/queue/Timeline.java b/core/src/main/java/hudson/model/queue/Timeline.java index 1d70c03e26de1..ee7c4d54deef2 100644 --- a/core/src/main/java/hudson/model/queue/Timeline.java +++ b/core/src/main/java/hudson/model/queue/Timeline.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.queue; import static java.lang.Math.max; @@ -44,7 +45,7 @@ final class Timeline { * Obtains q(t) for the given t. */ private int at(long t) { - SortedMap head = data.subMap(t,Long.MAX_VALUE); + SortedMap head = data.subMap(t, Long.MAX_VALUE); if (head.isEmpty()) return 0; return data.get(head.firstKey())[0]; } @@ -105,15 +106,15 @@ Long fit(long start, long duration, int n) { long t = start; // check if 'start' satisfies the two conditions by moving t across [start,start+duration) while (t - start < duration) { - if (at(t)>n) { + if (at(t) > n) { // value too big. what's the next t that's worth trying? Long nxt = next(t); - if (nxt==null) return null; + if (nxt == null) return null; start = nxt; continue OUTER; } else { Long nxt = next(t); - if (nxt==null) t = Long.MAX_VALUE; + if (nxt == null) t = Long.MAX_VALUE; else t = nxt; } } diff --git a/core/src/main/java/hudson/model/queue/WorkUnit.java b/core/src/main/java/hudson/model/queue/WorkUnit.java index 8aed254e31eeb..8c2924b49ba5c 100644 --- a/core/src/main/java/hudson/model/queue/WorkUnit.java +++ b/core/src/main/java/hudson/model/queue/WorkUnit.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.queue; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -98,14 +99,14 @@ public void setExecutable(Executable executable) { * represented by {@link Task} itself. */ public boolean isMainWork() { - return context.task==work; + return context.task == work; } @Override public String toString() { - if (work==context.task) - return super.toString()+"[work="+context.task.getFullDisplayName()+"]"; + if (work == context.task) + return super.toString() + "[work=" + context.task.getFullDisplayName() + "]"; else - return super.toString()+"[work="+work+",context.task="+context.task.getFullDisplayName()+"]"; + return super.toString() + "[work=" + work + ",context.task=" + context.task.getFullDisplayName() + "]"; } } diff --git a/core/src/main/java/hudson/model/queue/WorkUnitContext.java b/core/src/main/java/hudson/model/queue/WorkUnitContext.java index 1b534855270f2..31829ba7dd1f2 100644 --- a/core/src/main/java/hudson/model/queue/WorkUnitContext.java +++ b/core/src/main/java/hudson/model/queue/WorkUnitContext.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.queue; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -74,7 +75,7 @@ public final class WorkUnitContext { public WorkUnitContext(BuildableItem item) { this.item = item; this.task = item.task; - this.future = (FutureImpl)item.getFuture(); + this.future = (FutureImpl) item.getFuture(); // JENKINS-51584 do not use item.getAllActions() here. this.actions = new ArrayList<>(item.getActions()); // +1 for the main task @@ -88,7 +89,7 @@ protected void onCriteriaMet() { // Unclear if this will work with AsynchronousExecution; it *seems* this is only called from synchronize which is only called from synchronizeStart which is only called from an executor thread. Executor e = Executor.currentExecutor(); if (e.getCurrentWorkUnit().isMainWork()) { - e.getOwner().taskAccepted(e,task); + e.getOwner().taskAccepted(e, task); for (ExecutorListener listener : ExtensionList.lookup(ExecutorListener.class)) { try { listener.taskAccepted(e, task); @@ -160,7 +161,7 @@ public void synchronizeEnd(Queue.Executable executable, Throwable problems, long */ @Restricted(NoExternalUse.class) public void synchronizeEnd(Executor e, Queue.Executable executable, Throwable problems, long duration) throws InterruptedException { - // Let code waiting for the build to finish (future.get()) finishes when there is a faulty SubTask by setting + // Let code waiting for the build to finish (future.get()) finishes when there is a faulty SubTask by setting // the future always. try { endLatch.synchronize(); @@ -197,8 +198,8 @@ public void synchronizeEnd(Executor e, Queue.Executable executable, Throwable pr * When one of the work unit is aborted, call this method to abort all the other work units. */ public synchronized void abort(Throwable cause) { - if (cause==null) throw new IllegalArgumentException(); - if (aborted!=null) return; // already aborted + if (cause == null) throw new IllegalArgumentException(); + if (aborted != null) return; // already aborted aborted = cause; startLatch.abort(cause); endLatch.abort(cause); @@ -206,7 +207,7 @@ public synchronized void abort(Throwable cause) { Thread c = Thread.currentThread(); for (WorkUnit wu : workUnits) { Executor e = wu.getExecutor(); - if (e!=null && e!=c) + if (e != null && e != c) e.interrupt(); } } diff --git a/core/src/main/java/hudson/node_monitors/AbstractAsyncNodeMonitorDescriptor.java b/core/src/main/java/hudson/node_monitors/AbstractAsyncNodeMonitorDescriptor.java index 842c9bed0ea76..8e46a37057187 100644 --- a/core/src/main/java/hudson/node_monitors/AbstractAsyncNodeMonitorDescriptor.java +++ b/core/src/main/java/hudson/node_monitors/AbstractAsyncNodeMonitorDescriptor.java @@ -51,14 +51,14 @@ protected AbstractAsyncNodeMonitorDescriptor(Class clazz, /** * Creates a {@link Callable} that performs the monitoring when executed. */ - protected abstract @CheckForNull Callable createCallable(Computer c); + protected abstract @CheckForNull Callable createCallable(Computer c); @Override protected T monitor(Computer c) throws IOException, InterruptedException { VirtualChannel ch = c.getChannel(); if (ch != null) { - Callable cc = createCallable(c); - if (cc!=null) + Callable cc = createCallable(c); + if (cc != null) return ch.call(cc); } return null; @@ -80,17 +80,17 @@ protected Map monitor() throws InterruptedException { * Perform monitoring with detailed reporting. */ protected final @NonNull Result monitorDetailed() throws InterruptedException { - Map> futures = new HashMap<>(); + Map> futures = new HashMap<>(); Set skipped = new HashSet<>(); for (Computer c : Jenkins.get().getComputers()) { try { VirtualChannel ch = c.getChannel(); - futures.put(c,null); // sentinel value - if (ch!=null) { + futures.put(c, null); // sentinel value + if (ch != null) { Callable cc = createCallable(c); - if (cc!=null) - futures.put(c,ch.callAsync(cc)); + if (cc != null) + futures.put(c, ch.callAsync(cc)); } } catch (RuntimeException | IOException e) { error(c, e); @@ -100,16 +100,16 @@ protected Map monitor() throws InterruptedException { final long now = System.currentTimeMillis(); final long end = now + getMonitoringTimeOut(); - final Map data = new HashMap<>(); + final Map data = new HashMap<>(); for (Map.Entry> e : futures.entrySet()) { Computer c = e.getKey(); Future f = futures.get(c); data.put(c, null); // sentinel value - if (f!=null) { + if (f != null) { try { - data.put(c,f.get(Math.max(0,end-System.currentTimeMillis()), MILLISECONDS)); + data.put(c, f.get(Math.max(0, end - System.currentTimeMillis()), MILLISECONDS)); } catch (RuntimeException | TimeoutException | ExecutionException x) { error(c, x); } diff --git a/core/src/main/java/hudson/node_monitors/AbstractDiskSpaceMonitor.java b/core/src/main/java/hudson/node_monitors/AbstractDiskSpaceMonitor.java index dce9ca3e14e1d..38230dd80f915 100644 --- a/core/src/main/java/hudson/node_monitors/AbstractDiskSpaceMonitor.java +++ b/core/src/main/java/hudson/node_monitors/AbstractDiskSpaceMonitor.java @@ -28,7 +28,7 @@ protected AbstractDiskSpaceMonitor() { } public long getThresholdBytes() { - if (freeSpaceThreshold==null) + if (freeSpaceThreshold == null) return DEFAULT_THRESHOLD; // backward compatibility with the data format that didn't have 'freeSpaceThreshold' try { return DiskSpace.parse(freeSpaceThreshold).size; @@ -39,12 +39,12 @@ public long getThresholdBytes() { @Override public Object data(Computer c) { - DiskSpace size = markNodeOfflineIfDiskspaceIsTooLow(c); - - // mark online (again), if free space is over threshold - if(size!=null && size.size > getThresholdBytes() && c.isOffline() && c.getOfflineCause() instanceof DiskSpace) - if(this.getClass().equals(((DiskSpace)c.getOfflineCause()).getTrigger())) - if(getDescriptor().markOnline(c)) { + DiskSpace size = markNodeOfflineIfDiskspaceIsTooLow(c); + + // mark online (again), if free space is over threshold + if (size != null && size.size > getThresholdBytes() && c.isOffline() && c.getOfflineCause() instanceof DiskSpace) + if (this.getClass().equals(((DiskSpace) c.getOfflineCause()).getTrigger())) + if (getDescriptor().markOnline(c)) { LOGGER.info(Messages.DiskSpaceMonitor_MarkedOnline(c.getDisplayName())); } return size; @@ -59,15 +59,15 @@ public Object data(Computer c) { @Restricted(NoExternalUse.class) public DiskSpace markNodeOfflineIfDiskspaceIsTooLow(Computer c) { DiskSpace size = (DiskSpace) super.data(c); - if(size!=null && size.size < getThresholdBytes()) { - size.setTriggered(this.getClass(), true); - if(getDescriptor().markOffline(c,size)) { - LOGGER.warning(Messages.DiskSpaceMonitor_MarkedOffline(c.getDisplayName())); - } + if (size != null && size.size < getThresholdBytes()) { + size.setTriggered(this.getClass(), true); + if (getDescriptor().markOffline(c, size)) { + LOGGER.warning(Messages.DiskSpaceMonitor_MarkedOffline(c.getDisplayName())); + } } return size; } private static final Logger LOGGER = Logger.getLogger(AbstractDiskSpaceMonitor.class.getName()); - private static final long DEFAULT_THRESHOLD = 1024L*1024*1024; + private static final long DEFAULT_THRESHOLD = 1024L * 1024 * 1024; } diff --git a/core/src/main/java/hudson/node_monitors/AbstractNodeMonitorDescriptor.java b/core/src/main/java/hudson/node_monitors/AbstractNodeMonitorDescriptor.java index 11b11f55a33d6..4a2386c2a1b17 100644 --- a/core/src/main/java/hudson/node_monitors/AbstractNodeMonitorDescriptor.java +++ b/core/src/main/java/hudson/node_monitors/AbstractNodeMonitorDescriptor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.node_monitors; import hudson.Util; @@ -134,7 +135,7 @@ public void doRun() { * whereas {@link IOException} is useful for indicating a hard error that needs to be * corrected. */ - protected abstract T monitor(Computer c) throws IOException,InterruptedException; + protected abstract T monitor(Computer c) throws IOException, InterruptedException; /** * Performs monitoring across the board. @@ -142,20 +143,20 @@ public void doRun() { * @return * For all the computers, report the monitored values. */ - protected Map monitor() throws InterruptedException { - Map data = new HashMap<>(); - for( Computer c : Jenkins.get().getComputers() ) { + protected Map monitor() throws InterruptedException { + Map data = new HashMap<>(); + for (Computer c : Jenkins.get().getComputers()) { try { - Thread.currentThread().setName("Monitoring "+c.getDisplayName()+" for "+getDisplayName()); + Thread.currentThread().setName("Monitoring " + c.getDisplayName() + " for " + getDisplayName()); - if(c.getChannel()==null) - data.put(c,null); + if (c.getChannel() == null) + data.put(c, null); else - data.put(c,monitor(c)); + data.put(c, monitor(c)); } catch (RuntimeException | IOException e) { - LOGGER.log(Level.WARNING, "Failed to monitor "+c.getDisplayName()+" for "+getDisplayName(), e); + LOGGER.log(Level.WARNING, "Failed to monitor " + c.getDisplayName() + " for " + getDisplayName(), e); } catch (InterruptedException e) { - throw (InterruptedException)new InterruptedException("Node monitoring "+c.getDisplayName()+" for "+getDisplayName()+" aborted.").initCause(e); + throw (InterruptedException) new InterruptedException("Node monitoring " + c.getDisplayName() + " for " + getDisplayName() + " aborted.").initCause(e); } } return data; @@ -168,7 +169,7 @@ protected Map monitor() throws InterruptedException { * If no data is available, a background task to collect data will be started. */ public T get(Computer c) { - if(record==null || !record.data.containsKey(c)) { + if (record == null || !record.data.containsKey(c)) { // if we don't have the data, schedule the check now triggerUpdate(); return null; @@ -180,20 +181,20 @@ public T get(Computer c) { * Is the monitoring activity currently in progress? */ private synchronized boolean isInProgress() { - return inProgress !=null && inProgress.isAlive(); + return inProgress != null && inProgress.isAlive(); } /** * The timestamp that indicates when the last round of the monitoring has completed. */ public long getTimestamp() { - return record==null ? 0L : record.timestamp; + return record == null ? 0L : record.timestamp; } public String getTimestampString() { - if (record==null) + if (record == null) return Messages.AbstractNodeMonitorDescriptor_NoDataYet(); - return Util.getTimeSpanString(System.currentTimeMillis()-record.timestamp); + return Util.getTimeSpanString(System.currentTimeMillis() - record.timestamp); } /** @@ -201,22 +202,22 @@ public String getTimestampString() { */ public boolean isIgnored() { NodeMonitor m = ComputerSet.getMonitors().get(this); - return m==null || m.isIgnored(); + return m == null || m.isIgnored(); } /** * Utility method to mark the computer online for derived classes. - * - * @return true + * + * @return true * if the node was actually taken online by this act (as opposed to us deciding not to do it, * or the computer was already online.) */ protected boolean markOnline(Computer c) { - if(isIgnored() || c.isOnline()) return false; // noop - c.setTemporarilyOffline(false,null); + if (isIgnored() || c.isOnline()) return false; // noop + c.setTemporarilyOffline(false, null); return true; } - + /** * Utility method to mark the computer offline for derived classes. * @@ -225,13 +226,13 @@ protected boolean markOnline(Computer c) { * or the computer already marked offline.) */ protected boolean markOffline(Computer c, OfflineCause oc) { - if(isIgnored() || c.isTemporarilyOffline()) return false; // noop + if (isIgnored() || c.isTemporarilyOffline()) return false; // noop c.setTemporarilyOffline(true, oc); // notify the admin MonitorMarkedNodeOffline no = AdministrativeMonitor.all().get(MonitorMarkedNodeOffline.class); - if(no!=null) + if (no != null) no.active = true; return true; } @@ -242,7 +243,7 @@ protected boolean markOffline(Computer c, OfflineCause oc) { */ @Deprecated protected boolean markOffline(Computer c) { - return markOffline(c,null); + return markOffline(c, null); } /** @@ -288,12 +289,12 @@ private final class Record extends Thread { /** * Last computed monitoring result. */ - private /*final*/ Map data = Collections.emptyMap(); + private /*final*/ Map data = Collections.emptyMap(); private long timestamp; Record() { - super("Monitoring thread for "+getDisplayName()+" started on "+new Date()); + super("Monitoring thread for " + getDisplayName() + " started on " + new Date()); } @Override @@ -301,20 +302,20 @@ public void run() { try { long startTime = System.currentTimeMillis(); String oldName = getName(); - data=monitor(); + data = monitor(); setName(oldName); timestamp = System.currentTimeMillis(); record = this; - LOGGER.log(Level.FINE, "Node monitoring {0} completed in {1}ms", new Object[] {getDisplayName(), System.currentTimeMillis()-startTime}); + LOGGER.log(Level.FINE, "Node monitoring {0} completed in {1}ms", new Object[] {getDisplayName(), System.currentTimeMillis() - startTime}); } catch (InterruptedException x) { // interrupted by new one, fine } catch (Throwable t) { - LOGGER.log(Level.WARNING, "Unexpected node monitoring termination: "+getDisplayName(),t); + LOGGER.log(Level.WARNING, "Unexpected node monitoring termination: " + getDisplayName(), t); } finally { - synchronized(AbstractNodeMonitorDescriptor.this) { - if (inProgress==this) + synchronized (AbstractNodeMonitorDescriptor.this) { + if (inProgress == this) inProgress = null; } } diff --git a/core/src/main/java/hudson/node_monitors/ArchitectureMonitor.java b/core/src/main/java/hudson/node_monitors/ArchitectureMonitor.java index fe96c807bc1c9..b7e88d8e0eefc 100644 --- a/core/src/main/java/hudson/node_monitors/ArchitectureMonitor.java +++ b/core/src/main/java/hudson/node_monitors/ArchitectureMonitor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.node_monitors; import hudson.Extension; @@ -59,12 +60,12 @@ public NodeMonitor newInstance(StaplerRequest req, JSONObject formData) throws F /** * Obtains the string that represents the architecture. */ - private static class GetArchTask extends MasterToSlaveCallable { + private static class GetArchTask extends MasterToSlaveCallable { @Override public String call() { String os = System.getProperty("os.name"); String arch = System.getProperty("os.arch"); - return os+" ("+arch+')'; + return os + " (" + arch + ')'; } private static final long serialVersionUID = 1L; diff --git a/core/src/main/java/hudson/node_monitors/ClockMonitor.java b/core/src/main/java/hudson/node_monitors/ClockMonitor.java index 602ba646859d7..6c7dc54f343d7 100644 --- a/core/src/main/java/hudson/node_monitors/ClockMonitor.java +++ b/core/src/main/java/hudson/node_monitors/ClockMonitor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Thomas J. Black - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,8 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.node_monitors; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import hudson.model.Computer; import hudson.model.Node; @@ -53,18 +55,20 @@ public ClockDifference getDifferenceFor(Computer c) { */ @Deprecated @Restricted(NoExternalUse.class) + @SuppressFBWarnings(value = "MS_PKGPROTECT", justification = "for backward compatibility") public static /*almost final*/ AbstractNodeMonitorDescriptor DESCRIPTOR; @Extension @Symbol("clock") public static class DescriptorImpl extends AbstractAsyncNodeMonitorDescriptor { + @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "for backward compatibility") public DescriptorImpl() { DESCRIPTOR = this; } @Override - protected Callable createCallable(Computer c) { + protected Callable createCallable(Computer c) { Node n = c.getNode(); - if(n==null) return null; + if (n == null) return null; return n.getClockDifferenceCallable(); } diff --git a/core/src/main/java/hudson/node_monitors/DiskSpaceMonitor.java b/core/src/main/java/hudson/node_monitors/DiskSpaceMonitor.java index 21d531a9796ba..bcf96ba02704b 100644 --- a/core/src/main/java/hudson/node_monitors/DiskSpaceMonitor.java +++ b/core/src/main/java/hudson/node_monitors/DiskSpaceMonitor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.node_monitors; import hudson.Extension; @@ -43,12 +44,12 @@ */ public class DiskSpaceMonitor extends AbstractDiskSpaceMonitor { @DataBoundConstructor - public DiskSpaceMonitor(String freeSpaceThreshold) throws ParseException { + public DiskSpaceMonitor(String freeSpaceThreshold) throws ParseException { super(freeSpaceThreshold); - } + } public DiskSpaceMonitor() {} - + public DiskSpace getFreeSpace(Computer c) { return DESCRIPTOR.get(c); } @@ -69,9 +70,9 @@ public String getDisplayName() { protected Callable createCallable(Computer c) { Node node = c.getNode(); if (node == null) return null; - + FilePath p = node.getRootPath(); - if(p==null) return null; + if (p == null) return null; return p.asCallableWith(new GetUsableSpace()); } diff --git a/core/src/main/java/hudson/node_monitors/DiskSpaceMonitorDescriptor.java b/core/src/main/java/hudson/node_monitors/DiskSpaceMonitorDescriptor.java index ed68ff4576ce6..076c2b281c7f1 100644 --- a/core/src/main/java/hudson/node_monitors/DiskSpaceMonitorDescriptor.java +++ b/core/src/main/java/hudson/node_monitors/DiskSpaceMonitorDescriptor.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.node_monitors; import hudson.Functions; @@ -54,7 +55,7 @@ public static final class DiskSpace extends MonitorOfflineCause implements Seria private final String path; @Exported public final long size; - + private boolean triggered; private Class trigger; @@ -69,12 +70,12 @@ public DiskSpace(String path, long size) { @Override public String toString() { - if(triggered) { + if (triggered) { return Messages.DiskSpaceMonitorDescriptor_DiskSpace_FreeSpaceTooLow(getGbLeft(), path); } return Messages.DiskSpaceMonitorDescriptor_DiskSpace_FreeSpace(getGbLeft(), path); } - + /** * The path that was checked */ @@ -96,8 +97,8 @@ public long getFreeSize() { */ public String getGbLeft() { long space = size; - space/=1024L; // convert to KB - space/=1024L; // convert to MB + space /= 1024L; // convert to KB + space /= 1024L; // convert to MB return new BigDecimal(space).scaleByPowerOfTen(-3).toPlainString(); } @@ -107,33 +108,33 @@ public String getGbLeft() { */ public String toHtml() { String humanReadableSpace = Functions.humanReadableByteSize(size); - if(triggered) { + if (triggered) { return Util.wrapToErrorSpan(humanReadableSpace); } return humanReadableSpace; } - + /** * Sets whether this disk space amount should be treated as outside * the acceptable conditions or not. */ protected void setTriggered(boolean triggered) { - this.triggered = triggered; + this.triggered = triggered; } - /** + /** * Same as {@link DiskSpace#setTriggered(boolean)}, also sets the trigger class which made the decision */ protected void setTriggered(Class trigger, boolean triggered) { this.trigger = trigger; this.triggered = triggered; } - + @Override public Class getTrigger() { return trigger; } - + /** * Parses a human readable size description like "1GB", "0.5m", etc. into {@link DiskSpace} * @@ -143,23 +144,23 @@ public Class getTrigger() { public static DiskSpace parse(String size) throws ParseException { size = size.toUpperCase(Locale.ENGLISH).trim(); if (size.endsWith("B")) // cut off 'B' from KB, MB, etc. - size = size.substring(0,size.length()-1); + size = size.substring(0, size.length() - 1); - long multiplier=1; + long multiplier = 1; // look for the size suffix. The goal here isn't to detect all invalid size suffix, // so we ignore double suffix like "10gkb" or anything like that. String suffix = "KMGT"; - for (int i=0; i { public GetUsableSpace() {} + @Override public DiskSpace invoke(File f, VirtualChannel channel) throws IOException { long s = f.getUsableSpace(); - if(s<=0) return null; + if (s <= 0) return null; return new DiskSpace(f.getCanonicalPath(), s); } + private static final long serialVersionUID = 1L; } } diff --git a/core/src/main/java/hudson/node_monitors/MonitorMarkedNodeOffline.java b/core/src/main/java/hudson/node_monitors/MonitorMarkedNodeOffline.java index 21cec64d9a1e3..220774a458ed0 100644 --- a/core/src/main/java/hudson/node_monitors/MonitorMarkedNodeOffline.java +++ b/core/src/main/java/hudson/node_monitors/MonitorMarkedNodeOffline.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.node_monitors; import hudson.Extension; diff --git a/core/src/main/java/hudson/node_monitors/MonitorOfflineCause.java b/core/src/main/java/hudson/node_monitors/MonitorOfflineCause.java index 3c40df208aabe..7bb30048d872f 100644 --- a/core/src/main/java/hudson/node_monitors/MonitorOfflineCause.java +++ b/core/src/main/java/hudson/node_monitors/MonitorOfflineCause.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.node_monitors; import edu.umd.cs.findbugs.annotations.NonNull; diff --git a/core/src/main/java/hudson/node_monitors/NodeMonitor.java b/core/src/main/java/hudson/node_monitors/NodeMonitor.java index 9b11988dc4f77..eb5a9459c33d6 100644 --- a/core/src/main/java/hudson/node_monitors/NodeMonitor.java +++ b/core/src/main/java/hudson/node_monitors/NodeMonitor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Thomas J. Black - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.node_monitors; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -53,7 +54,7 @@ *

    config.jelly (optional)
    *
    * Configuration fragment to be displayed in {@code http://server/hudson/computer/configure}. - * Used for configuring the threshold for taking nodes offline. + * Used for configuring the threshold for taking nodes offline. * * *

    Persistence

    @@ -144,7 +145,7 @@ public void setIgnored(boolean ignored) { /** * Returns all the registered {@link NodeMonitor} descriptors. */ - public static DescriptorExtensionList> all() { + public static DescriptorExtensionList> all() { return Jenkins.get().getDescriptorList(NodeMonitor.class); } } diff --git a/core/src/main/java/hudson/node_monitors/NodeMonitorUpdater.java b/core/src/main/java/hudson/node_monitors/NodeMonitorUpdater.java index d0b36fb978905..10238deb3352a 100644 --- a/core/src/main/java/hudson/node_monitors/NodeMonitorUpdater.java +++ b/core/src/main/java/hudson/node_monitors/NodeMonitorUpdater.java @@ -36,7 +36,7 @@ public void run() { */ @Override public void onOnline(Computer c, TaskListener listener) throws IOException, InterruptedException { - synchronized(this) { + synchronized (this) { future.cancel(false); future = Timer.get().schedule(MONITOR_UPDATER, 5, TimeUnit.SECONDS); } diff --git a/core/src/main/java/hudson/node_monitors/ResponseTimeMonitor.java b/core/src/main/java/hudson/node_monitors/ResponseTimeMonitor.java index 3ecfabbdaac94..8932941432c1b 100644 --- a/core/src/main/java/hudson/node_monitors/ResponseTimeMonitor.java +++ b/core/src/main/java/hudson/node_monitors/ResponseTimeMonitor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Red Hat, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.node_monitors; import hudson.Extension; @@ -46,7 +47,7 @@ public class ResponseTimeMonitor extends NodeMonitor { public static final AbstractNodeMonitorDescriptor DESCRIPTOR = new AbstractAsyncNodeMonitorDescriptor() { @Override - protected Callable createCallable(Computer c) { + protected Callable createCallable(Computer c) { return new Step1(get(c)); } @@ -62,12 +63,12 @@ protected Map monitor() throws InterruptedException { continue; } - if (d ==null) { + if (d == null) { // if we failed to monitor, put in the special value that indicates a failure - e.setValue(d=new Data(get(c),-1L)); + e.setValue(d = new Data(get(c), -1L)); } - if(d.hasTooManyTimeouts() && !isIgnored()) { + if (d.hasTooManyTimeouts() && !isIgnored()) { // unlike other monitors whose failure still allow us to communicate with the agent, // the failure in this monitor indicates that we are just unable to make any requests // to this agent. So we should severe the connection, as opposed to marking it temporarily @@ -90,7 +91,7 @@ public NodeMonitor newInstance(StaplerRequest req, JSONObject formData) throws F } }; - private static final class Step1 extends MasterToSlaveCallable { + private static final class Step1 extends MasterToSlaveCallable { private Data cur; private Step1(Data cur) { @@ -100,7 +101,7 @@ private Step1(Data cur) { @Override public Data call() { // this method must be being invoked locally, which means the roundtrip time is zero and zero forever - return new Data(cur,0); + return new Data(cur, 0); } private Object writeReplace() { @@ -110,7 +111,7 @@ private Object writeReplace() { private static final long serialVersionUID = 1L; } - private static final class Step2 extends MasterToSlaveCallable { + private static final class Step2 extends MasterToSlaveCallable { private final Data cur; private final long start = System.currentTimeMillis(); @@ -121,7 +122,7 @@ private static final class Step2 extends MasterToSlaveCallable=0 && past5[i]<0; i--, cnt++) + for (int i = past5.length - 1; i >= 0 && past5[i] < 0; i--, cnt++) ; return cnt; } @@ -182,16 +183,16 @@ private int failureCount() { */ @Exported public long getAverage() { - long total=0; + long total = 0; for (long l : past5) { - if(l<0) total += TIMEOUT; + if (l < 0) total += TIMEOUT; else total += l; } - return total/past5.length; + return total / past5.length; } public boolean hasTooManyTimeouts() { - return failureCount()>=5; + return failureCount() >= 5; } /** @@ -200,9 +201,9 @@ public boolean hasTooManyTimeouts() { @Override public String toString() { int fc = failureCount(); - if(fc>0) + if (fc > 0) return Messages.ResponseTimeMonitor_TimeOut(fc); - return getAverage()+"ms"; + return getAverage() + "ms"; } @Override diff --git a/core/src/main/java/hudson/node_monitors/SwapSpaceMonitor.java b/core/src/main/java/hudson/node_monitors/SwapSpaceMonitor.java index bf0cbf7744734..286274b42fe58 100644 --- a/core/src/main/java/hudson/node_monitors/SwapSpaceMonitor.java +++ b/core/src/main/java/hudson/node_monitors/SwapSpaceMonitor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,8 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.node_monitors; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import hudson.Functions; import hudson.Util; @@ -49,15 +51,15 @@ public class SwapSpaceMonitor extends NodeMonitor { * Returns the HTML representation of the space. */ public String toHtml(MemoryUsage usage) { - if(usage.availableSwapSpace==-1) + if (usage.availableSwapSpace == -1) return "N/A"; String humanReadableSpace = Functions.humanReadableByteSize(usage.availableSwapSpace); - + long free = usage.availableSwapSpace; - free/=1024L; // convert to KB - free/=1024L; // convert to MB - if(free>256 || usage.totalSwapSpace 256 || usage.totalSwapSpace < usage.availableSwapSpace * 5) return humanReadableSpace; // if we have more than 256MB free or less than 80% filled up, it's OK // Otherwise considered dangerously low. @@ -65,12 +67,12 @@ public String toHtml(MemoryUsage usage) { } public long toMB(MemoryUsage usage) { - if(usage.availableSwapSpace==-1) + if (usage.availableSwapSpace == -1) return -1; long free = usage.availableSwapSpace; - free/=1024L; // convert to KB - free/=1024L; // convert to MB + free /= 1024L; // convert to KB + free /= 1024L; // convert to MB return free; } @@ -89,6 +91,7 @@ public String getColumnCaption() { @Extension @Symbol("swapSpace") public static class DescriptorImpl extends AbstractAsyncNodeMonitorDescriptor { + @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "for backward compatibility") public DescriptorImpl() { DESCRIPTOR = this; } @@ -112,7 +115,7 @@ public NodeMonitor newInstance(StaplerRequest req, JSONObject formData) throws F /** * Obtains the string that represents the architecture. */ - private static class MonitorTask extends MasterToSlaveCallable { + private static class MonitorTask extends MasterToSlaveCallable { @Override public MemoryUsage call() throws IOException { MemoryMonitor mm; diff --git a/core/src/main/java/hudson/node_monitors/TemporarySpaceMonitor.java b/core/src/main/java/hudson/node_monitors/TemporarySpaceMonitor.java index b5ddce5bbfb53..d6b8a4f23359e 100644 --- a/core/src/main/java/hudson/node_monitors/TemporarySpaceMonitor.java +++ b/core/src/main/java/hudson/node_monitors/TemporarySpaceMonitor.java @@ -21,8 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.node_monitors; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import hudson.FilePath; import hudson.model.Computer; @@ -45,9 +47,9 @@ */ public class TemporarySpaceMonitor extends AbstractDiskSpaceMonitor { @DataBoundConstructor - public TemporarySpaceMonitor(String freeSpaceThreshold) throws ParseException { + public TemporarySpaceMonitor(String freeSpaceThreshold) throws ParseException { super(freeSpaceThreshold); - } + } public TemporarySpaceMonitor() {} @@ -66,10 +68,12 @@ public String getColumnCaption() { * Use injection */ @Deprecated + @SuppressFBWarnings(value = "MS_PKGPROTECT", justification = "for backward compatibility") public static /*almost final*/ DiskSpaceMonitorDescriptor DESCRIPTOR; @Extension @Symbol("tmpSpace") public static class DescriptorImpl extends DiskSpaceMonitorDescriptor { + @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "for backward compatibility") public DescriptorImpl() { DESCRIPTOR = this; } @@ -80,12 +84,12 @@ public String getDisplayName() { } @Override - protected Callable createCallable(Computer c) { + protected Callable createCallable(Computer c) { Node node = c.getNode(); if (node == null) return null; - + FilePath p = node.getRootPath(); - if(p==null) return null; + if (p == null) return null; return p.asCallableWith(new GetTempSpace()); } @@ -98,7 +102,7 @@ protected Callable createCallable(Computer c) { public static DiskSpaceMonitorDescriptor install() { return DESCRIPTOR; } - + protected static final class GetTempSpace extends MasterToSlaveFileCallable { @Override public DiskSpace invoke(File f, VirtualChannel channel) throws IOException { @@ -106,9 +110,10 @@ public DiskSpace invoke(File f, VirtualChannel channel) throws IOException { // so calling File.createTempFile and figuring out the directory won't reliably work. f = new File(System.getProperty("java.io.tmpdir")); long s = f.getUsableSpace(); - if(s<=0) return null; + if (s <= 0) return null; return new DiskSpace(f.getCanonicalPath(), s); } + private static final long serialVersionUID = 1L; } } diff --git a/core/src/main/java/hudson/os/PosixAPI.java b/core/src/main/java/hudson/os/PosixAPI.java deleted file mode 100644 index c9f40ac31b207..0000000000000 --- a/core/src/main/java/hudson/os/PosixAPI.java +++ /dev/null @@ -1,36 +0,0 @@ -package hudson.os; - -import jnr.constants.platform.Errno; -import jnr.posix.POSIX; -import jnr.posix.POSIXFactory; -import jnr.posix.util.DefaultPOSIXHandler; - -/** - * POSIX API wrapper. - * @author Kohsuke Kawaguchi - */ -public class PosixAPI { - - private static POSIX posix; - - /** - * Load the JNR implementation of the POSIX APIs for the current platform. - * Runtime exceptions will be of type {@link PosixException}. - * {@link IllegalStateException} will be thrown for methods not implemented on this platform. - * @return some implementation (even on Windows or unsupported Unix) - * @since 1.518 - */ - public static synchronized POSIX jnr() { - if (posix == null) { - posix = POSIXFactory.getPOSIX(new DefaultPOSIXHandler() { - @Override public void error(Errno error, String extraData) { - throw new PosixException("native error " + error.description() + " " + extraData); - } - @Override public void error(Errno error, String methodName, String extraData) { - throw new PosixException("native error calling " + methodName + ": " + error.description() + " " + extraData); - } - }, true); - } - return posix; - } -} diff --git a/core/src/main/java/hudson/os/PosixException.java b/core/src/main/java/hudson/os/PosixException.java index c32b9a3e6b586..b741e94246a66 100644 --- a/core/src/main/java/hudson/os/PosixException.java +++ b/core/src/main/java/hudson/os/PosixException.java @@ -1,10 +1,13 @@ package hudson.os; +import java.io.IOException; + /** * Indicates an error during POSIX API call. - * @see PosixAPI * @author Kohsuke Kawaguchi + * @deprecated use {@link IOException} */ +@Deprecated public class PosixException extends RuntimeException { public PosixException(String message) { diff --git a/core/src/main/java/hudson/os/SU.java b/core/src/main/java/hudson/os/SU.java index 9103c72a866fb..185110d83781d 100644 --- a/core/src/main/java/hudson/os/SU.java +++ b/core/src/main/java/hudson/os/SU.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.os; import static hudson.util.jna.GNUCLibrary.LIBC; @@ -42,6 +43,7 @@ import java.io.File; import java.io.IOException; import java.io.PrintStream; +import java.nio.charset.Charset; import java.util.Collections; /** @@ -71,36 +73,36 @@ private SU() { // not meant to be instantiated * Close this channel and the SU environment will be shut down. */ public static VirtualChannel start(final TaskListener listener, final String rootUsername, final String rootPassword) throws IOException, InterruptedException { - if(File.pathSeparatorChar==';') // on Windows + if (File.pathSeparatorChar == ';') // on Windows return newLocalChannel(); // TODO: perhaps use RunAs to run as an Administrator? String os = Util.fixNull(System.getProperty("os.name")); - if(os.equals("Linux")) + if (os.equals("Linux")) return new UnixSu() { @Override protected String sudoExe() { return "sudo"; } - @SuppressFBWarnings(value = {"COMMAND_INJECTION", "DM_DEFAULT_ENCODING"}, justification = "TODO needs triage") + @SuppressFBWarnings(value = "COMMAND_INJECTION", justification = "TODO needs triage") @Override protected Process sudoWithPass(ArgumentListBuilder args) throws IOException { - args.prepend(sudoExe(),"-S"); + args.prepend(sudoExe(), "-S"); listener.getLogger().println("$ " + String.join(" ", args.toList())); ProcessBuilder pb = new ProcessBuilder(args.toCommandArray()); Process p = pb.start(); // TODO: use -p to detect prompt // TODO: detect if the password didn't work - try (PrintStream ps = new PrintStream(p.getOutputStream())) { + try (PrintStream ps = new PrintStream(p.getOutputStream(), false, Charset.defaultCharset().name())) { ps.println(rootPassword); ps.println(rootPassword); ps.println(rootPassword); } return p; } - }.start(listener,rootPassword); + }.start(listener, rootPassword); - if(os.equals("SunOS")) + if (os.equals("SunOS")) return new UnixSu() { @Override protected String sudoExe() { @@ -116,7 +118,7 @@ protected Process sudoWithPass(ArgumentListBuilder args) throws IOException { } // in solaris, pfexec never asks for a password, so username==null means // we won't be using password. this helps disambiguate empty password - }.start(listener,rootUsername==null?null:rootPassword); + }.start(listener, rootUsername == null ? null : rootPassword); // TODO: Mac? @@ -131,7 +133,7 @@ private static LocalChannel newLocalChannel() { /** * Starts a new privilege-escalated environment, execute a closure, and shut it down. */ - public static V execute(TaskListener listener, String rootUsername, String rootPassword, final Callable closure) throws T, IOException, InterruptedException { + public static V execute(TaskListener listener, String rootUsername, String rootPassword, final Callable closure) throws T, IOException, InterruptedException { VirtualChannel ch = start(listener, rootUsername, rootPassword); try { return ch.call(closure); @@ -150,16 +152,16 @@ private abstract static class UnixSu { VirtualChannel start(TaskListener listener, String rootPassword) throws IOException, InterruptedException { final int uid = LIBC.geteuid(); - if(uid==0) // already running as root + if (uid == 0) // already running as root return newLocalChannel(); String javaExe = System.getProperty("java.home") + "/bin/java"; File agentJar = Which.jarFile(Launcher.class); ArgumentListBuilder args = new ArgumentListBuilder().add(javaExe); - if(agentJar.isFile()) + if (agentJar.isFile()) args.add("-jar").add(agentJar); - else // in production code this never happens, but during debugging this is convenient + else // in production code this never happens, but during debugging this is convenient args.add("-cp").add(agentJar).add(hudson.remoting.Launcher.class.getName()); if (Util.fixEmptyAndTrim(rootPassword) == null) { @@ -171,7 +173,7 @@ VirtualChannel start(TaskListener listener, String rootPassword) throws IOExcept // try sudo with the given password. Also run in pfexec so that we can elevate the privileges Process proc = sudoWithPass(args); return Channels.forProcess(args.toStringWithQuote(), Computer.threadPoolForRemoting, proc, - listener.getLogger() ); + listener.getLogger()); } } } diff --git a/core/src/main/java/hudson/scheduler/BaseParser.java b/core/src/main/java/hudson/scheduler/BaseParser.java index e846636d6fed8..36a7131011773 100644 --- a/core/src/main/java/hudson/scheduler/BaseParser.java +++ b/core/src/main/java/hudson/scheduler/BaseParser.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scheduler; import antlr.ANTLRException; @@ -38,14 +39,14 @@ */ abstract class BaseParser extends LLkParser { // lower/upper bounds of fields (inclusive) - static final int[] LOWER_BOUNDS = new int[] {0,0,1,1,0}; - static final int[] UPPER_BOUNDS = new int[] {59,23,31,12,7}; + static final int[] LOWER_BOUNDS = new int[] {0, 0, 1, 1, 0}; + static final int[] UPPER_BOUNDS = new int[] {59, 23, 31, 12, 7}; /** * Used to pick a value from within the range */ protected Hash hash = Hash.zero(); - + protected BaseParser(int i) { super(i); } @@ -63,7 +64,7 @@ protected BaseParser(TokenStream tokenStream, int i) { } public void setHash(Hash hash) { - if (hash==null) hash = Hash.zero(); + if (hash == null) hash = Hash.zero(); this.hash = hash; } @@ -72,8 +73,8 @@ protected long doRange(int start, int end, int step, int field) throws ANTLRExce rangeCheck(end, field); if (step <= 0) error(Messages.BaseParser_MustBePositive(step)); - if (start>end) - error(Messages.BaseParser_StartEndReversed(end,start)); + if (start > end) + error(Messages.BaseParser_StartEndReversed(end, start)); long bits = 0; for (int i = start; i <= end; i += step) { @@ -82,8 +83,8 @@ protected long doRange(int start, int end, int step, int field) throws ANTLRExce return bits; } - protected long doRange( int step, int field ) throws ANTLRException { - return doRange( LOWER_BOUNDS[field], UPPER_BOUNDS[field], step, field ); + protected long doRange(int step, int field) throws ANTLRException { + return doRange(LOWER_BOUNDS[field], UPPER_BOUNDS[field], step, field); } /** @@ -95,8 +96,8 @@ protected long doRange( int step, int field ) throws ANTLRException { */ protected long doHash(int step, int field) throws ANTLRException { int u = UPPER_BOUNDS[field]; - if (field==2) u = 28; // day of month can vary depending on month, so to make life simpler, just use [1,28] that's always safe - if (field==4) u = 6; // Both 0 and 7 of day of week are Sunday. For better distribution, limit upper bound to 6 + if (field == 2) u = 28; // day of month can vary depending on month, so to make life simpler, just use [1,28] that's always safe + if (field == 4) u = 6; // Both 0 and 7 of day of week are Sunday. For better distribution, limit upper bound to 6 return doHash(LOWER_BOUNDS[field], u, step, field); } @@ -113,19 +114,19 @@ protected long doHash(int s, int e, int step, int field) throws ANTLRException { } assert bits != 0; return bits; - } else if (step <=0) { + } else if (step <= 0) { error(Messages.BaseParser_MustBePositive(step)); throw new AssertionError(); } else { - assert step==NO_STEP; + assert step == NO_STEP; // step=1 (i.e. omitted) in the case of hash is actually special; means pick one value, not step by 1 - return 1L << (s+hash.next(e+1-s)); + return 1L << (s + hash.next(e + 1 - s)); } } - + protected void rangeCheck(int value, int field) throws ANTLRException { - if( value60) return -1; + while ((bits | (1L << n)) != bits) { + if (n > 60) return -1; n++; } return n; @@ -233,20 +234,20 @@ private int ceil(CronTab c, int n) { * Given a bit mask, finds the first bit that's on, and return its index. */ private int first(CronTab c) { - return ceil(c,0); + return ceil(c, 0); } private int floor(CronTab c, int n) { long bits = bits(c); - while ((bits|(1L<= firstDayOfWeek) { // in crontab, the first DoW is always Sunday, but in Java, it can be Monday or in theory arbitrary other days. // When first DoW is 1/2 Monday, calendar points to 1/2 Monday, setting the DoW to Sunday makes // the calendar moves forward to 1/8 Sunday, instead of 1/1 Sunday. So we need to compensate that effect here. - addTo(c,-7); + addTo(c, -7); } else if (was < firstDayOfWeek && firstDayOfWeek <= v) { // If we wrap the other way around, we need to adjust in the opposite direction of above. addTo(c, 7); @@ -357,26 +363,26 @@ public Calendar ceil(Calendar cal) { } for (CalendarField f : CalendarField.ADJUST_ORDER) { int cur = f.valueOf(cal); - int next = f.ceil(this,cur); - if (cur==next) continue; // this field is already in a good shape. move on to next + int next = f.ceil(this, cur); + if (cur == next) continue; // this field is already in a good shape. move on to next // we are modifying this field, so clear all the lower level fields - for (CalendarField l=f.lowerField; l!=null; l=l.lowerField) + for (CalendarField l = f.lowerField; l != null; l = l.lowerField) l.clear(cal); - if (next<0) { + if (next < 0) { // we need to roll over to the next field. f.rollUp(cal, 1); - f.setTo(cal,f.first(this)); + f.setTo(cal, f.first(this)); // since higher order field is affected by this, we need to restart from all over continue OUTER; } else { - f.setTo(cal,next); + f.setTo(cal, next); //check if value was actually set if (f.valueOf(cal) != next) { // we need to roll over to the next field. f.rollUp(cal, 1); - f.setTo(cal,f.first(this)); + f.setTo(cal, f.first(this)); // since higher order field is affected by this, we need to restart from all over continue OUTER; } @@ -427,30 +433,30 @@ public Calendar floor(Calendar cal) { } for (CalendarField f : CalendarField.ADJUST_ORDER) { int cur = f.valueOf(cal); - int next = f.floor(this,cur); - if (cur==next) continue; // this field is already in a good shape. move on to next + int next = f.floor(this, cur); + if (cur == next) continue; // this field is already in a good shape. move on to next // we are modifying this field, so clear all the lower level fields - for (CalendarField l=f.lowerField; l!=null; l=l.lowerField) + for (CalendarField l = f.lowerField; l != null; l = l.lowerField) l.clear(cal); - if (next<0) { + if (next < 0) { // we need to borrow from the next field. - f.rollUp(cal,-1); + f.rollUp(cal, -1); // the problem here, in contrast with the ceil method, is that // the maximum value of the field is not always a fixed value (that is, day of month) // so we zero-clear all the lower fields, set the desired value +1, - f.setTo(cal,f.last(this)); - f.addTo(cal,1); + f.setTo(cal, f.last(this)); + f.addTo(cal, 1); // then subtract a minute to achieve maximum values on all the lower fields, // with the desired value in 'f' - CalendarField.MINUTE.addTo(cal,-1); + CalendarField.MINUTE.addTo(cal, -1); // since higher order field is affected by this, we need to restart from all over continue OUTER; } else { - f.setTo(cal,next); - f.addTo(cal,1); - CalendarField.MINUTE.addTo(cal,-1); + f.setTo(cal, next); + f.addTo(cal, 1); + CalendarField.MINUTE.addTo(cal, -1); if (f.redoAdjustmentIfModified) continue OUTER; // when we modify DAY_OF_MONTH and DAY_OF_WEEK, do it all over from the top } @@ -460,28 +466,28 @@ public Calendar floor(Calendar cal) { } void set(String format, Hash hash) throws ANTLRException { - set(format,1,hash); + set(format, 1, hash); } /** * Returns true if n-th bit is on. */ private boolean checkBits(long bitMask, int n) { - return (bitMask|(1L<0) + if (i > 0) return Messages.CronTab_do_you_really_mean_every_minute_when_you(spec, "H " + spec.substring(spec.indexOf(' ') + 1)); // once we find a sparse rank, upper ranks don't matter break OUTER; @@ -536,9 +542,9 @@ private String toString(String key, long bit) { if (spec.contains("H")) { // if someone is already using H, presumably he knows what it is, so a warning is likely false positive return null; - } else if (spec.startsWith("*/")) {// "*/15 ...." (every N minutes) to hash + } else if (spec.startsWith("*/")) { // "*/15 ...." (every N minutes) to hash return "H" + spec.substring(1); - } else if (spec.matches("\\d+ .+")) {// "0 ..." (certain minute) to hash + } else if (spec.matches("\\d+ .+")) { // "0 ..." (certain minute) to hash return "H " + spec.substring(spec.indexOf(' ') + 1); } else { Matcher m = Pattern.compile("0(,(\\d+)(,\\d+)*)( .+)").matcher(spec); diff --git a/core/src/main/java/hudson/scheduler/CronTabList.java b/core/src/main/java/hudson/scheduler/CronTabList.java index 5273629d8b353..7a1b4760ff751 100644 --- a/core/src/main/java/hudson/scheduler/CronTabList.java +++ b/core/src/main/java/hudson/scheduler/CronTabList.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scheduler; import antlr.ANTLRException; @@ -52,7 +53,7 @@ public CronTabList(Collection tabs) { */ public synchronized boolean check(Calendar cal) { for (CronTab tab : tabs) { - if(tab.check(cal)) + if (tab.check(cal)) return true; } return false; @@ -70,7 +71,7 @@ public synchronized boolean check(Calendar cal) { public String checkSanity() { for (CronTab tab : tabs) { String s = tab.checkSanity(); - if(s!=null) return s; + if (s != null) return s; } return null; } @@ -91,7 +92,7 @@ public String checkSanity() { } public static CronTabList create(@NonNull String format) throws ANTLRException { - return create(format,null); + return create(format, null); } public static CronTabList create(@NonNull String format, Hash hash) throws ANTLRException { @@ -102,11 +103,11 @@ public static CronTabList create(@NonNull String format, Hash hash) throws ANTLR for (String line : format.split("\\r?\\n")) { lineNumber++; line = line.trim(); - - if(lineNumber == 1 && line.startsWith("TZ=")) { + + if (lineNumber == 1 && line.startsWith("TZ=")) { final String timezoneString = line.replace("TZ=", ""); timezone = getValidTimezone(timezoneString); - if(timezone != null) { + if (timezone != null) { LOGGER.log(Level.CONFIG, "CRON with timezone {0}", timezone); } else { throw new ANTLRException("Invalid or unsupported timezone '" + timezoneString + "'"); @@ -114,15 +115,15 @@ public static CronTabList create(@NonNull String format, Hash hash) throws ANTLR continue; } - if(line.length()==0 || line.startsWith("#")) + if (line.length() == 0 || line.startsWith("#")) continue; // ignorable line try { - r.add(new CronTab(line,lineNumber,hash,timezone)); + r.add(new CronTab(line, lineNumber, hash, timezone)); } catch (ANTLRException e) { - throw new ANTLRException(Messages.CronTabList_InvalidInput(line,e.toString()),e); + throw new ANTLRException(Messages.CronTabList_InvalidInput(line, e.toString()), e); } } - + return new CronTabList(r); } @@ -149,6 +150,6 @@ public static CronTabList create(@NonNull String format, Hash hash) throws ANTLR } return nearest; } - + private static final Logger LOGGER = Logger.getLogger(CronTabList.class.getName()); } diff --git a/core/src/main/java/hudson/scheduler/Hash.java b/core/src/main/java/hudson/scheduler/Hash.java index 432d3b363069d..86520ed87faae 100644 --- a/core/src/main/java/hudson/scheduler/Hash.java +++ b/core/src/main/java/hudson/scheduler/Hash.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2012, CloudBees, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scheduler; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -32,16 +33,12 @@ /** * Generates a pseudo-random sequence of integers in the specified range. * - *

    - * {@link CronTab} supports tokens like '@daily', which means "do it once a day". + *

    {@link CronTab} supports tokens like '@daily', which means "do it once a day". * Exactly which time of the day this gets scheduled is randomized --- randomized * in the sense that it's spread out when many jobs choose @daily, but it's at * the same time stable so that every job sticks to a specific time of the day * even after the configuration is updated. * - *

    - * - * * @author Kohsuke Kawaguchi * @since 1.448 */ @@ -53,19 +50,19 @@ public abstract class Hash { */ public abstract int next(int n); - @SuppressFBWarnings(value="PREDICTABLE_RANDOM", justification = "The random is just used for load distribution.") + @SuppressFBWarnings(value = "PREDICTABLE_RANDOM", justification = "The random is just used for load distribution.") public static Hash from(String seed) { try { MessageDigest md5 = getMd5(); md5.update(seed.getBytes(StandardCharsets.UTF_8)); byte[] digest = md5.digest(); - for (int i=8; i run; + private transient /*final*/ Run run; @Deprecated protected transient /*final*/ AbstractBuild build; /** * @since 1.568 */ - protected AbstractScmTagAction(Run run) { + protected AbstractScmTagAction(Run run) { this.run = run; this.build = run instanceof AbstractBuild ? (AbstractBuild) run : null; } @@ -81,7 +82,7 @@ protected Permission getPermission() { /** * @since 1.568 */ - public Run getRun() { + public Run getRun() { return run; } @@ -108,11 +109,11 @@ protected ACL getACL() { } public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { - req.getView(this,chooseAction()).forward(req,rsp); + req.getView(this, chooseAction()).forward(req, rsp); } protected synchronized String chooseAction() { - if(workerThread!=null) + if (workerThread != null) return "inProgress.jelly"; return "tagForm.jelly"; } diff --git a/core/src/main/java/hudson/scm/AutoBrowserHolder.java b/core/src/main/java/hudson/scm/AutoBrowserHolder.java index cd14a15c2808c..f851704ba25de 100644 --- a/core/src/main/java/hudson/scm/AutoBrowserHolder.java +++ b/core/src/main/java/hudson/scm/AutoBrowserHolder.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scm; import hudson.model.AbstractProject; @@ -61,7 +62,7 @@ public RepositoryBrowser get() { return cache; } int g = d.getGeneration(); - if(g!=cacheGeneration) { + if (g != cacheGeneration) { cacheGeneration = g; cache = infer(); } @@ -76,10 +77,10 @@ public RepositoryBrowser get() { * null if no applicable configuration was found. */ private RepositoryBrowser infer() { - for( AbstractProject p : Jenkins.get().allItems(AbstractProject.class) ) { + for (AbstractProject p : Jenkins.get().allItems(AbstractProject.class)) { SCM scm = p.getScm(); - if (scm!=null && scm.getClass()==owner.getClass() && scm.getBrowser()!=null && - ((SCMDescriptor)scm.getDescriptor()).isBrowserReusable(scm,owner)) { + if (scm != null && scm.getClass() == owner.getClass() && scm.getBrowser() != null && + ((SCMDescriptor) scm.getDescriptor()).isBrowserReusable(scm, owner)) { return scm.getBrowser(); } } diff --git a/core/src/main/java/hudson/scm/ChangeLogAnnotator.java b/core/src/main/java/hudson/scm/ChangeLogAnnotator.java index daf129aa206fb..c76b3f4d0d158 100644 --- a/core/src/main/java/hudson/scm/ChangeLogAnnotator.java +++ b/core/src/main/java/hudson/scm/ChangeLogAnnotator.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scm; import hudson.Extension; @@ -77,7 +78,7 @@ public abstract class ChangeLogAnnotator implements ExtensionPoint { * will return the same string as {@link ChangeLogSet.Entry#getMsgEscaped()}. * @since 1.568 */ - public void annotate(Run build, ChangeLogSet.Entry change, MarkupText text) { + public void annotate(Run build, ChangeLogSet.Entry change, MarkupText text) { if (build instanceof AbstractBuild && Util.isOverridden(ChangeLogAnnotator.class, getClass(), "annotate", AbstractBuild.class, ChangeLogSet.Entry.class, MarkupText.class)) { annotate((AbstractBuild) build, change, text); } else { @@ -86,7 +87,7 @@ public void annotate(Run build, ChangeLogSet.Entry change, MarkupText text) } @Deprecated - public void annotate(AbstractBuild build, ChangeLogSet.Entry change, MarkupText text) { + public void annotate(AbstractBuild build, ChangeLogSet.Entry change, MarkupText text) { annotate((Run) build, change, text); } diff --git a/core/src/main/java/hudson/scm/ChangeLogParser.java b/core/src/main/java/hudson/scm/ChangeLogParser.java index 57062a996bb03..f38f836607155 100644 --- a/core/src/main/java/hudson/scm/ChangeLogParser.java +++ b/core/src/main/java/hudson/scm/ChangeLogParser.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scm; import hudson.Util; diff --git a/core/src/main/java/hudson/scm/ChangeLogSet.java b/core/src/main/java/hudson/scm/ChangeLogSet.java index 0b0d9c1d0e994..a0c4a4c9cd79c 100644 --- a/core/src/main/java/hudson/scm/ChangeLogSet.java +++ b/core/src/main/java/hudson/scm/ChangeLogSet.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scm; import hudson.MarkupText; @@ -50,21 +51,21 @@ * * @author Kohsuke Kawaguchi */ -@ExportedBean(defaultVisibility=999) +@ExportedBean(defaultVisibility = 999) public abstract class ChangeLogSet implements Iterable { /** * Build whose change log this object represents. */ - private final Run run; + private final Run run; @Deprecated - public final AbstractBuild build; + public final AbstractBuild build; private final RepositoryBrowser browser; /** * @since 1.568 */ - protected ChangeLogSet(Run run, RepositoryBrowser browser) { + protected ChangeLogSet(Run run, RepositoryBrowser browser) { this.run = run; build = run instanceof AbstractBuild ? (AbstractBuild) run : null; this.browser = browser; @@ -74,7 +75,8 @@ protected ChangeLogSet(Run run, RepositoryBrowser browser) { protected ChangeLogSet(AbstractBuild build) { this(build, browserFromBuild(build)); } - private static RepositoryBrowser browserFromBuild(AbstractBuild build) { + + private static RepositoryBrowser browserFromBuild(AbstractBuild build) { if (build == null) { // not generally allowed, but sometimes done in unit tests return null; } @@ -84,7 +86,7 @@ private static RepositoryBrowser browserFromBuild(AbstractBuild build) { /** * @since 1.568 */ - public Run getRun() { + public Run getRun() { return run; } @@ -101,7 +103,7 @@ public RepositoryBrowser getBrowser() { public abstract boolean isEmptySet(); /** - * All changes in this change set. + * All changes in this change set. */ // method for the remote API. @Exported @@ -135,7 +137,7 @@ public static ChangeLogSet createEmpty(AbstractBui return createEmpty((Run) build); } - @ExportedBean(defaultVisibility=999) + @ExportedBean(defaultVisibility = 999) public abstract static class Entry { private ChangeLogSet parent; @@ -216,29 +218,29 @@ public long getTimestamp() { */ @Exported public abstract Collection getAffectedPaths(); - + /** * Returns a set of paths in the workspace that was * affected by this change. *

    - * Noted: since this is a new interface, some of the SCMs may not have - * implemented this interface. The default implementation for this + * Noted: since this is a new interface, some of the SCMs may not have + * implemented this interface. The default implementation for this * interface is throw UnsupportedOperationException *

    - * It doesn't throw NoSuchMethodException because I rather to throw a + * It doesn't throw NoSuchMethodException because I rather to throw a * runtime exception * * @return AffectedFile never null. * @since 1.309 */ public Collection getAffectedFiles() { - String scm = "this SCM"; - ChangeLogSet parent = getParent(); - if ( null != parent ) { - String kind = parent.getKind(); - if ( null != kind && kind.trim().length() > 0 ) scm = kind; - } - throw new UnsupportedOperationException("getAffectedFiles() is not implemented by " + scm); + String scm = "this SCM"; + ChangeLogSet parent = getParent(); + if (null != parent) { + String kind = parent.getKind(); + if (null != kind && kind.trim().length() > 0) scm = kind; + } + throw new UnsupportedOperationException("getAffectedFiles() is not implemented by " + scm); } /** @@ -249,9 +251,9 @@ public String getMsgAnnotated() { for (ChangeLogAnnotator a : ChangeLogAnnotator.all()) try { a.annotate(parent.run, this, markup); - } catch(RuntimeException e) { + } catch (RuntimeException e) { LOGGER.info("ChangeLogAnnotator " + a.toString() + " failed to annotate message '" + getMsg() + "'; " + e.getMessage()); - } catch(Error e) { + } catch (Error e) { LOGGER.severe("ChangeLogAnnotator " + a + " failed to annotate message '" + getMsg() + "'; " + e.getMessage()); } @@ -264,13 +266,13 @@ public String getMsgAnnotated() { public String getMsgEscaped() { return Util.escape(getMsg()); } - + static final Logger LOGGER = Logger.getLogger(ChangeLogSet.Entry.class.getName()); } - + /** * Represents a file change. Contains filename, edit type, etc. - * + * * I checked the API names against some some major SCMs and most SCMs * can adapt to this interface with very little changes * @@ -286,8 +288,8 @@ public interface AffectedFile { * @return never null. */ String getPath(); - - + + /** * Return whether the file is new/modified/deleted */ diff --git a/core/src/main/java/hudson/scm/EditType.java b/core/src/main/java/hudson/scm/EditType.java index 178a39a008c22..7672b09db2e4b 100644 --- a/core/src/main/java/hudson/scm/EditType.java +++ b/core/src/main/java/hudson/scm/EditType.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scm; import java.util.Arrays; @@ -55,9 +56,9 @@ public String toExportedObject() { return name; } - public static final EditType ADD = new EditType("add","The file was added"); - public static final EditType EDIT = new EditType("edit","The file was modified"); - public static final EditType DELETE = new EditType("delete","The file was removed"); + public static final EditType ADD = new EditType("add", "The file was added"); + public static final EditType EDIT = new EditType("edit", "The file was modified"); + public static final EditType DELETE = new EditType("delete", "The file was removed"); - public static final List ALL = Collections.unmodifiableList(Arrays.asList(ADD,EDIT,DELETE)); + public static final List ALL = Collections.unmodifiableList(Arrays.asList(ADD, EDIT, DELETE)); } diff --git a/core/src/main/java/hudson/scm/NullChangeLogParser.java b/core/src/main/java/hudson/scm/NullChangeLogParser.java index 1ab09948bd909..2832ede7c4b01 100644 --- a/core/src/main/java/hudson/scm/NullChangeLogParser.java +++ b/core/src/main/java/hudson/scm/NullChangeLogParser.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scm; import hudson.model.Run; @@ -33,13 +34,13 @@ * @author Kohsuke Kawaguchi */ public class NullChangeLogParser extends ChangeLogParser { - + public static final NullChangeLogParser INSTANCE = new NullChangeLogParser(); - + @Override public ChangeLogSet parse(Run build, RepositoryBrowser browser, File changelogFile) throws IOException, SAXException { return ChangeLogSet.createEmpty(build); } - + protected Object readResolve() { return INSTANCE; } diff --git a/core/src/main/java/hudson/scm/NullSCM.java b/core/src/main/java/hudson/scm/NullSCM.java index 777db3759e474..8d77816886554 100644 --- a/core/src/main/java/hudson/scm/NullSCM.java +++ b/core/src/main/java/hudson/scm/NullSCM.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scm; import hudson.Extension; @@ -48,11 +49,11 @@ public NullSCM() {} return null; } - @Override public PollingResult compareRemoteRevisionWith(Job project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline) throws IOException, InterruptedException { + @Override public PollingResult compareRemoteRevisionWith(Job project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline) throws IOException, InterruptedException { return PollingResult.NO_CHANGES; } - @Override public void checkout(Run build, Launcher launcher, FilePath workspace, TaskListener listener, File changelogFile, SCMRevisionState baseline) throws IOException, InterruptedException { + @Override public void checkout(Run build, Launcher launcher, FilePath workspace, TaskListener listener, File changelogFile, SCMRevisionState baseline) throws IOException, InterruptedException { if (changelogFile != null) { createEmptyChangeLog(changelogFile, listener, "log"); } diff --git a/core/src/main/java/hudson/scm/PollingResult.java b/core/src/main/java/hudson/scm/PollingResult.java index 7939fb579b7a2..bfcb135a63b94 100644 --- a/core/src/main/java/hudson/scm/PollingResult.java +++ b/core/src/main/java/hudson/scm/PollingResult.java @@ -6,7 +6,7 @@ import hudson.Launcher; import hudson.model.AbstractProject; import hudson.model.TaskListener; -import java.io.Serializable; +import org.jenkinsci.remoting.SerializableOnlyOverRemoting; /** * Immutable object that represents the result of {@linkplain SCM#poll(AbstractProject, Launcher, FilePath, TaskListener, SCMRevisionState) SCM polling}. @@ -18,7 +18,7 @@ * @author Kohsuke Kawaguchi * @since 1.345 */ -public final class PollingResult implements Serializable { +public final class PollingResult implements SerializableOnlyOverRemoting { /** * Baseline of the comparison. * (This comes from either the workspace, or from the remote repository as of the last polling. @@ -79,14 +79,14 @@ public enum Change { } public PollingResult(@CheckForNull SCMRevisionState baseline, @CheckForNull SCMRevisionState remote, @NonNull Change change) { - if (change==null) throw new IllegalArgumentException(); + if (change == null) throw new IllegalArgumentException(); this.baseline = baseline; this.remote = remote; this.change = change; } public PollingResult(@NonNull Change change) { - this(null,null,change); + this(null, null, change); } public boolean hasChanges() { diff --git a/core/src/main/java/hudson/scm/RepositoryBrowser.java b/core/src/main/java/hudson/scm/RepositoryBrowser.java index dbeb7390ba4a8..05b095b02bceb 100644 --- a/core/src/main/java/hudson/scm/RepositoryBrowser.java +++ b/core/src/main/java/hudson/scm/RepositoryBrowser.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scm; import hudson.DescriptorExtensionList; @@ -37,7 +38,7 @@ /** * Connects Hudson to repository browsers like ViewCVS or FishEye, - * so that Hudson can generate links to them. + * so that Hudson can generate links to them. * *

    * {@link RepositoryBrowser} instance is normally created as @@ -70,24 +71,24 @@ public abstract class RepositoryBrowser extends Ab * If the given string starts with '/', return a string that removes it. */ protected static String trimHeadSlash(String s) { - if(s.startsWith("/")) return s.substring(1); + if (s.startsWith("/")) return s.substring(1); return s; } /** * Normalize the URL so that it ends with '/'. *

    - * An attention is paid to preserve the query parameters in URL if any. + * An attention is paid to preserve the query parameters in URL if any. */ protected static URL normalizeToEndWithSlash(URL url) { - if(url.getPath().endsWith("/")) + if (url.getPath().endsWith("/")) return url; // normalize String q = url.getQuery(); q = q != null ? '?' + q : ""; try { - return new URL(url,url.getPath()+'/'+q); + return new URL(url, url.getPath() + '/' + q); } catch (MalformedURLException e) { // impossible throw new Error(e); @@ -97,7 +98,7 @@ protected static URL normalizeToEndWithSlash(URL url) { /** * Returns all the registered {@link RepositoryBrowser} descriptors. */ - public static DescriptorExtensionList,Descriptor>> all() { + public static DescriptorExtensionList, Descriptor>> all() { return (DescriptorExtensionList) Jenkins.get().getDescriptorList(RepositoryBrowser.class); } diff --git a/core/src/main/java/hudson/scm/RepositoryBrowsers.java b/core/src/main/java/hudson/scm/RepositoryBrowsers.java index cc907e72f73e7..0a1e28d1a1529 100644 --- a/core/src/main/java/hudson/scm/RepositoryBrowsers.java +++ b/core/src/main/java/hudson/scm/RepositoryBrowsers.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Daniel Dyer, Stephen Connolly - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scm; import hudson.Extension; @@ -45,7 +46,7 @@ public class RepositoryBrowsers { * Use {@link RepositoryBrowser#all()} for read access and {@link Extension} for registration. */ @Deprecated - public static final List>> LIST = new DescriptorList>((Class)RepositoryBrowser.class); + public static final List>> LIST = new DescriptorList>((Class) RepositoryBrowser.class); /** * Only returns those {@link RepositoryBrowser} descriptors that extend from the given type. @@ -53,7 +54,7 @@ public class RepositoryBrowsers { public static List>> filter(Class t) { List>> r = new ArrayList<>(); for (Descriptor> d : RepositoryBrowser.all()) - if(d.isSubTypeOf(t)) + if (d.isSubTypeOf(t)) r.add(d); return r; } @@ -69,7 +70,7 @@ public static List>> filter(Class type, StaplerRequest req, String fieldName) throws FormException { List>> list = filter(type); String value = req.getParameter(fieldName); - if(value==null || value.equals("auto")) + if (value == null || value.equals("auto")) return null; // TODO: There was a TODO in the original code, which presumes passing something meaningful to the newInstance() JSON param @@ -85,9 +86,9 @@ T createInstance(Class type, StaplerRequest req, String fieldName) throws For */ public static T createInstance(Class type, StaplerRequest req, JSONObject parent, String fieldName) throws FormException { - JSONObject o = (JSONObject)parent.get(fieldName); - if(o==null) return null; + JSONObject o = (JSONObject) parent.get(fieldName); + if (o == null) return null; - return req.bindJSON(type,o); + return req.bindJSON(type, o); } } diff --git a/core/src/main/java/hudson/scm/SCM.java b/core/src/main/java/hudson/scm/SCM.java index 7b94b07e7dd5d..c00bcea162297 100644 --- a/core/src/main/java/hudson/scm/SCM.java +++ b/core/src/main/java/hudson/scm/SCM.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Stephen Connolly, InfraDNA, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scm; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -52,8 +53,10 @@ import hudson.security.PermissionScope; import hudson.tasks.Builder; import java.io.File; -import java.io.FileWriter; import java.io.IOException; +import java.io.Writer; +import java.nio.charset.Charset; +import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -137,10 +140,10 @@ public String getType() { * @see #guessBrowser */ @SuppressWarnings("deprecation") - @Exported(name="browser") + @Exported(name = "browser") public final @CheckForNull RepositoryBrowser getEffectiveBrowser() { RepositoryBrowser b = getBrowser(); - if(b!=null) + if (b != null) return b; if (useAutoBrowserHolder) { if (autoBrowserHolder == null) { @@ -166,14 +169,14 @@ public String getType() { public boolean supportsPolling() { return true; } - + /** * Returns true if this SCM requires a checked out workspace for doing polling. * *

    * This flag affects the behavior of Hudson when a job lost its workspace - * (typically due to a agent outage.) If this method returns false and - * polling is configured, then that would immediately trigger a new build. + * (typically due to a agent outage.) If this method returns true and + * polling is configured, then that would usually trigger a new build. * *

    * This flag also affects the mutual exclusion control between builds and polling. @@ -190,7 +193,7 @@ public boolean supportsPolling() { * @since 1.196 */ public boolean requiresWorkspaceForPolling() { - return true; + return true; } /** @@ -229,10 +232,10 @@ public boolean requiresWorkspaceForPolling() { * @return * true if {@link SCM} is OK to let Hudson proceed with deleting the workspace. * False to veto the workspace deletion. - * + * * @since 1.568 */ - public boolean processWorkspaceBeforeDeletion(@NonNull Job project, @NonNull FilePath workspace, @NonNull Node node) throws IOException, InterruptedException { + public boolean processWorkspaceBeforeDeletion(@NonNull Job project, @NonNull FilePath workspace, @NonNull Node node) throws IOException, InterruptedException { if (project instanceof AbstractProject) { return processWorkspaceBeforeDeletion((AbstractProject) project, workspace, node); } else { @@ -241,7 +244,7 @@ public boolean processWorkspaceBeforeDeletion(@NonNull Job project, @NonNul } @Deprecated - public boolean processWorkspaceBeforeDeletion(AbstractProject project, FilePath workspace, Node node) throws IOException, InterruptedException { + public boolean processWorkspaceBeforeDeletion(AbstractProject project, FilePath workspace, Node node) throws IOException, InterruptedException { if (Util.isOverridden(SCM.class, getClass(), "processWorkspaceBeforeDeletion", Job.class, FilePath.class, Node.class)) { return processWorkspaceBeforeDeletion((Job) project, workspace, node); } else { @@ -289,7 +292,7 @@ public boolean processWorkspaceBeforeDeletion(AbstractProject project, File * Call {@link #poll(AbstractProject, Launcher, FilePath, TaskListener, SCMRevisionState)} for use instead. */ @Deprecated - public boolean pollChanges(AbstractProject project, Launcher launcher, FilePath workspace, TaskListener listener) throws IOException, InterruptedException { + public boolean pollChanges(AbstractProject project, Launcher launcher, FilePath workspace, TaskListener listener) throws IOException, InterruptedException { // up until 1.336, this method was abstract, so everyone should have overridden this method // without calling super.pollChanges. So the compatibility implementation is purely for // new implementations that doesn't override this method. @@ -311,7 +314,7 @@ public boolean pollChanges(AbstractProject project, Launcher launcher, File *

    * The obtained object is added to the build as an {@link Action} for later retrieval. As an optimization, * {@link SCM} implementation can choose to compute {@link SCMRevisionState} and add it as an action - * during check out, in which case this method will not called. + * during check out, in which case this method will not called. * * @param build * The calculated {@link SCMRevisionState} is for the files checked out in this build. @@ -326,10 +329,10 @@ public boolean pollChanges(AbstractProject project, Launcher launcher, File * * @throws InterruptedException * interruption is usually caused by the user aborting the computation. - * this exception should be simply propagated all the way up. + * this exception should be simply propagated all the way up. * @since 1.568 */ - public @CheckForNull SCMRevisionState calcRevisionsFromBuild(@NonNull Run build, @Nullable FilePath workspace, @Nullable Launcher launcher, @NonNull TaskListener listener) throws IOException, InterruptedException { + public @CheckForNull SCMRevisionState calcRevisionsFromBuild(@NonNull Run build, @Nullable FilePath workspace, @Nullable Launcher launcher, @NonNull TaskListener listener) throws IOException, InterruptedException { if (build instanceof AbstractBuild && Util.isOverridden(SCM.class, getClass(), "calcRevisionsFromBuild", AbstractBuild.class, Launcher.class, TaskListener.class)) { return calcRevisionsFromBuild((AbstractBuild) build, launcher, listener); } else { @@ -338,7 +341,7 @@ public boolean pollChanges(AbstractProject project, Launcher launcher, File } @Deprecated - public SCMRevisionState calcRevisionsFromBuild(AbstractBuild build, Launcher launcher, TaskListener listener) throws IOException, InterruptedException { + public SCMRevisionState calcRevisionsFromBuild(AbstractBuild build, Launcher launcher, TaskListener listener) throws IOException, InterruptedException { return calcRevisionsFromBuild(build, launcher != null ? build.getWorkspace() : null, launcher, listener); } @@ -346,7 +349,7 @@ public SCMRevisionState calcRevisionsFromBuild(AbstractBuild build, Launche public SCMRevisionState _calcRevisionsFromBuild(AbstractBuild build, Launcher launcher, TaskListener listener) throws IOException, InterruptedException { return calcRevisionsFromBuild(build, launcher, listener); } - + /** * Compares the current state of the remote repository against the given baseline {@link SCMRevisionState}. * @@ -355,7 +358,7 @@ public SCMRevisionState _calcRevisionsFromBuild(AbstractBuild build, Launc * if there's any difference. In practice, however, comparing two arbitrary repository states is an expensive * operation, so in this abstraction, we chose to mix (1) the act of building up a repository state and * (2) the act of comparing it with the earlier state, so that SCM implementations can implement this - * more easily. + * more easily. * *

    * Multiple invocations of this method may happen over time to make sure that the remote repository @@ -412,19 +415,19 @@ public PollingResult compareRemoteRevisionWith( } @Deprecated - protected PollingResult compareRemoteRevisionWith(AbstractProject project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline) throws IOException, InterruptedException { + protected PollingResult compareRemoteRevisionWith(AbstractProject project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline) throws IOException, InterruptedException { return compareRemoteRevisionWith((Job) project, launcher, workspace, listener, baseline); } /** * Convenience method for the caller to handle the backward compatibility between pre 1.345 SCMs. */ - public final PollingResult poll(AbstractProject project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline) throws IOException, InterruptedException { + public final PollingResult poll(AbstractProject project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline) throws IOException, InterruptedException { if (is1_346OrLater()) { // This is to work around JENKINS-5827 in a general way. // don't let the SCM.compareRemoteRevisionWith(...) see SCMRevisionState that it didn't produce. SCMRevisionState baseline2; - if (baseline!=SCMRevisionState.NONE) { + if (baseline != SCMRevisionState.NONE) { baseline2 = baseline; } else { baseline2 = calcRevisionsFromBuild(project.getLastBuild(), launcher, listener); @@ -432,7 +435,7 @@ public final PollingResult poll(AbstractProject project, Launcher launcher, return compareRemoteRevisionWith(project, launcher, workspace, listener, baseline2); } else { - return pollChanges(project,launcher,workspace,listener) ? PollingResult.SIGNIFICANT : PollingResult.NO_CHANGES; + return pollChanges(project, launcher, workspace, listener) ? PollingResult.SIGNIFICANT : PollingResult.NO_CHANGES; } } @@ -445,7 +448,7 @@ private boolean is1_346OrLater() { try { c.getDeclaredMethod("compareRemoteRevisionWith", Job.class, Launcher.class, FilePath.class, TaskListener.class, SCMRevisionState.class); return true; - } catch (NoSuchMethodException e2) {} + } catch (NoSuchMethodException e2) { } } } return false; @@ -532,8 +535,8 @@ public void checkout( } @Deprecated - public boolean checkout(AbstractBuild build, Launcher launcher, FilePath workspace, BuildListener listener, @NonNull File changelogFile) throws IOException, InterruptedException { - AbstractBuild prev = build.getPreviousBuild(); + public boolean checkout(AbstractBuild build, Launcher launcher, FilePath workspace, BuildListener listener, @NonNull File changelogFile) throws IOException, InterruptedException { + AbstractBuild prev = build.getPreviousBuild(); checkout((Run) build, launcher, workspace, listener, changelogFile, prev != null ? prev.getAction(SCMRevisionState.class) : null); return true; } @@ -542,14 +545,14 @@ public boolean checkout(AbstractBuild build, Launcher launcher, FilePath wo * Get a chance to do operations after the workspace i checked out and the changelog is written. * @since 1.568 */ - public void postCheckout(@NonNull Run build, @NonNull Launcher launcher, @NonNull FilePath workspace, @NonNull TaskListener listener) throws IOException, InterruptedException { + public void postCheckout(@NonNull Run build, @NonNull Launcher launcher, @NonNull FilePath workspace, @NonNull TaskListener listener) throws IOException, InterruptedException { if (build instanceof AbstractBuild && listener instanceof BuildListener) { postCheckout((AbstractBuild) build, launcher, workspace, (BuildListener) listener); } } @Deprecated - public void postCheckout(AbstractBuild build, Launcher launcher, FilePath workspace, BuildListener listener) throws IOException, InterruptedException { + public void postCheckout(AbstractBuild build, Launcher launcher, FilePath workspace, BuildListener listener) throws IOException, InterruptedException { if (Util.isOverridden(SCM.class, getClass(), "postCheckout", Run.class, Launcher.class, FilePath.class, TaskListener.class)) { postCheckout((Run) build, launcher, workspace, listener); } @@ -571,9 +574,9 @@ public void postCheckout(AbstractBuild build, Launcher launcher, FilePath w * * @since 2.60 */ - public void buildEnvironment(@NonNull Run build, @NonNull Map env) { + public void buildEnvironment(@NonNull Run build, @NonNull Map env) { if (build instanceof AbstractBuild) { - buildEnvVars((AbstractBuild)build, env); + buildEnvVars((AbstractBuild) build, env); } } @@ -581,7 +584,7 @@ public void buildEnvironment(@NonNull Run build, @NonNull Map build, Map env) { + public void buildEnvVars(AbstractBuild build, Map env) { if (Util.isOverridden(SCM.class, getClass(), "buildEnvironment", Run.class, Map.class)) { buildEnvironment(build, env); } @@ -640,16 +643,16 @@ public FilePath getModuleRoot(FilePath workspace, AbstractBuild build) { // For backwards compatibility, call the one argument version of the method. return getModuleRoot(workspace); } - + /** * @deprecated since 1.382 * Use/override {@link #getModuleRoot(FilePath, AbstractBuild)} instead. */ @Deprecated public FilePath getModuleRoot(FilePath workspace) { - if (Util.isOverridden(SCM.class,getClass(),"getModuleRoot", FilePath.class,AbstractBuild.class)) + if (Util.isOverridden(SCM.class, getClass(), "getModuleRoot", FilePath.class, AbstractBuild.class)) // if the subtype already implements newer getModuleRoot(FilePath,AbstractBuild), call that. - return getModuleRoot(workspace,null); + return getModuleRoot(workspace, null); return workspace; } @@ -688,23 +691,23 @@ public FilePath getModuleRoot(FilePath workspace) { * @since 1.382 */ public FilePath[] getModuleRoots(FilePath workspace, AbstractBuild build) { - if (Util.isOverridden(SCM.class,getClass(),"getModuleRoots", FilePath.class)) + if (Util.isOverridden(SCM.class, getClass(), "getModuleRoots", FilePath.class)) // if the subtype derives legacy getModuleRoots(FilePath), delegate to it return getModuleRoots(workspace); // otherwise the default implementation - return new FilePath[]{getModuleRoot(workspace,build)}; + return new FilePath[]{getModuleRoot(workspace, build)}; } - + /** * @deprecated as of 1.382. * Use/derive from {@link #getModuleRoots(FilePath, AbstractBuild)} instead. */ @Deprecated public FilePath[] getModuleRoots(FilePath workspace) { - if (Util.isOverridden(SCM.class,getClass(),"getModuleRoots", FilePath.class, AbstractBuild.class)) + if (Util.isOverridden(SCM.class, getClass(), "getModuleRoots", FilePath.class, AbstractBuild.class)) // if the subtype already derives newer getModuleRoots(FilePath,AbstractBuild), delegate to it - return getModuleRoots(workspace,null); + return getModuleRoots(workspace, null); // otherwise the default implementation return new FilePath[] { getModuleRoot(workspace), }; @@ -739,14 +742,14 @@ protected final boolean createEmptyChangeLog(File changelogFile, BuildListener l * @since 1.568 */ protected final void createEmptyChangeLog(@NonNull File changelogFile, @NonNull TaskListener listener, @NonNull String rootTag) throws IOException { - try (FileWriter w = new FileWriter(changelogFile)) { - w.write("<"+rootTag +"/>"); + try (Writer w = Files.newBufferedWriter(Util.fileToPath(changelogFile), Charset.defaultCharset())) { + w.write("<" + rootTag + "/>"); } } protected final String nullify(String s) { - if(s==null) return null; - if(s.trim().length()==0) return null; + if (s == null) return null; + if (s.trim().length() == 0) return null; return s; } @@ -755,12 +758,12 @@ protected final String nullify(String s) { * Permission to create new tags. * @since 1.171 */ - public static final Permission TAG = new Permission(PERMISSIONS,"Tag",Messages._SCM_TagPermission_Description(),Permission.CREATE, PermissionScope.ITEM); + public static final Permission TAG = new Permission(PERMISSIONS, "Tag", Messages._SCM_TagPermission_Description(), Permission.CREATE, PermissionScope.ITEM); /** * Returns all the registered {@link SCMDescriptor}s. */ - public static DescriptorExtensionList> all() { + public static DescriptorExtensionList> all() { return Jenkins.get().getDescriptorList(SCM.class); } @@ -772,16 +775,16 @@ public static DescriptorExtensionList> all() { * @since 1.568 */ public static List> _for(@CheckForNull final Job project) { - if(project==null) return all(); - + if (project == null) return all(); + final Descriptor pd = Jenkins.get().getDescriptor((Class) project.getClass()); List> r = new ArrayList<>(); for (SCMDescriptor scmDescriptor : all()) { - if(!scmDescriptor.isApplicable(project)) continue; + if (!scmDescriptor.isApplicable(project)) continue; if (pd instanceof TopLevelItemDescriptor) { TopLevelItemDescriptor apd = (TopLevelItemDescriptor) pd; - if(!apd.isApplicable(scmDescriptor)) continue; + if (!apd.isApplicable(scmDescriptor)) continue; } r.add(scmDescriptor); diff --git a/core/src/main/java/hudson/scm/SCMDescriptor.java b/core/src/main/java/hudson/scm/SCMDescriptor.java index 7a9465b88e066..b9a600a9a3245 100644 --- a/core/src/main/java/hudson/scm/SCMDescriptor.java +++ b/core/src/main/java/hudson/scm/SCMDescriptor.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scm; import static java.util.logging.Level.WARNING; @@ -52,7 +53,7 @@ public abstract class SCMDescriptor extends Descriptor { * that type. Otherwise this SCM will not have any repository browser. */ public final transient Class repositoryBrowser; - + private final transient AtomicInteger atomicGeneration = new AtomicInteger(1); protected SCMDescriptor(Class clazz, Class repositoryBrowser) { @@ -101,13 +102,13 @@ public void incrementGeneration() { public void load() { Class rb = repositoryBrowser; super.load(); - if (repositoryBrowser!=rb) { // XStream may overwrite even the final field. + if (repositoryBrowser != rb) { // XStream may overwrite even the final field. try { Field f = SCMDescriptor.class.getDeclaredField("repositoryBrowser"); f.setAccessible(true); - f.set(this,rb); + f.set(this, rb); } catch (NoSuchFieldException | IllegalAccessException e) { - LOGGER.log(WARNING, "Failed to overwrite the repositoryBrowser field",e); + LOGGER.log(WARNING, "Failed to overwrite the repositoryBrowser field", e); } } } @@ -163,7 +164,7 @@ public boolean isApplicable(AbstractProject project) { * can be empty but never null. */ public List>> getBrowserDescriptors() { - if(repositoryBrowser==null) return Collections.emptyList(); + if (repositoryBrowser == null) return Collections.emptyList(); return RepositoryBrowsers.filter(repositoryBrowser); } diff --git a/core/src/main/java/hudson/scm/SCMS.java b/core/src/main/java/hudson/scm/SCMS.java index 56c9d405e4db8..a8fd4ddc4dc11 100644 --- a/core/src/main/java/hudson/scm/SCMS.java +++ b/core/src/main/java/hudson/scm/SCMS.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scm; import hudson.Extension; @@ -33,7 +34,7 @@ /** * List of all installed SCMs. - * + * * @author Kohsuke Kawaguchi */ public class SCMS { @@ -67,7 +68,7 @@ public static SCM parseSCM(StaplerRequest req, AbstractProject target) throws Fo */ @Deprecated public static SCM parseSCM(StaplerRequest req) throws FormException, ServletException { - return parseSCM(req,null); + return parseSCM(req, null); } } diff --git a/core/src/main/java/hudson/scm/browsers/QueryBuilder.java b/core/src/main/java/hudson/scm/browsers/QueryBuilder.java index f80ca8a8068e3..06d933aa7ef34 100644 --- a/core/src/main/java/hudson/scm/browsers/QueryBuilder.java +++ b/core/src/main/java/hudson/scm/browsers/QueryBuilder.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scm.browsers; /** @@ -36,8 +37,8 @@ public QueryBuilder(String s) { } public QueryBuilder add(String s) { - if(s==null) return this; // nothing to add - if(buf.length()==0) buf.append('?'); + if (s == null) return this; // nothing to add + if (buf.length() == 0) buf.append('?'); else buf.append('&'); buf.append(s); return this; diff --git a/core/src/main/java/hudson/search/CollectionSearchIndex.java b/core/src/main/java/hudson/search/CollectionSearchIndex.java index 35c4e8f11ca1a..b6bb423d40f42 100644 --- a/core/src/main/java/hudson/search/CollectionSearchIndex.java +++ b/core/src/main/java/hudson/search/CollectionSearchIndex.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.search; import edu.umd.cs.findbugs.annotations.NonNull; @@ -31,7 +32,7 @@ /** * {@link SearchIndex} built on a {@link Map}. - * + * * @author Kohsuke Kawaguchi */ public abstract class CollectionSearchIndex implements SearchIndex { @@ -55,21 +56,21 @@ protected Iterable allAsIterable() { @Override public void find(String token, List result) { SearchItem p = get(token); - if(p!=null) + if (p != null) result.add(p); } @Override public void suggest(String token, List result) { boolean isCaseSensitive = UserSearchProperty.isCaseInsensitive(); - if(isCaseSensitive){ + if (isCaseSensitive) { token = token.toLowerCase(); } for (SMT o : allAsIterable()) { String name = getName(o); - if(isCaseSensitive) - name=name.toLowerCase(); - if(o!=null && name.contains(token)) + if (isCaseSensitive) + name = name.toLowerCase(); + if (o != null && name.contains(token)) result.add(o); } } diff --git a/core/src/main/java/hudson/search/FixedSet.java b/core/src/main/java/hudson/search/FixedSet.java index 7c44604251e88..dfe413fbf7377 100644 --- a/core/src/main/java/hudson/search/FixedSet.java +++ b/core/src/main/java/hudson/search/FixedSet.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.search; import java.util.Arrays; diff --git a/core/src/main/java/hudson/search/ParsedQuickSilver.java b/core/src/main/java/hudson/search/ParsedQuickSilver.java index 6ecb80b3c8032..1671665b9472e 100644 --- a/core/src/main/java/hudson/search/ParsedQuickSilver.java +++ b/core/src/main/java/hudson/search/ParsedQuickSilver.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.search; import java.beans.Introspector; @@ -39,12 +40,12 @@ * @author Kohsuke Kawaguchi */ final class ParsedQuickSilver { - private static final Map TABLE = new HashMap<>(); + private static final Map TABLE = new HashMap<>(); static synchronized ParsedQuickSilver get(Class clazz) { ParsedQuickSilver pqs = TABLE.get(clazz); - if(pqs==null) - TABLE.put(clazz,pqs = new ParsedQuickSilver(clazz)); + if (pqs == null) + TABLE.put(clazz, pqs = new ParsedQuickSilver(clazz)); return pqs; } @@ -55,24 +56,24 @@ private ParsedQuickSilver(Class clazz) { for (Method m : clazz.getMethods()) { qs = m.getAnnotation(QuickSilver.class); - if(qs!=null) { + if (qs != null) { String url = stripGetPrefix(m); - if(qs.value().length==0) - getters.add(new MethodGetter(url,splitName(url),m)); + if (qs.value().length == 0) + getters.add(new MethodGetter(url, splitName(url), m)); else { for (String name : qs.value()) - getters.add(new MethodGetter(url,name,m)); + getters.add(new MethodGetter(url, name, m)); } } } for (Field f : clazz.getFields()) { qs = f.getAnnotation(QuickSilver.class); - if(qs!=null) { - if(qs.value().length==0) - getters.add(new FieldGetter(f.getName(),splitName(f.getName()),f)); + if (qs != null) { + if (qs.value().length == 0) + getters.add(new FieldGetter(f.getName(), splitName(f.getName()), f)); else { for (String name : qs.value()) - getters.add(new FieldGetter(f.getName(),name,f)); + getters.add(new FieldGetter(f.getName(), name, f)); } } } @@ -82,9 +83,9 @@ private ParsedQuickSilver(Class clazz) { * Convert names like "abcDefGhi" to "abc def ghi". */ private String splitName(String url) { - StringBuilder buf = new StringBuilder(url.length()+5); - for(String token : url.split("(?<=[a-z])(?=[A-Z])")) { - if(buf.length()>0) buf.append(' '); + StringBuilder buf = new StringBuilder(url.length() + 5); + for (String token : url.split("(?<=[a-z])(?=[A-Z])")) { + if (buf.length() > 0) buf.append(' '); buf.append(Introspector.decapitalize(token)); } return buf.toString(); @@ -92,7 +93,7 @@ private String splitName(String url) { private String stripGetPrefix(Method m) { String n = m.getName(); - if(n.startsWith("get")) + if (n.startsWith("get")) n = Introspector.decapitalize(n.substring(3)); return n; } @@ -180,7 +181,7 @@ public SearchItemCategory getSearchItemCategory() { @Override public SearchIndex getSearchIndex() { Object child = getter.get(instance); - if(child==null) return SearchIndex.EMPTY; + if (child == null) return SearchIndex.EMPTY; return ((SearchableModelObject) child).getSearchIndex(); } }); diff --git a/core/src/main/java/hudson/search/QuickSilver.java b/core/src/main/java/hudson/search/QuickSilver.java index 0d78712dc33ea..ad214694f5efc 100644 --- a/core/src/main/java/hudson/search/QuickSilver.java +++ b/core/src/main/java/hudson/search/QuickSilver.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.search; import static java.lang.annotation.ElementType.FIELD; @@ -43,7 +44,7 @@ *

    * Such getter/field indicates an edge in the search graph, and will be added * automatically by {@link SearchIndexBuilder#addAllAnnotations(SearchableModelObject)} - * to a search index. + * to a search index. * * @author Kohsuke Kawaguchi */ diff --git a/core/src/main/java/hudson/search/Search.java b/core/src/main/java/hudson/search/Search.java index 44967bc289aac..b4ed20c1d8f30 100644 --- a/core/src/main/java/hudson/search/Search.java +++ b/core/src/main/java/hudson/search/Search.java @@ -1,19 +1,19 @@ /* * The MIT License - * + * * Copyright (c) 2004-2011, Sun Microsystems, Inc., Kohsuke Kawaguchi, * Yahoo!, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.search; import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; @@ -69,21 +70,21 @@ public class Search implements StaplerProxy { public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { List l = req.getAncestors(); - for( int i=l.size()-1; i>=0; i-- ) { + for (int i = l.size() - 1; i >= 0; i--) { Ancestor a = l.get(i); if (a.getObject() instanceof SearchableModelObject) { SearchableModelObject smo = (SearchableModelObject) a.getObject(); - if(LOGGER.isLoggable(Level.FINE)){ - LOGGER.fine(String.format("smo.displayName=%s, searchName=%s",smo.getDisplayName(), smo.getSearchName())); + if (LOGGER.isLoggable(Level.FINE)) { + LOGGER.fine(String.format("smo.displayName=%s, searchName=%s", smo.getDisplayName(), smo.getSearchName())); } SearchIndex index = smo.getSearchIndex(); String query = req.getParameter("q"); - if(query!=null) { + if (query != null) { SuggestedItem target = find(index, query, smo); - if(target!=null) { + if (target != null) { // found - rsp.sendRedirect2(req.getContextPath()+target.getUrl()); + rsp.sendRedirect2(req.getContextPath() + target.getUrl()); return; } } @@ -92,7 +93,7 @@ public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException, // no exact match. show the suggestions rsp.setStatus(SC_NOT_FOUND); - req.getView(this,"search-failed.jelly").forward(req,rsp); + req.getView(this, "search-failed.jelly").forward(req, rsp); } /** @@ -130,7 +131,7 @@ public void doSuggest(StaplerRequest req, StaplerResponse rsp, @QueryParameter S item.item.getSearchItemIcon(), item.item.getSearchItemCategory())); - rsp.serveExposedBean(req,r,Flavor.JSON); + rsp.serveExposedBean(req, r, Flavor.JSON); } /** @@ -138,7 +139,7 @@ public void doSuggest(StaplerRequest req, StaplerResponse rsp, @QueryParameter S * * @return * can be empty but never null. The size of the list is always smaller than - * a certain threshold to avoid showing too many options. + * a certain threshold to avoid showing too many options. */ public SearchResult getSuggestions(StaplerRequest req, String query) { Set paths = new HashSet<>(); // paths already added, to control duplicates @@ -146,11 +147,11 @@ public SearchResult getSuggestions(StaplerRequest req, String query) { int max = req.hasParameter("max") ? Integer.parseInt(req.getParameter("max")) : 100; SearchableModelObject smo = findClosestSearchableModelObject(req); for (SuggestedItem i : suggest(makeSuggestIndex(req), query, smo)) { - if(r.size()>=max) { + if (r.size() >= max) { r.hasMoreResults = true; break; } - if(paths.add(i.getPath())) + if (paths.add(i.getPath())) r.add(i); } return r; @@ -158,10 +159,10 @@ public SearchResult getSuggestions(StaplerRequest req, String query) { private @CheckForNull SearchableModelObject findClosestSearchableModelObject(StaplerRequest req) { List l = req.getAncestors(); - for( int i=l.size()-1; i>=0; i-- ) { + for (int i = l.size() - 1; i >= 0; i--) { Ancestor a = l.get(i); if (a.getObject() instanceof SearchableModelObject) { - return (SearchableModelObject)a.getObject(); + return (SearchableModelObject) a.getObject(); } } return null; @@ -197,11 +198,12 @@ public static class Result { public List suggestions = new ArrayList<>(); } - @ExportedBean(defaultVisibility=999) + @ExportedBean(defaultVisibility = 999) public static class Item { @Exported public String url; @Exported + @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", justification = "read by Stapler") public String name; @Exported public String description; @@ -251,7 +253,7 @@ void find(SearchIndex index, String token, List result) { * When there are multiple suggested items, this method can narrow down the resultset * to the SuggestedItem that has a url that contains the query. This is useful is one * job has a display name that matches another job's project name. - * @param r A list of Suggested items. It is assumed that there is at least one + * @param r A list of Suggested items. It is assumed that there is at least one * SuggestedItem in r. * @param query A query string * @return Returns the SuggestedItem which has a search url that contains the query. @@ -259,20 +261,20 @@ void find(SearchIndex index, String token, List result) { * SuggestedItem in the List is returned. */ static SuggestedItem findClosestSuggestedItem(List r, String query) { - for(SuggestedItem curItem : r) { - if(LOGGER.isLoggable(Level.FINE)) { + for (SuggestedItem curItem : r) { + if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(String.format("item's searchUrl:%s;query=%s", curItem.item.getSearchUrl(), query)); } - if(curItem.item.getSearchUrl().contains(Util.rawEncode(query))) { + if (curItem.item.getSearchUrl().contains(Util.rawEncode(query))) { return curItem; } } - + // couldn't find an item with the query in the url so just // return the first one - return r.get(0); + return r.get(0); } - + /** * @deprecated Use {@link Search#find(SearchIndex, String, SearchableModelObject)} instead. */ @@ -280,7 +282,7 @@ static SuggestedItem findClosestSuggestedItem(List r, String quer public static SuggestedItem find(SearchIndex index, String query) { return find(index, query, null); } - + /** * Performs a search and returns the match, or null if no match was found * or more than one match was found. @@ -288,10 +290,10 @@ public static SuggestedItem find(SearchIndex index, String query) { */ public static SuggestedItem find(SearchIndex index, String query, SearchableModelObject searchContext) { List r = find(Mode.FIND, index, query, searchContext); - if(r.isEmpty()){ + if (r.isEmpty()) { return null; } - else if(1==r.size()){ + else if (1 == r.size()) { return r.get(0); } else { @@ -299,11 +301,11 @@ else if(1==r.size()){ // contains the query as this is probably the job's name return findClosestSuggestedItem(r, query); } - + } /** - * @deprecated use {@link Search#suggest(SearchIndex, String, SearchableModelObject)} instead. + * @deprecated use {@link Search#suggest(SearchIndex, String, SearchableModelObject)} instead. */ @Deprecated public static List suggest(SearchIndex index, final String tokenList) { @@ -315,7 +317,7 @@ public static List suggest(SearchIndex index, final String tokenL */ public static List suggest(SearchIndex index, final String tokenList, SearchableModelObject searchContext) { - class Tag implements Comparable{ + class Tag implements Comparable { final SuggestedItem item; final int distance; /** If the path to this suggestion starts with the token list, 1. Otherwise 0. */ @@ -323,16 +325,15 @@ class Tag implements Comparable{ Tag(SuggestedItem i) { item = i; - distance = EditDistance.editDistance(i.getPath(),tokenList); - prefixMatch = i.getPath().startsWith(tokenList)?1:0; + distance = EditDistance.editDistance(i.getPath(), tokenList); + prefixMatch = i.getPath().startsWith(tokenList) ? 1 : 0; } - @SuppressFBWarnings(value = "EQ_COMPARETO_USE_OBJECT_EQUALS", justification = "TODO needs triage") @Override public int compareTo(Tag that) { - int r = this.prefixMatch -that.prefixMatch; - if(r!=0) return -r; // ones with head match should show up earlier - return this.distance-that.distance; + int r = this.prefixMatch - that.prefixMatch; + if (r != 0) return -r; // ones with head match should show up earlier + return this.distance - that.distance; } } @@ -340,7 +341,7 @@ public int compareTo(Tag that) { List items = find(Mode.SUGGEST, index, tokenList, searchContext); // sort them - for( SuggestedItem i : items) + for (SuggestedItem i : items) buf.add(new Tag(i)); Collections.sort(buf); items.clear(); @@ -354,7 +355,7 @@ static final class TokenList { private final String[] tokens; TokenList(String tokenList) { - tokens = tokenList!=null ? tokenList.split("(?<=\\s)(?=\\S)") : MemoryReductionUtil.EMPTY_STRING_ARRAY; + tokens = tokenList != null ? tokenList.split("(?<=\\s)(?=\\S)") : MemoryReductionUtil.EMPTY_STRING_ARRAY; } public int length() { return tokens.length; } @@ -369,67 +370,67 @@ public List subSequence(final int start) { @Override public String get(int index) { StringBuilder buf = new StringBuilder(); - for(int i=start; i<=start+index; i++ ) + for (int i = start; i <= start + index; i++) buf.append(tokens[i]); return buf.toString().trim(); } @Override public int size() { - return tokens.length-start; + return tokens.length - start; } }; } - - + + @Override public String toString() { StringBuilder s = new StringBuilder("TokenList{"); - for(String token : tokens) { + for (String token : tokens) { s.append(token); s.append(","); } s.append('}'); - + return s.toString(); } } private static List find(Mode m, SearchIndex index, String tokenList, SearchableModelObject searchContext) { TokenList tokens = new TokenList(tokenList); - if(tokens.length()==0) return Collections.emptyList(); // no tokens given + if (tokens.length() == 0) return Collections.emptyList(); // no tokens given - List[] paths = new List[tokens.length()+1]; // we won't use [0]. - for(int i=1;i<=tokens.length();i++) + List[] paths = new List[tokens.length() + 1]; // we won't use [0]. + for (int i = 1; i <= tokens.length(); i++) paths[i] = new ArrayList<>(); List items = new ArrayList<>(); // items found in 1 step LOGGER.log(Level.FINE, "tokens={0}", tokens); - + // first token - int w=1; // width of token + int w = 1; // width of token for (String token : tokens.subSequence(0)) { items.clear(); - m.find(index,token,items); + m.find(index, token, items); for (SearchItem si : items) { - paths[w].add(SuggestedItem.build(searchContext ,si)); + paths[w].add(SuggestedItem.build(searchContext, si)); LOGGER.log(Level.FINE, "found search item: {0}", si.getSearchName()); } w++; } // successive tokens - for (int j=1; j result) { // no item to contribute } + @Override public void suggest(String token, List result) { // nothing to suggest diff --git a/core/src/main/java/hudson/search/SearchIndexBuilder.java b/core/src/main/java/hudson/search/SearchIndexBuilder.java index b907e02884077..4cf082598b102 100644 --- a/core/src/main/java/hudson/search/SearchIndexBuilder.java +++ b/core/src/main/java/hudson/search/SearchIndexBuilder.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.search; import hudson.model.AbstractModelObject; @@ -45,7 +46,7 @@ public final class SearchIndexBuilder { * Adds all {@link QuickSilver}-annotated properties to the search index. */ public SearchIndexBuilder addAllAnnotations(SearchableModelObject o) { - ParsedQuickSilver.get(o.getClass()).addTo(this,o); + ParsedQuickSilver.get(o.getClass()).addTo(this, o); return this; } @@ -53,23 +54,23 @@ public SearchIndexBuilder addAllAnnotations(SearchableModelObject o) { * Short for {@code add(urlAsWellAsName,urlAsWellAsName)} */ public SearchIndexBuilder add(String urlAsWellAsName) { - return add(urlAsWellAsName,urlAsWellAsName); + return add(urlAsWellAsName, urlAsWellAsName); } /** * Adds a search index under the keyword 'name' to the given URL. * * @param url - * Relative URL from the source of the search index. + * Relative URL from the source of the search index. */ public SearchIndexBuilder add(String url, String name) { - items.add(SearchItems.create(name,url)); + items.add(SearchItems.create(name, url)); return this; } public SearchIndexBuilder add(String url, String... names) { for (String name : names) - add(url,name); + add(url, name); return this; } @@ -79,13 +80,13 @@ public SearchIndexBuilder add(SearchItem item) { } public SearchIndexBuilder add(String url, SearchableModelObject searchable, String name) { - items.add(SearchItems.create(name,url,searchable)); + items.add(SearchItems.create(name, url, searchable)); return this; } public SearchIndexBuilder add(String url, SearchableModelObject searchable, String... names) { for (String name : names) - add(url,searchable,name); + add(url, searchable, name); return this; } @@ -101,7 +102,7 @@ public SearchIndexBuilder add(SearchIndexBuilder index) { public SearchIndex make() { SearchIndex r = new FixedSet(items); for (SearchIndex index : indices) - r = new UnionSearchIndex(r,index); + r = new UnionSearchIndex(r, index); return r; } } diff --git a/core/src/main/java/hudson/search/SearchItem.java b/core/src/main/java/hudson/search/SearchItem.java index 087f4152eee32..072562150aa5f 100644 --- a/core/src/main/java/hudson/search/SearchItem.java +++ b/core/src/main/java/hudson/search/SearchItem.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.search; import hudson.model.Build; @@ -50,6 +51,7 @@ public interface SearchItem { * The path that starts with '/' will be interpreted as the absolute path * (within the context path of Jenkins.) */ + String getSearchUrl(); default String getSearchDescription() { diff --git a/core/src/main/java/hudson/search/SearchItems.java b/core/src/main/java/hudson/search/SearchItems.java index 39f62acc2068f..ce9cd91a37b35 100644 --- a/core/src/main/java/hudson/search/SearchItems.java +++ b/core/src/main/java/hudson/search/SearchItems.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.search; /** @@ -28,7 +29,7 @@ */ public class SearchItems { public static SearchItem create(String searchName, String url) { - return create(searchName,url, SearchIndex.EMPTY); + return create(searchName, url, SearchIndex.EMPTY); } public static SearchItem create(final String searchName, final String url, final SearchIndex children) { diff --git a/core/src/main/java/hudson/search/SearchableModelObject.java b/core/src/main/java/hudson/search/SearchableModelObject.java index ebc16348d980e..52bdcc47a587b 100644 --- a/core/src/main/java/hudson/search/SearchableModelObject.java +++ b/core/src/main/java/hudson/search/SearchableModelObject.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.search; import hudson.model.ModelObject; diff --git a/core/src/main/java/hudson/search/SuggestedItem.java b/core/src/main/java/hudson/search/SuggestedItem.java index 31e5956ce4ed7..86dbc36b5fe34 100644 --- a/core/src/main/java/hudson/search/SuggestedItem.java +++ b/core/src/main/java/hudson/search/SuggestedItem.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.search; import hudson.model.Item; @@ -37,7 +38,7 @@ public class SuggestedItem { private String path; public SuggestedItem(SearchItem top) { - this(null,top); + this(null, top); } public SuggestedItem(SuggestedItem parent, SearchItem item) { @@ -46,18 +47,18 @@ public SuggestedItem(SuggestedItem parent, SearchItem item) { } public String getPath() { - if(path!=null) return path; - if(parent==null) - return path=item.getSearchName(); + if (path != null) return path; + if (parent == null) + return path = item.getSearchName(); else { StringBuilder buf = new StringBuilder(); getPath(buf); - return path=buf.toString(); + return path = buf.toString(); } } private void getPath(StringBuilder buf) { - if(parent==null) + if (parent == null) buf.append(item.getSearchName()); else { parent.getPath(buf); @@ -71,23 +72,23 @@ private void getPath(StringBuilder buf) { * URL that starts with '/' but doesn't end with '/'. * The path is the combined path from the {@link SearchIndex} where the search started * to the final item found. Thus to convert to the actual URL, the caller would need - * to prepend the URL of the object where the search started. + * to prepend the URL of the object where the search started. */ public String getUrl() { StringBuilder buf = new StringBuilder(); getUrl(buf); return buf.toString(); } - + private static SuggestedItem build(SearchableModelObject searchContext, Item top) { ItemGroup parent = top.getParent(); if (parent instanceof Item) { - Item parentItem = (Item)parent; + Item parentItem = (Item) parent; return new SuggestedItem(build(searchContext, parentItem), top); } return new SuggestedItem(top); } - + /** * Given a SearchItem, builds a SuggestedItem hierarchy by looking up parent items (if applicable). * This allows search results for items not contained within the same {@link ItemGroup} to be distinguished. @@ -96,21 +97,21 @@ private static SuggestedItem build(SearchableModelObject searchContext, Item top */ public static SuggestedItem build(SearchableModelObject searchContext, SearchItem si) { if (si instanceof Item) { - return build(searchContext, (Item)si); + return build(searchContext, (Item) si); } return new SuggestedItem(si); } private void getUrl(StringBuilder buf) { - if(parent!=null) { + if (parent != null) { parent.getUrl(buf); } String f = item.getSearchUrl(); - if(f.startsWith("/")) { + if (f.startsWith("/")) { buf.setLength(0); buf.append(f); } else { - if(buf.length()==0 || buf.charAt(buf.length()-1)!='/') + if (buf.length() == 0 || buf.charAt(buf.length() - 1) != '/') buf.append('/'); buf.append(f); } diff --git a/core/src/main/java/hudson/search/UnionSearchIndex.java b/core/src/main/java/hudson/search/UnionSearchIndex.java index 6a7a625924f29..d32deb5edfe68 100644 --- a/core/src/main/java/hudson/search/UnionSearchIndex.java +++ b/core/src/main/java/hudson/search/UnionSearchIndex.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.search; import java.util.List; @@ -32,7 +33,7 @@ */ public class UnionSearchIndex implements SearchIndex { public static SearchIndex combine(SearchIndex... sets) { - SearchIndex p=EMPTY; + SearchIndex p = EMPTY; for (SearchIndex q : sets) { // allow some of the inputs to be null, // and also recognize EMPTY @@ -40,13 +41,13 @@ public static SearchIndex combine(SearchIndex... sets) { if (p == EMPTY) p = q; else - p = new UnionSearchIndex(p,q); + p = new UnionSearchIndex(p, q); } } return p; } - private final SearchIndex lhs,rhs; + private final SearchIndex lhs, rhs; public UnionSearchIndex(SearchIndex lhs, SearchIndex rhs) { this.lhs = lhs; @@ -55,13 +56,13 @@ public UnionSearchIndex(SearchIndex lhs, SearchIndex rhs) { @Override public void find(String token, List result) { - lhs.find(token,result); - rhs.find(token,result); + lhs.find(token, result); + rhs.find(token, result); } @Override public void suggest(String token, List result) { - lhs.suggest(token,result); - rhs.suggest(token,result); + lhs.suggest(token, result); + rhs.suggest(token, result); } } diff --git a/core/src/main/java/hudson/search/UserSearchProperty.java b/core/src/main/java/hudson/search/UserSearchProperty.java index 7e5d704fd7470..50813ce3c79b4 100644 --- a/core/src/main/java/hudson/search/UserSearchProperty.java +++ b/core/src/main/java/hudson/search/UserSearchProperty.java @@ -23,8 +23,8 @@ public UserSearchProperty(boolean insensitiveSearch) { public boolean getInsensitiveSearch() { return insensitiveSearch; } - - public static boolean isCaseInsensitive(){ + + public static boolean isCaseInsensitive() { User user = User.current(); if (user == null) { @@ -33,7 +33,7 @@ public static boolean isCaseInsensitive(){ return user.getProperty(UserSearchProperty.class).getInsensitiveSearch(); } - + @Extension @Symbol("search") public static final class DescriptorImpl extends UserPropertyDescriptor { diff --git a/core/src/main/java/hudson/security/ACL.java b/core/src/main/java/hudson/security/ACL.java index 47ff187077e7f..039820ef22f3a 100644 --- a/core/src/main/java/hudson/security/ACL.java +++ b/core/src/main/java/hudson/security/ACL.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -72,11 +73,11 @@ public final void checkPermission(@NonNull Permission p) { if (a.equals(SYSTEM2)) { // perhaps redundant given check in AccessControlled return; } - if (!hasPermission2(a,p)) { + if (!hasPermission2(a, p)) { while (!p.enabled && p.impliedBy != null) { p = p.impliedBy; } - throw new AccessDeniedException3(a,p); + throw new AccessDeniedException3(a, p); } } @@ -236,7 +237,7 @@ public final void checkCreatePermission(@NonNull ItemGroup c, } if (!hasCreatePermission2(a, c, d)) { throw new AccessDeniedException(Messages.AccessDeniedException2_MissingPermission(a.getName(), - Item.CREATE.group.title+"/"+Item.CREATE.name + Item.CREATE + "/" + d.getDisplayName())); + Item.CREATE.group.title + "/" + Item.CREATE.name + Item.CREATE + "/" + d.getDisplayName())); } } /** @@ -251,6 +252,7 @@ public final void checkCreatePermission(@NonNull ItemGroup c, * if the user doesn't have the permission. * @since 2.266 */ + public boolean hasCreatePermission2(@NonNull Authentication a, @NonNull ItemGroup c, @NonNull TopLevelItemDescriptor d) { if (Util.isOverridden(ACL.class, getClass(), "hasCreatePermission", org.acegisecurity.Authentication.class, ItemGroup.class, TopLevelItemDescriptor.class)) { @@ -355,7 +357,7 @@ public String toString() { */ public static final Sid ANONYMOUS = new PrincipalSid(ANONYMOUS_USERNAME); - protected static final Sid[] AUTOMATIC_SIDS = new Sid[]{EVERYONE,ANONYMOUS}; + static final Sid[] AUTOMATIC_SIDS = new Sid[]{EVERYONE, ANONYMOUS}; /** * The username for the system user @@ -370,7 +372,7 @@ public String toString() { * of acting on behalf of an user, such as doing builds. * @since 2.266 */ - public static final Authentication SYSTEM2 = new UsernamePasswordAuthenticationToken(SYSTEM_USERNAME,"SYSTEM"); + public static final Authentication SYSTEM2 = new UsernamePasswordAuthenticationToken(SYSTEM_USERNAME, "SYSTEM"); /** * @deprecated use {@link #SYSTEM2} @@ -381,12 +383,12 @@ public String toString() { /** * Changes the {@link Authentication} associated with the current thread * to the specified one, and returns the previous security context. - * + * *

    * When the impersonation is over, be sure to restore the previous authentication * via {@code SecurityContextHolder.setContext(returnValueFromThisMethod)}; * or just use {@link #impersonate2(Authentication, Runnable)}. - * + * *

    * We need to create a new {@link SecurityContext} instead of {@link SecurityContext#setAuthentication(Authentication)} * because the same {@link SecurityContext} object is reused for all the concurrent requests from the same session. @@ -443,7 +445,7 @@ public static void impersonate(@NonNull org.acegisecurity.Authentication auth, @ * @deprecated use try with resources and {@link #as2(Authentication)} */ @Deprecated - public static V impersonate2(Authentication auth, Callable body) throws T { + public static V impersonate2(Authentication auth, Callable body) throws T { SecurityContext old = impersonate2(auth); try { return body.call(); @@ -457,7 +459,7 @@ public static V impersonate2(Authentication auth, Callab * @since 1.587 */ @Deprecated - public static V impersonate(org.acegisecurity.Authentication auth, Callable body) throws T { + public static V impersonate(org.acegisecurity.Authentication auth, Callable body) throws T { return impersonate2(auth.toSpring(), body); } diff --git a/core/src/main/java/hudson/security/ACLContext.java b/core/src/main/java/hudson/security/ACLContext.java index e5b49ff324bee..9873e65f37629 100644 --- a/core/src/main/java/hudson/security/ACLContext.java +++ b/core/src/main/java/hudson/security/ACLContext.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import edu.umd.cs.findbugs.annotations.NonNull; diff --git a/core/src/main/java/hudson/security/AbstractPasswordBasedSecurityRealm.java b/core/src/main/java/hudson/security/AbstractPasswordBasedSecurityRealm.java index 64d579a8c4ab6..055c7151a94a6 100644 --- a/core/src/main/java/hudson/security/AbstractPasswordBasedSecurityRealm.java +++ b/core/src/main/java/hudson/security/AbstractPasswordBasedSecurityRealm.java @@ -180,7 +180,7 @@ protected void additionalAuthenticationChecks(UserDetails userDetails, UsernameP @Override protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { - return doAuthenticate(username,authentication.getCredentials().toString()); + return doAuthenticate(username, authentication.getCredentials().toString()); } } diff --git a/core/src/main/java/hudson/security/AccessControlled.java b/core/src/main/java/hudson/security/AccessControlled.java index a8c8a93a8b57f..b0cb2c2a9b82b 100644 --- a/core/src/main/java/hudson/security/AccessControlled.java +++ b/core/src/main/java/hudson/security/AccessControlled.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import edu.umd.cs.findbugs.annotations.NonNull; diff --git a/core/src/main/java/hudson/security/AccessDeniedException2.java b/core/src/main/java/hudson/security/AccessDeniedException2.java index cdb778473ab44..00daee721251b 100644 --- a/core/src/main/java/hudson/security/AccessDeniedException2.java +++ b/core/src/main/java/hudson/security/AccessDeniedException2.java @@ -28,12 +28,12 @@ public class AccessDeniedException2 extends AccessDeniedException { public final Permission permission; public AccessDeniedException2(Authentication authentication, Permission permission) { - this(null,authentication,permission); + this(null, authentication, permission); } public AccessDeniedException2(Throwable t, Authentication authentication, Permission permission) { super(Messages.AccessDeniedException2_MissingPermission(authentication.getName(), - permission.group.title+"/"+permission.name), t); + permission.group.title + "/" + permission.name), t); this.authentication = authentication; this.permission = permission; } diff --git a/core/src/main/java/hudson/security/AccessDeniedException3.java b/core/src/main/java/hudson/security/AccessDeniedException3.java index 755def42aee6f..82f5d50428cec 100644 --- a/core/src/main/java/hudson/security/AccessDeniedException3.java +++ b/core/src/main/java/hudson/security/AccessDeniedException3.java @@ -29,12 +29,12 @@ public class AccessDeniedException3 extends AccessDeniedException { public final Permission permission; public AccessDeniedException3(Authentication authentication, Permission permission) { - this(null,authentication,permission); + this(null, authentication, permission); } public AccessDeniedException3(Throwable t, Authentication authentication, Permission permission) { super(Messages.AccessDeniedException2_MissingPermission(authentication.getName(), - permission.group.title+"/"+permission.name), t); + permission.group.title + "/" + permission.name), t); this.authentication = authentication; this.permission = permission; } @@ -43,16 +43,16 @@ public AccessDeniedException3(Throwable t, Authentication authentication, Permis * Reports the details of the access failure in HTTP headers to assist diagnosis. */ public void reportAsHeaders(HttpServletResponse rsp) { - rsp.addHeader("X-You-Are-Authenticated-As",authentication.getName()); + rsp.addHeader("X-You-Are-Authenticated-As", authentication.getName()); if (REPORT_GROUP_HEADERS) { for (GrantedAuthority auth : authentication.getAuthorities()) { - rsp.addHeader("X-You-Are-In-Group",auth.getAuthority()); + rsp.addHeader("X-You-Are-In-Group", auth.getAuthority()); } } else { rsp.addHeader("X-You-Are-In-Group-Disabled", "JENKINS-39402: use -Dhudson.security.AccessDeniedException2.REPORT_GROUP_HEADERS=true or use /whoAmI to diagnose"); } rsp.addHeader("X-Required-Permission", permission.getId()); - for (Permission p=permission.impliedBy; p!=null; p=p.impliedBy) { + for (Permission p = permission.impliedBy; p != null; p = p.impliedBy) { rsp.addHeader("X-Permission-Implied-By", p.getId()); } } @@ -63,15 +63,15 @@ public void reportAsHeaders(HttpServletResponse rsp) { * but instead of using HTTP headers, this version is meant to go inside the payload. */ public void report(PrintWriter w) { - w.println("You are authenticated as: "+authentication.getName()); + w.println("You are authenticated as: " + authentication.getName()); w.println("Groups that you are in:"); for (GrantedAuthority auth : authentication.getAuthorities()) { - w.println(" "+auth.getAuthority()); + w.println(" " + auth.getAuthority()); } - w.println("Permission you need to have (but didn't): "+permission.getId()); - for (Permission p=permission.impliedBy; p!=null; p=p.impliedBy) { - w.println(" ... which is implied by: "+p.getId()); + w.println("Permission you need to have (but didn't): " + permission.getId()); + for (Permission p = permission.impliedBy; p != null; p = p.impliedBy) { + w.println(" ... which is implied by: " + p.getId()); } } } diff --git a/core/src/main/java/hudson/security/AccessDeniedHandlerImpl.java b/core/src/main/java/hudson/security/AccessDeniedHandlerImpl.java index 92c45b0f9fe94..68843cfddd16d 100644 --- a/core/src/main/java/hudson/security/AccessDeniedHandlerImpl.java +++ b/core/src/main/java/hudson/security/AccessDeniedHandlerImpl.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import java.io.IOException; @@ -46,13 +47,13 @@ public class AccessDeniedHandlerImpl implements AccessDeniedHandler { @Override public void handle(HttpServletRequest req, HttpServletResponse rsp, AccessDeniedException cause) throws IOException, ServletException { rsp.setStatus(HttpServletResponse.SC_FORBIDDEN); - req.setAttribute("exception",cause); + req.setAttribute("exception", cause); if (cause instanceof AccessDeniedException3) { - ((AccessDeniedException3)cause).reportAsHeaders(rsp); + ((AccessDeniedException3) cause).reportAsHeaders(rsp); } WebApp.get(Jenkins.get().servletContext).getSomeStapler() - .invoke(req,rsp, Jenkins.get(), "/accessDenied"); + .invoke(req, rsp, Jenkins.get(), "/accessDenied"); } } diff --git a/core/src/main/java/hudson/security/AuthenticationManagerProxy.java b/core/src/main/java/hudson/security/AuthenticationManagerProxy.java index 9e48891107780..7de8cb39ab5ec 100644 --- a/core/src/main/java/hudson/security/AuthenticationManagerProxy.java +++ b/core/src/main/java/hudson/security/AuthenticationManagerProxy.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import org.kohsuke.accmod.Restricted; @@ -48,7 +49,7 @@ public class AuthenticationManagerProxy implements AuthenticationManager { public Authentication authenticate(Authentication authentication) throws AuthenticationException { AuthenticationManager m = delegate; // fix the reference we are working with - if(m ==null) + if (m == null) throw new DisabledException("Authentication service is still not ready yet"); else return m.authenticate(authentication); diff --git a/core/src/main/java/hudson/security/AuthenticationProcessingFilter2.java b/core/src/main/java/hudson/security/AuthenticationProcessingFilter2.java index 6764550ab722f..2714ec8eba635 100644 --- a/core/src/main/java/hudson/security/AuthenticationProcessingFilter2.java +++ b/core/src/main/java/hudson/security/AuthenticationProcessingFilter2.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Matthew R. Harrah - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -47,7 +48,7 @@ * Login filter with a change for Jenkins so that * we can pick up the hidden "from" form field defined in {@code login.jelly} * to send the user back to where he came from, after a successful authentication. - * + * * @author Kohsuke Kawaguchi */ @Restricted(NoExternalUse.class) diff --git a/core/src/main/java/hudson/security/AuthorizationStrategy.java b/core/src/main/java/hudson/security/AuthorizationStrategy.java index 84c8599abdf8a..e1ce1596b74ac 100644 --- a/core/src/main/java/hudson/security/AuthorizationStrategy.java +++ b/core/src/main/java/hudson/security/AuthorizationStrategy.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe, Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import edu.umd.cs.findbugs.annotations.NonNull; @@ -63,7 +64,7 @@ * The corresponding {@link Describable} instance will be asked to create a new {@link AuthorizationStrategy} * every time the system configuration is updated. Implementations that keep more state in ACL beyond * the system configuration should use {@link jenkins.model.Jenkins#getAuthorizationStrategy()} to talk to the current - * instance to carry over the state. + * instance to carry over the state. * * @author Kohsuke Kawaguchi * @see SecurityRealm @@ -83,12 +84,12 @@ public abstract class AuthorizationStrategy extends AbstractDescribableImpl project) { - return getACL((Job)project); + public @NonNull ACL getACL(@NonNull AbstractProject project) { + return getACL((Job) project); } - public @NonNull ACL getACL(@NonNull Job project) { - return getRootACL(); + public @NonNull ACL getACL(@NonNull Job project) { + return getRootACL(); } /** @@ -107,13 +108,13 @@ public abstract class AuthorizationStrategy extends AbstractDescribableImpl> all() { + public static @NonNull DescriptorExtensionList> all() { return Jenkins.get().getDescriptorList(AuthorizationStrategy.class); } @@ -201,7 +202,7 @@ public abstract class AuthorizationStrategy extends AbstractDescribableImpl LIST = new DescriptorList<>(AuthorizationStrategy.class); - + /** * {@link AuthorizationStrategy} that implements the semantics * of unsecured Hudson where everyone has full control. diff --git a/core/src/main/java/hudson/security/BasicAuthenticationFilter.java b/core/src/main/java/hudson/security/BasicAuthenticationFilter.java index d481260c3a4ae..dd29dc3004fea 100644 --- a/core/src/main/java/hudson/security/BasicAuthenticationFilter.java +++ b/core/src/main/java/hudson/security/BasicAuthenticationFilter.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -66,7 +67,7 @@ * This causes the container to perform authentication, but there's no way * to find out whether the user has been successfully authenticated or not. * So to find this out, we then redirect the user to - * {@link jenkins.model.Jenkins#doSecured(StaplerRequest, StaplerResponse) {@code /secured/...} page}. + * {@link jenkins.model.Jenkins#doSecured(StaplerRequest, StaplerResponse) /secured/... page}. * *

    * The handler of the above URL checks if the user is authenticated, @@ -85,7 +86,7 @@ *

  • * This A → B → A redirect is a cyclic redirection, so we need to watch out for clients * that detect this as an error. - *
+ * * * @author Kohsuke Kawaguchi */ @@ -98,17 +99,16 @@ public void init(FilterConfig filterConfig) throws ServletException { } @Override - @SuppressWarnings("ACL.impersonate") public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse rsp = (HttpServletResponse) response; String authorization = req.getHeader("Authorization"); String path = req.getServletPath(); - if(authorization==null || req.getUserPrincipal() !=null || path.startsWith("/secured/") + if (authorization == null || req.getUserPrincipal() != null || path.startsWith("/secured/") || !Jenkins.get().isUseSecurity()) { // normal requests, or security not enabled - if(req.getUserPrincipal()!=null) { + if (req.getUserPrincipal() != null) { // before we route this request, integrate the container authentication // to Spring Security. For anonymous users that doesn't have user principal, // AnonymousProcessingFilter that follows this should create @@ -116,7 +116,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha SecurityContextHolder.getContext().setAuthentication(new ContainerAuthentication(req)); } try { - chain.doFilter(request,response); + chain.doFilter(request, response); } finally { SecurityContextHolder.clearContext(); } @@ -130,18 +130,18 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha int idx = uidpassword.indexOf(':'); if (idx >= 0) { username = uidpassword.substring(0, idx); - password = uidpassword.substring(idx+1); + password = uidpassword.substring(idx + 1); } - if(username==null) { + if (username == null) { rsp.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - rsp.setHeader("WWW-Authenticate","Basic realm=\"Jenkins user\""); + rsp.setHeader("WWW-Authenticate", "Basic realm=\"Jenkins user\""); return; } { User u = BasicApiTokenHelper.isConnectingUsingApiToken(username, password); - if(u != null){ + if (u != null) { UserDetails userDetails = u.getUserDetailsForImpersonation2(); Authentication auth = u.impersonate(userDetails); @@ -149,7 +149,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha SecurityContextHolder.getContext().setAuthentication(auth); try { - chain.doFilter(request,response); + chain.doFilter(request, response); } finally { SecurityContextHolder.clearContext(); } @@ -158,24 +158,24 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha } - path = req.getContextPath()+"/secured"+path; + path = req.getContextPath() + "/secured" + path; String q = req.getQueryString(); - if(q!=null) - path += '?'+q; + if (q != null) + path += '?' + q; // prepare a redirect prepareRedirect(rsp, path); // ... but first let the container authenticate this request - RequestDispatcher d = servletContext.getRequestDispatcher("/j_security_check?j_username="+ - URLEncoder.encode(username,"UTF-8")+"&j_password="+URLEncoder.encode(password,"UTF-8")); - d.include(req,rsp); + RequestDispatcher d = servletContext.getRequestDispatcher("/j_security_check?j_username=" + + URLEncoder.encode(username, "UTF-8") + "&j_password=" + URLEncoder.encode(password, "UTF-8")); + d.include(req, rsp); } @SuppressFBWarnings(value = "UNVALIDATED_REDIRECT", justification = "Redirect is validated as processed.") private void prepareRedirect(HttpServletResponse rsp, String path) { rsp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); - rsp.setHeader("Location",path); + rsp.setHeader("Location", path); } @Override diff --git a/core/src/main/java/hudson/security/ChainedServletFilter.java b/core/src/main/java/hudson/security/ChainedServletFilter.java index b717a314f117b..faf9171300a78 100644 --- a/core/src/main/java/hudson/security/ChainedServletFilter.java +++ b/core/src/main/java/hudson/security/ChainedServletFilter.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import java.io.IOException; @@ -74,6 +75,7 @@ public void init(FilterConfig filterConfig) throws ServletException { } private static final Pattern UNINTERESTING_URIS = Pattern.compile("/(images|jsbundles|css|scripts|adjuncts)/|/favicon[.]ico|/ajax"); + @Override public void doFilter(ServletRequest request, ServletResponse response, final FilterChain chain) throws IOException, ServletException { String uri = request instanceof HttpServletRequest ? ((HttpServletRequest) request).getRequestURI() : "?"; @@ -81,20 +83,20 @@ public void doFilter(ServletRequest request, ServletResponse response, final Fil LOGGER.log(level, () -> "starting filter on " + uri); new FilterChain() { - private int position=0; + private int position = 0; // capture the array for thread-safety private final Filter[] filters = ChainedServletFilter.this.filters; @Override public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { - if(position==filters.length) { + if (position == filters.length) { LOGGER.log(level, () -> uri + " end: " + status()); - chain.doFilter(request,response); + chain.doFilter(request, response); } else { Filter next = filters[position++]; try { LOGGER.log(level, () -> uri + " @" + position + " " + next + " »"); - next.doFilter(request,response,this); + next.doFilter(request, response, this); LOGGER.log(level, () -> uri + " @" + position + " " + next + " « success: " + status()); } catch (IOException | ServletException | RuntimeException x) { LOGGER.log(level, () -> uri + " @" + position + " " + next + " « " + x + ": " + status()); @@ -106,7 +108,7 @@ public void doFilter(ServletRequest request, ServletResponse response) throws IO private int status() { return response instanceof HttpServletResponse ? ((HttpServletResponse) response).getStatus() : 0; } - }.doFilter(request,response); + }.doFilter(request, response); } diff --git a/core/src/main/java/hudson/security/CliAuthenticator.java b/core/src/main/java/hudson/security/CliAuthenticator.java index 1fd6d4c7400f9..3b64167c1401a 100644 --- a/core/src/main/java/hudson/security/CliAuthenticator.java +++ b/core/src/main/java/hudson/security/CliAuthenticator.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import java.io.IOException; diff --git a/core/src/main/java/hudson/security/ContainerAuthentication.java b/core/src/main/java/hudson/security/ContainerAuthentication.java index 1a9c344af355c..be7bdc01ab623 100644 --- a/core/src/main/java/hudson/security/ContainerAuthentication.java +++ b/core/src/main/java/hudson/security/ContainerAuthentication.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import java.security.Principal; @@ -58,14 +59,14 @@ public final class ContainerAuthentication implements Authentication { */ public ContainerAuthentication(HttpServletRequest request) { this.principal = request.getUserPrincipal(); - if (principal==null) - throw new IllegalStateException(); // for anonymous users, we just don't call SecurityContextHolder.getContext().setAuthentication. + if (principal == null) + throw new IllegalStateException(); // for anonymous users, we just don't call SecurityContextHolder.getContext().setAuthentication. // Servlet API doesn't provide a way to list up all roles the current user // has, so we need to ask AuthorizationStrategy what roles it is going to check against. List l = new ArrayList<>(); - for( String g : Jenkins.get().getAuthorizationStrategy().getGroups()) { - if(request.isUserInRole(g)) + for (String g : Jenkins.get().getAuthorizationStrategy().getGroups()) { + if (request.isUserInRole(g)) l.add(new SimpleGrantedAuthority(g)); } l.add(SecurityRealm.AUTHENTICATED_AUTHORITY2); diff --git a/core/src/main/java/hudson/security/FederatedLoginService.java b/core/src/main/java/hudson/security/FederatedLoginService.java index 036332c8c7ce0..2d176290d8bee 100644 --- a/core/src/main/java/hudson/security/FederatedLoginService.java +++ b/core/src/main/java/hudson/security/FederatedLoginService.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -182,20 +183,19 @@ public final User locateUser() { * to the caller of your "doXyz" method, it will either render an error page or initiate * a user registration session (provided that {@link SecurityRealm} supports that.) */ - @SuppressWarnings("ACL.impersonate") @NonNull public User signin() throws UnclaimedIdentityException { User u = locateUser(); - if (u!=null) { + if (u != null) { // login as this user UserDetails d = Jenkins.get().getSecurityRealm().loadUserByUsername2(u.getId()); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(d,"",d.getAuthorities()); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(d, "", d.getAuthorities()); token.setDetails(d); SecurityContextHolder.getContext().setAuthentication(token); return u; } else { - // Unassociated identity. + // Unassociated identity. throw new UnclaimedIdentityException(this); } } @@ -210,7 +210,7 @@ public User signin() throws UnclaimedIdentityException { */ public void addToCurrentUser() throws IOException { User u = User.current(); - if (u==null) throw new IllegalStateException("Current request is unauthenticated"); + if (u == null) throw new IllegalStateException("Current request is unauthenticated"); addTo(u); } @@ -220,7 +220,7 @@ public void addToCurrentUser() throws IOException { */ public void addTo(User u) throws IOException { FederatedLoginServiceUserProperty p = u.getProperty(getUserPropertyClass()); - if (p==null) { + if (p == null) { p = (FederatedLoginServiceUserProperty) UserProperty.all().find(getUserPropertyClass()).newInstance(u); u.addProperty(p); } @@ -249,7 +249,7 @@ public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object nod SecurityRealm sr = Jenkins.get().getSecurityRealm(); if (sr.allowsSignup()) { try { - sr.commenceSignup(identity).generateResponse(req,rsp,node); + sr.commenceSignup(identity).generateResponse(req, rsp, node); return; } catch (UnsupportedOperationException e) { // fall through @@ -258,7 +258,7 @@ public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object nod // this security realm doesn't support user registration. // just report an error - req.getView(this,"error").forward(req,rsp); + req.getView(this, "error").forward(req, rsp); } } diff --git a/core/src/main/java/hudson/security/FederatedLoginServiceUserProperty.java b/core/src/main/java/hudson/security/FederatedLoginServiceUserProperty.java index b7dfa881c3a92..0961b3a2d8e03 100644 --- a/core/src/main/java/hudson/security/FederatedLoginServiceUserProperty.java +++ b/core/src/main/java/hudson/security/FederatedLoginServiceUserProperty.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import hudson.model.UserProperty; diff --git a/core/src/main/java/hudson/security/FullControlOnceLoggedInAuthorizationStrategy.java b/core/src/main/java/hudson/security/FullControlOnceLoggedInAuthorizationStrategy.java index df0363ac69cfd..7dbb0ab670216 100644 --- a/core/src/main/java/hudson/security/FullControlOnceLoggedInAuthorizationStrategy.java +++ b/core/src/main/java/hudson/security/FullControlOnceLoggedInAuthorizationStrategy.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,8 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import hudson.model.Descriptor; import java.util.Collections; @@ -47,7 +49,7 @@ public class FullControlOnceLoggedInAuthorizationStrategy extends AuthorizationS * default is to allow it */ private boolean denyAnonymousReadAccess = false; - + @DataBoundConstructor public FullControlOnceLoggedInAuthorizationStrategy() { } @@ -61,14 +63,14 @@ public ACL getRootACL() { public List getGroups() { return Collections.emptyList(); } - + /** * If true, anonymous read access will be allowed */ public boolean isAllowAnonymousRead() { return !denyAnonymousReadAccess; } - + @DataBoundSetter public void setAllowAnonymousRead(boolean allowAnonymousRead) { this.denyAnonymousReadAccess = !allowAnonymousRead; @@ -78,10 +80,10 @@ public void setAllowAnonymousRead(boolean allowAnonymousRead) { private static final SparseACL ANONYMOUS_READ = new SparseACL(null); static { - ANONYMOUS_READ.add(ACL.EVERYONE, Jenkins.ADMINISTER,true); - ANONYMOUS_READ.add(ACL.ANONYMOUS, Jenkins.ADMINISTER,false); - ANONYMOUS_READ.add(ACL.ANONYMOUS, Permission.READ,true); - + ANONYMOUS_READ.add(ACL.EVERYONE, Jenkins.ADMINISTER, true); + ANONYMOUS_READ.add(ACL.ANONYMOUS, Jenkins.ADMINISTER, false); + ANONYMOUS_READ.add(ACL.ANONYMOUS, Permission.READ, true); + AUTHENTICATED_READ.add(ACL.EVERYONE, Jenkins.ADMINISTER, true); AUTHENTICATED_READ.add(ACL.ANONYMOUS, Jenkins.ADMINISTER, false); } @@ -96,6 +98,7 @@ public void setAllowAnonymousRead(boolean allowAnonymousRead) { @Extension @Symbol("loggedInUsersCanDoAnything") public static class DescriptorImpl extends Descriptor { + @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "for backward compatibility") public DescriptorImpl() { DESCRIPTOR = this; } diff --git a/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java b/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java index 17317d2dc61a8..0d29257f18263 100644 --- a/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java +++ b/core/src/main/java/hudson/security/GlobalSecurityConfiguration.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import edu.umd.cs.findbugs.annotations.NonNull; @@ -62,7 +63,7 @@ */ @Extension(ordinal = Integer.MAX_VALUE - 210) @Symbol("securityConfig") public class GlobalSecurityConfiguration extends ManagementLink implements Describable { - + private static final Logger LOGGER = Logger.getLogger(GlobalSecurityConfiguration.class.getName()); public MarkupFormatter getMarkupFormatter() { @@ -100,11 +101,11 @@ public Category getCategory() { public synchronized void doConfigure(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException { // for compatibility reasons, the actual value is stored in Jenkins BulkChange bc = new BulkChange(Jenkins.get()); - try{ + try { boolean result = configure(req, req.getSubmittedForm()); - LOGGER.log(Level.FINE, "security saved: "+result); + LOGGER.log(Level.FINE, "security saved: " + result); Jenkins.get().save(); - FormApply.success(req.getContextPath()+"/manage").generateResponse(req, rsp, null); + FormApply.success(req.getContextPath() + "/manage").generateResponse(req, rsp, null); } finally { bc.commit(); } @@ -117,14 +118,14 @@ public boolean configure(StaplerRequest req, JSONObject json) throws FormExcepti j.setDisableRememberMe(json.optBoolean("disableRememberMe", false)); j.setSecurityRealm(SecurityRealm.all().newInstanceFromRadioList(json, "realm")); - j.setAuthorizationStrategy(AuthorizationStrategy.all().newInstanceFromRadioList(json, "authorization")); + j.setAuthorizationStrategy(AuthorizationStrategy.all().newInstanceFromRadioList(json, "authorization")); if (json.has("markupFormatter")) { j.setMarkupFormatter(req.bindJSON(MarkupFormatter.class, json.getJSONObject("markupFormatter"))); } else { j.setMarkupFormatter(null); } - + // Agent settings if (!isSlaveAgentPortEnforced()) { try { @@ -148,26 +149,26 @@ public boolean configure(StaplerRequest req, JSONObject json) throws FormExcepti // persist all the additional security configs boolean result = true; - for(Descriptor d : Functions.getSortedDescriptorsForGlobalConfigByDescriptor(FILTER)){ - result &= configureDescriptor(req,json,d); + for (Descriptor d : Functions.getSortedDescriptorsForGlobalConfigByDescriptor(FILTER)) { + result &= configureDescriptor(req, json, d); } - + return result; } - + private boolean configureDescriptor(StaplerRequest req, JSONObject json, Descriptor d) throws FormException { // collapse the structure to remain backward compatible with the JSON structure before 1. String name = d.getJsonSafeClassName(); JSONObject js = json.has(name) ? json.getJSONObject(name) : new JSONObject(); // if it doesn't have the property, the method returns invalid null object. json.putAll(js); return d.configure(req, js); - } + } @Override public String getDisplayName() { return getDescriptor().getDisplayName(); } - + @Override public String getDescription() { return Messages.GlobalSecurityConfiguration_Description(); @@ -175,14 +176,14 @@ public String getDescription() { @Override public String getIconFileName() { - return "secure.png"; + return "symbol-lock-closed"; } @Override public String getUrlName() { return "configureSecurity"; } - + @Override public Permission getRequiredPermission() { return Jenkins.SYSTEM_READ; @@ -200,7 +201,7 @@ public Permission getRequiredPermission() { public Descriptor getDescriptor() { return Jenkins.get().getDescriptorOrDie(getClass()); } - + @Extension @Symbol("security") public static final class DescriptorImpl extends Descriptor { @Override diff --git a/core/src/main/java/hudson/security/GroupDetails.java b/core/src/main/java/hudson/security/GroupDetails.java index 543074ef0e3ad..ae94f20a03927 100644 --- a/core/src/main/java/hudson/security/GroupDetails.java +++ b/core/src/main/java/hudson/security/GroupDetails.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import java.util.Set; diff --git a/core/src/main/java/hudson/security/HttpSessionContextIntegrationFilter2.java b/core/src/main/java/hudson/security/HttpSessionContextIntegrationFilter2.java index 51e3a980a9d36..786df5d72879b 100644 --- a/core/src/main/java/hudson/security/HttpSessionContextIntegrationFilter2.java +++ b/core/src/main/java/hudson/security/HttpSessionContextIntegrationFilter2.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import hudson.model.User; diff --git a/core/src/main/java/hudson/security/HudsonAuthenticationEntryPoint.java b/core/src/main/java/hudson/security/HudsonAuthenticationEntryPoint.java index 229c7974b521f..c81c642650ffe 100644 --- a/core/src/main/java/hudson/security/HudsonAuthenticationEntryPoint.java +++ b/core/src/main/java/hudson/security/HudsonAuthenticationEntryPoint.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; @@ -31,11 +32,11 @@ import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.text.MessageFormat; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang.StringUtils; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; import org.springframework.security.authentication.InsufficientAuthenticationException; @@ -53,7 +54,7 @@ * *

* The page that programs see is entirely white, and it auto-redirects, - * so humans wouldn't notice it. + * so humans wouldn't notice it. * * @author Kohsuke Kawaguchi */ @@ -69,7 +70,7 @@ public HudsonAuthenticationEntryPoint(String loginFormUrl) { @Override public void commence(HttpServletRequest req, HttpServletResponse rsp, AuthenticationException reason) throws IOException, ServletException { String requestedWith = req.getHeader("X-Requested-With"); - if("XMLHttpRequest".equals(requestedWith)) { + if ("XMLHttpRequest".equals(requestedWith)) { // container authentication normally relies on session attribute to // remember where the user came from, so concurrent AJAX requests // often ends up sending users back to AJAX pages after successful login. @@ -79,9 +80,9 @@ public void commence(HttpServletRequest req, HttpServletResponse rsp, Authentica } else { // give the opportunity to include the target URL String uriFrom = req.getRequestURI(); - if(!StringUtils.isEmpty(req.getQueryString())) uriFrom += "?" + req.getQueryString(); + if (req.getQueryString() != null && !req.getQueryString().isEmpty()) uriFrom += "?" + req.getQueryString(); String loginForm = req.getContextPath() + loginFormUrl; - loginForm = MessageFormat.format(loginForm, URLEncoder.encode(uriFrom,"UTF-8")); + loginForm = MessageFormat.format(loginForm, URLEncoder.encode(uriFrom, "UTF-8")); req.setAttribute("loginForm", loginForm); rsp.setStatus(SC_FORBIDDEN); @@ -100,21 +101,21 @@ public void commence(HttpServletRequest req, HttpServletResponse rsp, Authentica PrintWriter out; try { - out = new PrintWriter(new OutputStreamWriter(rsp.getOutputStream())); + out = new PrintWriter(new OutputStreamWriter(rsp.getOutputStream(), StandardCharsets.UTF_8)); } catch (IllegalStateException e) { out = rsp.getWriter(); } printResponse(loginForm, out); - if (cause!=null) + if (cause != null) cause.report(out); out.printf( - "-->%n%n"+ + "-->%n%n" + ""); // Turn Off "Show Friendly HTTP Error Messages" Feature on the Server Side. // See http://support.microsoft.com/kb/294807 - for (int i=0; i < 10; i++) + for (int i = 0; i < 10; i++) out.print(" "); out.close(); } @@ -128,8 +129,8 @@ private void printResponse(String loginForm, PrintWriter out) { "" + "" + "%n" + - "%n%n"+ - "Authentication required%n"+ - " \\?\UNC\server\share - path = "\\\\?\\UNC\\" + canonicalPath.substring(2); - } else { - // prefix, canonical path should be normalized and absolute so this should work. - path = "\\\\?\\" + canonicalPath; - } - return Kernel32.INSTANCE.GetFileAttributesW(new WString(path)); + // allow lookup of paths longer than MAX_PATH + // http://msdn.microsoft.com/en-us/library/aa365247(v=VS.85).aspx + String canonicalPath = file.getCanonicalPath(); + String path; + if (canonicalPath.length() < 260) { + // path is short, use as-is + path = canonicalPath; + } else if (canonicalPath.startsWith("\\\\")) { + // network share + // \\server\share --> \\?\UNC\server\share + path = "\\\\?\\UNC\\" + canonicalPath.substring(2); + } else { + // prefix, canonical path should be normalized and absolute so this should work. + path = "\\\\?\\" + canonicalPath; + } + return Kernel32.INSTANCE.GetFileAttributesW(new WString(path)); } /** @@ -98,8 +99,8 @@ public static int getWin32FileAttributes(File file) throws IOException { public static void createSymbolicLink(File symlink, String target, boolean dirLink) throws IOException { if (!Kernel32.INSTANCE.CreateSymbolicLinkW( new WString(symlink.getPath()), new WString(target), - dirLink?Kernel32.SYMBOLIC_LINK_FLAG_DIRECTORY:0)) { - throw new WinIOException("Failed to create a symlink "+symlink+" to "+target); + dirLink ? Kernel32.SYMBOLIC_LINK_FLAG_DIRECTORY : 0)) { + throw new WinIOException("Failed to create a symlink " + symlink + " to " + target); } } @@ -113,7 +114,7 @@ public static boolean isJunctionOrSymlink(File file) throws IOException { public static File getTempDir() { Memory buf = new Memory(1024); - if (Kernel32.INSTANCE.GetTempPathW(512,buf)!=0) {// the first arg is number of wchar + if (Kernel32.INSTANCE.GetTempPathW(512, buf) != 0) { // the first arg is number of wchar return new File(buf.getWideString(0)); } else { return null; @@ -125,7 +126,7 @@ public static File getTempDir() { return (Kernel32) Native.load("kernel32", Kernel32.class); } catch (Throwable e) { LOGGER.log(Level.SEVERE, "Failed to load Kernel32", e); - return InitializationErrorInvocationHandler.create(Kernel32.class,e); + return InitializationErrorInvocationHandler.create(Kernel32.class, e); } } diff --git a/core/src/main/java/hudson/util/jna/Options.java b/core/src/main/java/hudson/util/jna/Options.java index 44f1652408bad..2b75aac9f872b 100644 --- a/core/src/main/java/hudson/util/jna/Options.java +++ b/core/src/main/java/hudson/util/jna/Options.java @@ -13,6 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ + package hudson.util.jna; import static com.sun.jna.Library.OPTION_FUNCTION_MAPPER; @@ -20,6 +21,7 @@ import com.sun.jna.win32.W32APIFunctionMapper; import com.sun.jna.win32.W32APITypeMapper; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.HashMap; import java.util.Map; @@ -27,6 +29,7 @@ * * @author TB */ +@SuppressFBWarnings(value = "MS_OOI_PKGPROTECT", justification = "for backward compatibility") public interface Options { Map UNICODE_OPTIONS = new HashMap() { { diff --git a/core/src/main/java/hudson/util/jna/RegistryKey.java b/core/src/main/java/hudson/util/jna/RegistryKey.java index cae66d6b10870..cd9e9c0a07bca 100644 --- a/core/src/main/java/hudson/util/jna/RegistryKey.java +++ b/core/src/main/java/hudson/util/jna/RegistryKey.java @@ -13,6 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ + package hudson.util.jna; import com.sun.jna.ptr.IntByReference; @@ -44,16 +45,16 @@ private RegistryKey(int handle) { path = ""; } - private RegistryKey(RegistryKey ancestor, String path,int handle) { + private RegistryKey(RegistryKey ancestor, String path, int handle) { this.handle = handle; this.root = ancestor.root; - this.path = combine(ancestor.path,path); + this.path = combine(ancestor.path, path); } private static String combine(String a, String b) { - if(a.length()==0) return b; - if(b.length()==0) return a; - return a+'\\'+b; + if (a.length() == 0) return b; + if (b.length() == 0) return a; + return a + '\\' + b; } /** @@ -96,7 +97,7 @@ private byte[] getValue(String valueName) { lpcbData = new IntByReference(); OUTER: - while(true) { + while (true) { int r = Advapi32.INSTANCE.RegQueryValueEx(handle, valueName, null, pType, lpData, lpcbData); switch (r) { case WINERROR.ERROR_MORE_DATA: @@ -126,7 +127,7 @@ private void check(int r) { */ public void setValue(String name, String value) { byte[] bytes = value.getBytes(StandardCharsets.UTF_16LE); - int newLength = bytes.length+2; // for 0 padding + int newLength = bytes.length + 2; // for 0 padding byte[] with0 = new byte[newLength]; System.arraycopy(bytes, 0, with0, 0, newLength); check(Advapi32.INSTANCE.RegSetValueEx(handle, name, 0, WINNT.REG_SZ, with0, with0.length)); @@ -156,9 +157,9 @@ public boolean valueExists(String name) { lpcbData = new IntByReference(); OUTER: - while(true) { + while (true) { int r = Advapi32.INSTANCE.RegQueryValueEx(handle, name, null, pType, lpData, lpcbData); - switch(r) { + switch (r) { case WINERROR.ERROR_MORE_DATA: lpData = new byte[lpcbData.getValue()]; continue OUTER; @@ -204,17 +205,17 @@ public Collection getSubKeys() { } public RegistryKey open(String subKeyName) { - return open(subKeyName,0xF003F/*KEY_ALL_ACCESS*/); + return open(subKeyName, 0xF003F/*KEY_ALL_ACCESS*/); } public RegistryKey openReadonly(String subKeyName) { - return open(subKeyName,0x20019/*KEY_READ*/); + return open(subKeyName, 0x20019/*KEY_READ*/); } public RegistryKey open(String subKeyName, int access) { IntByReference pHandle = new IntByReference(); check(Advapi32.INSTANCE.RegOpenKeyEx(handle, subKeyName, 0, access, pHandle)); - return new RegistryKey(this,subKeyName,pHandle.getValue()); + return new RegistryKey(this, subKeyName, pHandle.getValue()); } /** @@ -266,7 +267,7 @@ public TreeMap getValues() { break; // not supported yet } break; - + default: check(result); } @@ -283,7 +284,7 @@ protected void finalize() throws Throwable { } public void dispose() { - if(handle!=0) + if (handle != 0) Advapi32.INSTANCE.RegCloseKey(handle); handle = 0; } diff --git a/core/src/main/java/hudson/util/jna/SHELLEXECUTEINFO.java b/core/src/main/java/hudson/util/jna/SHELLEXECUTEINFO.java index 61302f8e5ddba..bca03457306df 100644 --- a/core/src/main/java/hudson/util/jna/SHELLEXECUTEINFO.java +++ b/core/src/main/java/hudson/util/jna/SHELLEXECUTEINFO.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.util.jna; import com.sun.jna.Pointer; @@ -57,7 +58,7 @@ * @author Kohsuke Kawaguchi * @see MSDN: SHELLEXECUTEINFO */ -@SuppressFBWarnings(value = {"UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD", "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD"}, +@SuppressFBWarnings(value = {"UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD", "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD"}, justification = "JNA Data Structure") public class SHELLEXECUTEINFO extends Structure { public int cbSize = size(); @@ -88,7 +89,7 @@ protected List getFieldOrder() { "hProcess"); } - @SuppressFBWarnings(value = {"UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD", "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD"}, + @SuppressFBWarnings(value = {"UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD", "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD"}, justification = "JNA Data Structure") public static class DUMMYUNIONNAME_union extends Union { public Pointer hIcon; @@ -103,11 +104,11 @@ public DUMMYUNIONNAME_union(Pointer hIcon_or_hMonitor) { } public static class ByReference extends DUMMYUNIONNAME_union implements Structure.ByReference { - + } public static class ByValue extends DUMMYUNIONNAME_union implements Structure.ByValue { - + } } } diff --git a/core/src/main/java/hudson/util/jna/Shell32.java b/core/src/main/java/hudson/util/jna/Shell32.java index 8165a4f099ee5..2007167befa79 100644 --- a/core/src/main/java/hudson/util/jna/Shell32.java +++ b/core/src/main/java/hudson/util/jna/Shell32.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.util.jna; import com.sun.jna.Native; diff --git a/core/src/main/java/hudson/util/jna/WINBASE.java b/core/src/main/java/hudson/util/jna/WINBASE.java index 9aa47e7d079ed..695976d521c88 100644 --- a/core/src/main/java/hudson/util/jna/WINBASE.java +++ b/core/src/main/java/hudson/util/jna/WINBASE.java @@ -13,6 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ + package hudson.util.jna; import com.sun.jna.Pointer; diff --git a/core/src/main/java/hudson/util/jna/WINERROR.java b/core/src/main/java/hudson/util/jna/WINERROR.java index 0f9f134f721ab..027fa144642c7 100644 --- a/core/src/main/java/hudson/util/jna/WINERROR.java +++ b/core/src/main/java/hudson/util/jna/WINERROR.java @@ -13,6 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ + package hudson.util.jna; /** diff --git a/core/src/main/java/hudson/util/jna/WINNT.java b/core/src/main/java/hudson/util/jna/WINNT.java index bcfd651676250..6935041796ff7 100644 --- a/core/src/main/java/hudson/util/jna/WINNT.java +++ b/core/src/main/java/hudson/util/jna/WINNT.java @@ -13,6 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ + package hudson.util.jna; /** diff --git a/core/src/main/java/hudson/util/jna/WinIOException.java b/core/src/main/java/hudson/util/jna/WinIOException.java index c3de2ebbfa4da..a5a14712fc32b 100644 --- a/core/src/main/java/hudson/util/jna/WinIOException.java +++ b/core/src/main/java/hudson/util/jna/WinIOException.java @@ -30,7 +30,7 @@ public WinIOException(Throwable cause) { @Override public String getMessage() { - return super.getMessage()+" error="+errorCode+":"+ Util.getWin32ErrorMessage(errorCode); + return super.getMessage() + " error=" + errorCode + ":" + Util.getWin32ErrorMessage(errorCode); } public int getErrorCode() { diff --git a/core/src/main/java/hudson/util/jna/package-info.java b/core/src/main/java/hudson/util/jna/package-info.java index 637a0c66ffdd1..a2abf2e79aa39 100644 --- a/core/src/main/java/hudson/util/jna/package-info.java +++ b/core/src/main/java/hudson/util/jna/package-info.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE diff --git a/core/src/main/java/hudson/util/xstream/ImmutableListConverter.java b/core/src/main/java/hudson/util/xstream/ImmutableListConverter.java index 0cd1184825f8c..196e2289d0ebd 100644 --- a/core/src/main/java/hudson/util/xstream/ImmutableListConverter.java +++ b/core/src/main/java/hudson/util/xstream/ImmutableListConverter.java @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.util.xstream; import com.google.common.collect.ImmutableList; @@ -48,12 +49,12 @@ public class ImmutableListConverter extends CollectionConverter { private final SerializableConverter sc; public ImmutableListConverter(XStream xs) { - this(xs.getMapper(),xs.getReflectionProvider()); + this(xs.getMapper(), xs.getReflectionProvider()); } public ImmutableListConverter(Mapper mapper, ReflectionProvider reflectionProvider) { super(mapper); - sc = new SerializableConverter(mapper,reflectionProvider); + sc = new SerializableConverter(mapper, reflectionProvider); } @Override @@ -69,26 +70,26 @@ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext co List items = new ArrayList(); if (reader.hasMoreChildren()) { reader.moveDown(); - // read the individual items from xml into a list - while (reader.hasMoreChildren()) { - reader.moveDown(); - try { - Object item = readItem(reader, context, items); - items.add(item); - } catch (CriticalXStreamException e) { - throw e; - } catch (XStreamException | LinkageError e) { - RobustReflectionConverter.addErrorInContext(context, e); - } + // read the individual items from xml into a list + while (reader.hasMoreChildren()) { + reader.moveDown(); + try { + Object item = readItem(reader, context, items); + items.add(item); + } catch (CriticalXStreamException e) { + throw e; + } catch (XStreamException | LinkageError e) { + RobustReflectionConverter.addErrorInContext(context, e); + } reader.moveUp(); - } + } // move back up past the elements element. reader.moveUp(); } return ImmutableList.copyOf(items); } else { - return ImmutableList.copyOf((List)super.unmarshal(reader, context)); + return ImmutableList.copyOf((List) super.unmarshal(reader, context)); } } diff --git a/core/src/main/java/hudson/util/xstream/ImmutableMapConverter.java b/core/src/main/java/hudson/util/xstream/ImmutableMapConverter.java index c353cf672c51d..d5821a5c0c952 100644 --- a/core/src/main/java/hudson/util/xstream/ImmutableMapConverter.java +++ b/core/src/main/java/hudson/util/xstream/ImmutableMapConverter.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.util.xstream; import com.google.common.collect.ImmutableMap; @@ -44,12 +45,12 @@ public class ImmutableMapConverter extends MapConverter { private final SerializableConverter sc; public ImmutableMapConverter(XStream xs) { - this(xs.getMapper(),xs.getReflectionProvider()); + this(xs.getMapper(), xs.getReflectionProvider()); } public ImmutableMapConverter(Mapper mapper, ReflectionProvider reflectionProvider) { super(mapper); - sc = new SerializableConverter(mapper,reflectionProvider); + sc = new SerializableConverter(mapper, reflectionProvider); } @Override @@ -59,7 +60,7 @@ public boolean canConvert(Class type) { @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { - return ImmutableMap.copyOf((Map)super.unmarshal(reader, context)); + return ImmutableMap.copyOf((Map) super.unmarshal(reader, context)); } @Override diff --git a/core/src/main/java/hudson/util/xstream/ImmutableSetConverter.java b/core/src/main/java/hudson/util/xstream/ImmutableSetConverter.java index 08184ff504490..b8c3c183984ef 100644 --- a/core/src/main/java/hudson/util/xstream/ImmutableSetConverter.java +++ b/core/src/main/java/hudson/util/xstream/ImmutableSetConverter.java @@ -18,12 +18,12 @@ public class ImmutableSetConverter extends CollectionConverter { private final SerializableConverter sc; public ImmutableSetConverter(XStream xs) { - this(xs.getMapper(),xs.getReflectionProvider()); + this(xs.getMapper(), xs.getReflectionProvider()); } public ImmutableSetConverter(Mapper mapper, ReflectionProvider reflectionProvider) { super(mapper); - sc = new SerializableConverter(mapper,reflectionProvider); + sc = new SerializableConverter(mapper, reflectionProvider); } @Override diff --git a/core/src/main/java/hudson/util/xstream/ImmutableSortedSetConverter.java b/core/src/main/java/hudson/util/xstream/ImmutableSortedSetConverter.java index 09d55c489b7bd..6a1481f9e85af 100644 --- a/core/src/main/java/hudson/util/xstream/ImmutableSortedSetConverter.java +++ b/core/src/main/java/hudson/util/xstream/ImmutableSortedSetConverter.java @@ -18,12 +18,12 @@ public class ImmutableSortedSetConverter extends CollectionConverter { private final SerializableConverter sc; public ImmutableSortedSetConverter(XStream xs) { - this(xs.getMapper(),xs.getReflectionProvider()); + this(xs.getMapper(), xs.getReflectionProvider()); } public ImmutableSortedSetConverter(Mapper mapper, ReflectionProvider reflectionProvider) { super(mapper); - sc = new SerializableConverter(mapper,reflectionProvider); + sc = new SerializableConverter(mapper, reflectionProvider); } @Override diff --git a/core/src/main/java/hudson/util/xstream/MapperDelegate.java b/core/src/main/java/hudson/util/xstream/MapperDelegate.java index deea611a748b5..78d045ca123ca 100644 --- a/core/src/main/java/hudson/util/xstream/MapperDelegate.java +++ b/core/src/main/java/hudson/util/xstream/MapperDelegate.java @@ -9,6 +9,7 @@ * * Created on 22. January 2005 by Joe Walnes */ + package hudson.util.xstream; import com.thoughtworks.xstream.XStream; @@ -139,7 +140,7 @@ public Mapper lookupMapperOfType(Class type) { @Override public SingleValueConverter getConverterFromItemType(String fieldName, Class type, Class definedIn) { - return delegate.getConverterFromItemType(fieldName, type, definedIn); + return delegate.getConverterFromItemType(fieldName, type, definedIn); } /** @@ -148,7 +149,7 @@ public SingleValueConverter getConverterFromItemType(String fieldName, Class typ @Deprecated @Override public String aliasForAttribute(Class definedIn, String fieldName) { - return delegate.aliasForAttribute(definedIn, fieldName); + return delegate.aliasForAttribute(definedIn, fieldName); } /** @@ -157,7 +158,7 @@ public String aliasForAttribute(Class definedIn, String fieldName) { @Deprecated @Override public String attributeForAlias(Class definedIn, String alias) { - return delegate.attributeForAlias(definedIn, alias); + return delegate.attributeForAlias(definedIn, alias); } /** @@ -166,7 +167,7 @@ public String attributeForAlias(Class definedIn, String alias) { @Deprecated @Override public SingleValueConverter getConverterFromAttribute(Class type, String attribute) { - return delegate.getConverterFromAttribute(type, attribute); + return delegate.getConverterFromAttribute(type, attribute); } @Override diff --git a/core/src/main/java/hudson/views/BuildButtonColumn.java b/core/src/main/java/hudson/views/BuildButtonColumn.java index f0aa4436cfc62..5a48f0da6de81 100644 --- a/core/src/main/java/hudson/views/BuildButtonColumn.java +++ b/core/src/main/java/hudson/views/BuildButtonColumn.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Martin Eigenbrodt - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import hudson.Extension; @@ -40,7 +41,7 @@ public String taskNoun(Object job) { return hudson.model.Messages.AbstractItem_TaskNoun(); } - @Extension(ordinal=DEFAULT_COLUMNS_ORDINAL_ACTIONS_START-1) @Symbol("buildButton") + @Extension(ordinal = DEFAULT_COLUMNS_ORDINAL_ACTIONS_START - 1) @Symbol("buildButton") public static class DescriptorImpl extends ListViewColumnDescriptor { @Override public String getDisplayName() { diff --git a/core/src/main/java/hudson/views/DefaultMyViewsTabBar.java b/core/src/main/java/hudson/views/DefaultMyViewsTabBar.java index 9ebc1e63599cf..d697552a68570 100644 --- a/core/src/main/java/hudson/views/DefaultMyViewsTabBar.java +++ b/core/src/main/java/hudson/views/DefaultMyViewsTabBar.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2010, Winston.Prakash@Oracle.com - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import hudson.Extension; diff --git a/core/src/main/java/hudson/views/DefaultViewsTabBar.java b/core/src/main/java/hudson/views/DefaultViewsTabBar.java index e9e9f56dbe114..6f697f96a86e9 100644 --- a/core/src/main/java/hudson/views/DefaultViewsTabBar.java +++ b/core/src/main/java/hudson/views/DefaultViewsTabBar.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2010, Winston.Prakash@Oracle.com - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import hudson.Extension; diff --git a/core/src/main/java/hudson/views/GlobalDefaultViewConfiguration.java b/core/src/main/java/hudson/views/GlobalDefaultViewConfiguration.java index 89fe448d0e80e..b60939aae5eec 100644 --- a/core/src/main/java/hudson/views/GlobalDefaultViewConfiguration.java +++ b/core/src/main/java/hudson/views/GlobalDefaultViewConfiguration.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import hudson.Extension; @@ -36,7 +37,7 @@ * * @author Kohsuke Kawaguchi */ -@Extension(ordinal=300) @Symbol("defaultView") +@Extension(ordinal = 300) @Symbol("defaultView") public class GlobalDefaultViewConfiguration extends GlobalConfiguration { @Override public boolean configure(StaplerRequest req, JSONObject json) throws FormException { @@ -53,7 +54,7 @@ public boolean configure(StaplerRequest req, JSONObject json) throws FormExcepti // Fallback if the view is not specified j.setPrimaryView(j.getViews().iterator().next()); } - + return true; } } diff --git a/core/src/main/java/hudson/views/JobColumn.java b/core/src/main/java/hudson/views/JobColumn.java index b6f581c154c23..b2ec060f09c3b 100644 --- a/core/src/main/java/hudson/views/JobColumn.java +++ b/core/src/main/java/hudson/views/JobColumn.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Martin Eigenbrodt - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import hudson.Extension; @@ -37,7 +38,7 @@ public JobColumn() { } // put this in the middle of icons and properties - @Extension(ordinal=DEFAULT_COLUMNS_ORDINAL_ICON_END+1) @Symbol("jobName") + @Extension(ordinal = DEFAULT_COLUMNS_ORDINAL_ICON_END + 1) @Symbol("jobName") public static class DescriptorImpl extends ListViewColumnDescriptor { @Override public String getDisplayName() { diff --git a/core/src/main/java/hudson/views/LastDurationColumn.java b/core/src/main/java/hudson/views/LastDurationColumn.java index 04696704a65dd..f1d7258e5b956 100644 --- a/core/src/main/java/hudson/views/LastDurationColumn.java +++ b/core/src/main/java/hudson/views/LastDurationColumn.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Martin Eigenbrodt - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import hudson.Extension; @@ -32,7 +33,7 @@ public class LastDurationColumn extends ListViewColumn { public LastDurationColumn() { } - @Extension(ordinal=DEFAULT_COLUMNS_ORDINAL_PROPERTIES_START-4) @Symbol("lastDuration") + @Extension(ordinal = DEFAULT_COLUMNS_ORDINAL_PROPERTIES_START - 4) @Symbol("lastDuration") public static class DescriptorImpl extends ListViewColumnDescriptor { @Override public String getDisplayName() { diff --git a/core/src/main/java/hudson/views/LastFailureColumn.java b/core/src/main/java/hudson/views/LastFailureColumn.java index 1c272b855f8bb..c31f3f9590a03 100644 --- a/core/src/main/java/hudson/views/LastFailureColumn.java +++ b/core/src/main/java/hudson/views/LastFailureColumn.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Martin Eigenbrodt - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import hudson.Extension; @@ -32,7 +33,7 @@ public class LastFailureColumn extends ListViewColumn { public LastFailureColumn() { } - @Extension(ordinal=DEFAULT_COLUMNS_ORDINAL_PROPERTIES_START-2) @Symbol("lastFailure") + @Extension(ordinal = DEFAULT_COLUMNS_ORDINAL_PROPERTIES_START - 2) @Symbol("lastFailure") public static class DescriptorImpl extends ListViewColumnDescriptor { @Override public String getDisplayName() { diff --git a/core/src/main/java/hudson/views/LastStableColumn.java b/core/src/main/java/hudson/views/LastStableColumn.java index 0844121e5dcb4..7dfd482eaab31 100644 --- a/core/src/main/java/hudson/views/LastStableColumn.java +++ b/core/src/main/java/hudson/views/LastStableColumn.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2009, Sun Microsystems, Inc., Jesse Glick - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import hudson.Extension; @@ -32,7 +33,7 @@ public class LastStableColumn extends ListViewColumn { public LastStableColumn() { } - @Extension(ordinal=DEFAULT_COLUMNS_ORDINAL_PROPERTIES_START-3) @Symbol("lastStable") + @Extension(ordinal = DEFAULT_COLUMNS_ORDINAL_PROPERTIES_START - 3) @Symbol("lastStable") public static class DescriptorImpl extends ListViewColumnDescriptor { @Override public String getDisplayName() { diff --git a/core/src/main/java/hudson/views/LastSuccessColumn.java b/core/src/main/java/hudson/views/LastSuccessColumn.java index ebb5bc1bc9446..98571e8e9bf37 100644 --- a/core/src/main/java/hudson/views/LastSuccessColumn.java +++ b/core/src/main/java/hudson/views/LastSuccessColumn.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Martin Eigenbrodt - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import hudson.Extension; @@ -32,7 +33,7 @@ public class LastSuccessColumn extends ListViewColumn { public LastSuccessColumn() { } - @Extension(ordinal=DEFAULT_COLUMNS_ORDINAL_PROPERTIES_START-1) @Symbol("lastSuccess") + @Extension(ordinal = DEFAULT_COLUMNS_ORDINAL_PROPERTIES_START - 1) @Symbol("lastSuccess") public static class DescriptorImpl extends ListViewColumnDescriptor { @Override public String getDisplayName() { diff --git a/core/src/main/java/hudson/views/ListViewColumn.java b/core/src/main/java/hudson/views/ListViewColumn.java index dcf2dd9b0d364..1796f4cc495c4 100644 --- a/core/src/main/java/hudson/views/ListViewColumn.java +++ b/core/src/main/java/hudson/views/ListViewColumn.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Martin Eigenbrodt - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import hudson.DescriptorExtensionList; @@ -169,7 +170,7 @@ private static List createDefaultInitialColumnList(List> @Override public MyViewsTabBarDescriptor getDescriptor() { - return (MyViewsTabBarDescriptor)super.getDescriptor(); + return (MyViewsTabBarDescriptor) super.getDescriptor(); } /** @@ -92,7 +93,7 @@ public List sort(@NonNull List views) { * * @author Kohsuke Kawaguchi */ - @Extension(ordinal=305) @Symbol("myView") + @Extension(ordinal = 305) @Symbol("myView") public static class GlobalConfigurationImpl extends GlobalConfiguration { public MyViewsTabBar getMyViewsTabBar() { return Jenkins.get().getMyViewsTabBar(); @@ -104,7 +105,7 @@ public boolean configure(StaplerRequest req, JSONObject json) throws FormExcepti Jenkins j = Jenkins.get(); if (json.has("myViewsTabBar")) { - j.setMyViewsTabBar(req.bindJSON(MyViewsTabBar.class,json.getJSONObject("myViewsTabBar"))); + j.setMyViewsTabBar(req.bindJSON(MyViewsTabBar.class, json.getJSONObject("myViewsTabBar"))); } else { j.setMyViewsTabBar(new DefaultMyViewsTabBar()); } diff --git a/core/src/main/java/hudson/views/MyViewsTabBarDescriptor.java b/core/src/main/java/hudson/views/MyViewsTabBarDescriptor.java index c98391e6b000a..f191f05d1bd16 100644 --- a/core/src/main/java/hudson/views/MyViewsTabBarDescriptor.java +++ b/core/src/main/java/hudson/views/MyViewsTabBarDescriptor.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import hudson.model.Descriptor; diff --git a/core/src/main/java/hudson/views/StatusColumn.java b/core/src/main/java/hudson/views/StatusColumn.java index 80813e00ea206..9d9e92d3dfdd1 100644 --- a/core/src/main/java/hudson/views/StatusColumn.java +++ b/core/src/main/java/hudson/views/StatusColumn.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Martin Eigenbrodt - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import hudson.Extension; @@ -38,7 +39,7 @@ public class StatusColumn extends ListViewColumn { public StatusColumn() { } - @Extension(ordinal=DEFAULT_COLUMNS_ORDINAL_ICON_START-1) @Symbol("status") + @Extension(ordinal = DEFAULT_COLUMNS_ORDINAL_ICON_START - 1) @Symbol("status") public static class DescriptorImpl extends ListViewColumnDescriptor { @Override public String getDisplayName() { diff --git a/core/src/main/java/hudson/views/StatusFilter.java b/core/src/main/java/hudson/views/StatusFilter.java index a2789b8b8fa32..f15132145017e 100644 --- a/core/src/main/java/hudson/views/StatusFilter.java +++ b/core/src/main/java/hudson/views/StatusFilter.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import edu.umd.cs.findbugs.annotations.NonNull; @@ -60,7 +61,7 @@ public List filter(List added, List al List filtered = new ArrayList<>(); for (TopLevelItem item : added) { if (!(item instanceof ParameterizedJobMixIn.ParameterizedJob) // TODO or better to call the more generic Job.isBuildable? - || ((ParameterizedJobMixIn.ParameterizedJob) item).isDisabled() ^ statusFilter) + || ((ParameterizedJobMixIn.ParameterizedJob) item).isDisabled() ^ statusFilter) filtered.add(item); } return filtered; diff --git a/core/src/main/java/hudson/views/ViewJobFilter.java b/core/src/main/java/hudson/views/ViewJobFilter.java index c00541c215ae6..576ec824d0c85 100644 --- a/core/src/main/java/hudson/views/ViewJobFilter.java +++ b/core/src/main/java/hudson/views/ViewJobFilter.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, Martin Eigenbrodt - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import hudson.DescriptorExtensionList; @@ -48,10 +49,10 @@ public static DescriptorExtensionList> @Override @SuppressWarnings("unchecked") - public Descriptor getDescriptor() { + public Descriptor getDescriptor() { return Jenkins.get().getDescriptorOrDie(getClass()); } - + /** * Choose which jobs to show for a view. * @param added which jobs have been added so far. This JobFilter can remove or add to this list. diff --git a/core/src/main/java/hudson/views/ViewsTabBar.java b/core/src/main/java/hudson/views/ViewsTabBar.java index b8af8de198ae8..195f72104abaf 100644 --- a/core/src/main/java/hudson/views/ViewsTabBar.java +++ b/core/src/main/java/hudson/views/ViewsTabBar.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2010, Winston.Prakash@oracle.com, CloudBees, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import edu.umd.cs.findbugs.annotations.NonNull; @@ -68,7 +69,7 @@ public static DescriptorExtensionList> all( @Override public ViewsTabBarDescriptor getDescriptor() { - return (ViewsTabBarDescriptor)super.getDescriptor(); + return (ViewsTabBarDescriptor) super.getDescriptor(); } /** @@ -92,7 +93,7 @@ public List sort(@NonNull List views) { * * @author Kohsuke Kawaguchi */ - @Extension(ordinal=310) @Symbol("viewsTabBar") + @Extension(ordinal = 310) @Symbol("viewsTabBar") public static class GlobalConfigurationImpl extends GlobalConfiguration { public ViewsTabBar getViewsTabBar() { return Jenkins.get().getViewsTabBar(); @@ -104,7 +105,7 @@ public boolean configure(StaplerRequest req, JSONObject json) throws FormExcepti Jenkins j = Jenkins.get(); if (json.has("viewsTabBar")) { - j.setViewsTabBar(req.bindJSON(ViewsTabBar.class,json.getJSONObject("viewsTabBar"))); + j.setViewsTabBar(req.bindJSON(ViewsTabBar.class, json.getJSONObject("viewsTabBar"))); } else { j.setViewsTabBar(new DefaultViewsTabBar()); } diff --git a/core/src/main/java/hudson/views/ViewsTabBarDescriptor.java b/core/src/main/java/hudson/views/ViewsTabBarDescriptor.java index 73f0c85b825ad..012a43ed9dd81 100644 --- a/core/src/main/java/hudson/views/ViewsTabBarDescriptor.java +++ b/core/src/main/java/hudson/views/ViewsTabBarDescriptor.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import hudson.model.Descriptor; diff --git a/core/src/main/java/hudson/views/WeatherColumn.java b/core/src/main/java/hudson/views/WeatherColumn.java index d14e9ca5582bf..ee04f7c0f08b9 100644 --- a/core/src/main/java/hudson/views/WeatherColumn.java +++ b/core/src/main/java/hudson/views/WeatherColumn.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Martin Eigenbrodt - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -33,7 +33,7 @@ public class WeatherColumn extends ListViewColumn { public WeatherColumn() { } - @Extension(ordinal=DEFAULT_COLUMNS_ORDINAL_ICON_START-2) @Symbol("weather") + @Extension(ordinal = DEFAULT_COLUMNS_ORDINAL_ICON_START - 2) @Symbol("weather") public static class DescriptorImpl extends ListViewColumnDescriptor { @Override public String getDisplayName() { diff --git a/core/src/main/java/hudson/widgets/BuildHistoryWidget.java b/core/src/main/java/hudson/widgets/BuildHistoryWidget.java index aa44599fbbcd4..da3576771416f 100644 --- a/core/src/main/java/hudson/widgets/BuildHistoryWidget.java +++ b/core/src/main/java/hudson/widgets/BuildHistoryWidget.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.widgets; import hudson.model.Queue.Item; @@ -39,13 +40,13 @@ * * @author Kohsuke Kawaguchi */ -public class BuildHistoryWidget extends HistoryWidget { +public class BuildHistoryWidget extends HistoryWidget { /** * @param owner * The parent model object that owns this widget. */ - public BuildHistoryWidget(Task owner, Iterable baseList,Adapter adapter) { - super(owner,baseList, adapter); + public BuildHistoryWidget(Task owner, Iterable baseList, Adapter adapter) { + super(owner, baseList, adapter); } /** @@ -65,7 +66,7 @@ public List getQueuedItems() { list.addFirst(item); } } - return list; + return list; } @Override diff --git a/core/src/main/java/hudson/widgets/HistoryWidget.java b/core/src/main/java/hudson/widgets/HistoryWidget.java index 4cae7eccfb392..aba195ab7c744 100644 --- a/core/src/main/java/hudson/widgets/HistoryWidget.java +++ b/core/src/main/java/hudson/widgets/HistoryWidget.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.widgets; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -50,7 +51,7 @@ * Type individual record. * @author Kohsuke Kawaguchi */ -public class HistoryWidget extends Widget { +public class HistoryWidget extends Widget { /** * The given data model of records. Newer ones first. */ @@ -89,7 +90,7 @@ public HistoryWidget(O owner, Iterable baseList, Adapter adapter) StaplerRequest currentRequest = Stapler.getCurrentRequest(); this.adapter = adapter; this.baseList = baseList; - this.baseUrl = Functions.getNearestAncestorUrl(currentRequest,owner); + this.baseUrl = Functions.getNearestAncestorUrl(currentRequest, owner); this.owner = owner; this.newerThan = getPagingParam(currentRequest, "newer-than"); this.olderThan = getPagingParam(currentRequest, "older-than"); @@ -127,9 +128,9 @@ protected HistoryPageFilter updateFirstTransientBuildKey(HistoryPageFilter histo } private Iterable> updateFirstTransientBuildKey(Iterable> source) { - String key=null; + String key = null; for (HistoryPageEntry t : source) { - if(adapter.isBuilding(t.getEntry())) { + if (adapter.isBuilding(t.getEntry())) { key = adapter.getKey(t.getEntry()); } } @@ -141,12 +142,12 @@ private Iterable> updateFirstTransientBuildKey(Iterable> getRenderList() { - if(trimmed) { + if (trimmed) { List> pageEntries = toPageEntries(baseList); - if(pageEntries.size() > THRESHOLD) { - return updateFirstTransientBuildKey(pageEntries.subList(0,THRESHOLD)); + if (pageEntries.size() > THRESHOLD) { + return updateFirstTransientBuildKey(pageEntries.subList(0, THRESHOLD)); } else { - trimmed=false; + trimmed = false; return updateFirstTransientBuildKey(pageEntries); } } else { @@ -212,8 +213,8 @@ public void setTrimmed(boolean trimmed) { * The build 'number' to fetch. This is string because various variants * uses non-numbers as the build key. */ - public void doAjax( StaplerRequest req, StaplerResponse rsp, - @Header("n") String n ) throws IOException, ServletException { + public void doAjax(StaplerRequest req, StaplerResponse rsp, + @Header("n") String n) throws IOException, ServletException { rsp.setContentType("text/html;charset=UTF-8"); @@ -221,39 +222,39 @@ public void doAjax( StaplerRequest req, StaplerResponse rsp, List items = new ArrayList<>(); if (n != null) { - String nn=null; // we'll compute next n here + String nn = null; // we'll compute next n here // list up all builds >=n. for (T t : baseList) { - if(adapter.compare(t,n)>=0) { + if (adapter.compare(t, n) >= 0) { items.add(t); - if(adapter.isBuilding(t)) + if (adapter.isBuilding(t)) nn = adapter.getKey(t); // the next fetch should start from youngest build in progress } else break; } - if (nn==null) { + if (nn == null) { if (items.isEmpty()) { // nothing to report back. next fetch should retry the same 'n' - nn=n; + nn = n; } else { // every record fetched this time is frozen. next fetch should start from the next build - nn=adapter.getNextKey(adapter.getKey(items.get(0))); + nn = adapter.getNextKey(adapter.getKey(items.get(0))); } } baseList = items; - rsp.setHeader("n",nn); + rsp.setHeader("n", nn); firstTransientBuildKey = nn; // all builds >= nn should be marked transient } HistoryPageFilter page = getHistoryPageFilter(); - req.getView(page,"ajaxBuildHistory.jelly").forward(req,rsp); + req.getView(page, "ajaxBuildHistory.jelly").forward(req, rsp); } - static final int THRESHOLD = SystemProperties.getInteger(HistoryWidget.class.getName()+".threshold",30); + static final int THRESHOLD = SystemProperties.getInteger(HistoryWidget.class.getName() + ".threshold", 30); public String getNextBuildNumberToFetch() { return nextBuildNumberToFetch; @@ -268,8 +269,11 @@ public interface Adapter { * If record is newer than the key, return a positive number. */ int compare(T record, String key); + String getKey(T record); + boolean isBuilding(T record); + String getNextKey(String key); } diff --git a/core/src/main/java/hudson/widgets/RenderOnDemandClosure.java b/core/src/main/java/hudson/widgets/RenderOnDemandClosure.java index 6e9687793f94a..9092526f109b1 100644 --- a/core/src/main/java/hudson/widgets/RenderOnDemandClosure.java +++ b/core/src/main/java/hudson/widgets/RenderOnDemandClosure.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.widgets; import hudson.Util; @@ -56,23 +57,23 @@ public class RenderOnDemandClosure { * Captures the recursive taglib call stack. */ private final Script[] bodyStack; - private final Map variables; + private final Map variables; private final String currentDescriptorByNameUrl; private final String[] adjuncts; public RenderOnDemandClosure(JellyContext context, String attributesToCapture) { List - - - diff --git a/core/src/main/resources/lib/hudson/buildCaption_pt_BR.properties b/core/src/main/resources/lib/hudson/buildCaption_pt_BR.properties index 492a202d6773c..ba77fd0435ba6 100644 --- a/core/src/main/resources/lib/hudson/buildCaption_pt_BR.properties +++ b/core/src/main/resources/lib/hudson/buildCaption_pt_BR.properties @@ -22,3 +22,4 @@ Progress=Progresso cancel=cancelar +confirm=Tem certeza de que quer abortar {0}? diff --git a/core/src/main/resources/lib/hudson/buildCaption_zh_TW.properties b/core/src/main/resources/lib/hudson/buildCaption_zh_TW.properties index b9263a8c38c21..10c7ab9dc883d 100644 --- a/core/src/main/resources/lib/hudson/buildCaption_zh_TW.properties +++ b/core/src/main/resources/lib/hudson/buildCaption_zh_TW.properties @@ -1,24 +1,3 @@ -# The MIT License -# -# Copyright (c) 2004-2010, Sun Microsystems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# 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: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -Progress=\u9032\u5EA6 -cancel=\u53D6\u6D88 +confirm=\u60a8\u78ba\u5b9a\u8981\u4e2d\u6b62 {0} \u55ce\uff1f +Progress=\u9032\u5ea6 +cancel=\u53d6\u6d88 diff --git a/core/src/main/resources/lib/hudson/buildHealth.jelly b/core/src/main/resources/lib/hudson/buildHealth.jelly index e8045ce6f203b..10f138f701bb5 100644 --- a/core/src/main/resources/lib/hudson/buildHealth.jelly +++ b/core/src/main/resources/lib/hudson/buildHealth.jelly @@ -57,7 +57,7 @@ THE SOFTWARE. - + diff --git a/core/src/main/resources/lib/hudson/buildListTable.jelly b/core/src/main/resources/lib/hudson/buildListTable.jelly index 0329a3c993771..fbf12aae037bd 100644 --- a/core/src/main/resources/lib/hudson/buildListTable.jelly +++ b/core/src/main/resources/lib/hudson/buildListTable.jelly @@ -44,7 +44,7 @@ THE SOFTWARE. insert(new Element('div', {class: 'jenkins-table__cell__button-wrapper'}). insert(generateSVGIcon(e.iconName, "${iconSizeClass}")))); tr.insert(new Element('td'). - insert(new Element('a', {class: 'jenkins-table__link model-link inside', href: '${rootURL}/' + e.parentUrl}). + insert(new Element('a', {class: 'jenkins-table__link model-link', href: '${rootURL}/' + e.parentUrl}). update(e.parentFullDisplayName)). insert(new Element('a', {class: 'jenkins-table__link jenkins-table__badge model-link inside', href: '${rootURL}/' + e.url}). update(e.displayName.escapeHTML()))); @@ -56,7 +56,7 @@ THE SOFTWARE. tr.insert(new Element('td', {class: 'jenkins-table__cell--tight'}). insert(new Element('div', {class: 'jenkins-table__cell__button-wrapper'}). insert(new Element('a', {class: 'jenkins-table__button', href: '${rootURL}/' + e.url + 'console'}). - insert(``)))); + insert(``)))); p.insert(tr); Behaviour.applySubtree(tr); } diff --git a/core/src/main/resources/lib/hudson/buildListTable_pt_BR.properties b/core/src/main/resources/lib/hudson/buildListTable_pt_BR.properties index 89818f78932fa..6a3925f882153 100644 --- a/core/src/main/resources/lib/hudson/buildListTable_pt_BR.properties +++ b/core/src/main/resources/lib/hudson/buildListTable_pt_BR.properties @@ -22,6 +22,7 @@ Time\ Since=Tempo desde Status=Estado -Build=Build +Build=Construir Click\ to\ center\ timeline\ on\ event=Clique para centralizar a linha do tempo no evento -Console\ output=Sa\u00edda do console +Console\ output=Sa\u00EDda do console +S=S diff --git a/core/src/main/resources/lib/hudson/buildListTable_zh_TW.properties b/core/src/main/resources/lib/hudson/buildListTable_zh_TW.properties index b8562b71393df..ba43e929c7a8d 100644 --- a/core/src/main/resources/lib/hudson/buildListTable_zh_TW.properties +++ b/core/src/main/resources/lib/hudson/buildListTable_zh_TW.properties @@ -1,7 +1,6 @@ # The MIT License # -# Copyright (c) 2004-2013, Sun Microsystems, Inc., Chunghwa Telecom Co., Ltd., -# and Pei-Tang Huang +# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributors # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,7 +21,7 @@ # THE SOFTWARE. Build=\u5efa\u7f6e -Time\ Since=\u65e5\u671f +Time\ Since=\u8ddd\u958b\u59cb\u6642\u9593 Status=\u72c0\u614b Click\ to\ center\ timeline\ on\ event=\u6309\u4e00\u4e0b\u8b93\u4e8b\u4ef6\u986f\u793a\u5728\u6642\u9593\u8ef8\u4e2d\u592e -Console\ output=\u756b\u9762\u8f38\u51fa +Console\ output=\u4e3b\u63a7\u53f0\u8f38\u51fa diff --git a/core/src/main/resources/lib/hudson/editableDescription.jelly b/core/src/main/resources/lib/hudson/editableDescription.jelly index 4faef20c6b3ef..33890930882a0 100644 --- a/core/src/main/resources/lib/hudson/editableDescription.jelly +++ b/core/src/main/resources/lib/hudson/editableDescription.jelly @@ -43,7 +43,7 @@ THE SOFTWARE.

- + diff --git a/core/src/main/resources/lib/hudson/editableDescription_zh_TW.properties b/core/src/main/resources/lib/hudson/editableDescription_zh_TW.properties index e52a9382d0ce8..3cc4592677ea3 100644 --- a/core/src/main/resources/lib/hudson/editableDescription_zh_TW.properties +++ b/core/src/main/resources/lib/hudson/editableDescription_zh_TW.properties @@ -1,7 +1,6 @@ # The MIT License # -# Copyright (c) 2004-2013, Sun Microsystems, Inc., Chunghwa Telecom Co., Ltd., -# and Pei-Tang Huang +# Copyright (c) 2021, Jenkins contributors # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -20,6 +19,5 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. - -add\ description=\u65B0\u589E\u63CF\u8FF0 -edit\ description=\u7de8\u8f2f\u63cf\u8ff0\u8aaa\u660e +add\ description=\u65b0\u589e\u8aaa\u660e +edit\ description=\u7de8\u8f2f\u8aaa\u660e diff --git a/core/src/main/resources/lib/hudson/executors.jelly b/core/src/main/resources/lib/hudson/executors.jelly index c63b0210aca26..fa8b46fa2b482 100644 --- a/core/src/main/resources/lib/hudson/executors.jelly +++ b/core/src/main/resources/lib/hudson/executors.jelly @@ -34,22 +34,23 @@ THE SOFTWARE. - ${title} - - - - - ( ${%offline}) - - - (${%launching}) - - - (${%offline}) - - - - (${%suspended}) + ${title} + + + + + ( ${%offline}) + + + (${%launching}) + + + (${%offline}) + + + + (${%suspended}) + diff --git a/core/src/main/resources/lib/hudson/executors_pt_BR.properties b/core/src/main/resources/lib/hudson/executors_pt_BR.properties index 2343ec308b273..7dc00b56a12b3 100644 --- a/core/src/main/resources/lib/hudson/executors_pt_BR.properties +++ b/core/src/main/resources/lib/hudson/executors_pt_BR.properties @@ -20,12 +20,14 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -Build\ Executor\ Status=Estado do executor de builds +Build\ Executor\ Status=Estado do executor de contru\u00E7\u00F5es offline=desconectado -Dead=Morto Idle=Parado -terminate\ this\ build=terminar esta builds -Unknown\ Task=Job n\u00e3o localizada +terminate\ this\ build=terminar esta constru\u00E7\u00E3o +Unknown\ Task=Job n\u00E3o localizado suspended=suspenso Offline=desconectado Computers=mestre{0,choice,0#|1# + {0,number} computador ({1} de {2} executores)|1< + {0,number} computadores ({1} de {2} executores)} +confirm=Voc\u00EA tem certeza de que quer abortar {0}? +launching=lan\u00E7ando... +Pending=Pendente diff --git a/core/src/main/resources/lib/hudson/executors_zh_TW.properties b/core/src/main/resources/lib/hudson/executors_zh_TW.properties index 69eebac77ebd5..4ef40ee7278ca 100644 --- a/core/src/main/resources/lib/hudson/executors_zh_TW.properties +++ b/core/src/main/resources/lib/hudson/executors_zh_TW.properties @@ -1,34 +1,15 @@ -# The MIT License -# -# Copyright (c) 2004-2013, Sun Microsystems, Inc., Chunghwa Telecom Co., Ltd., -# and Pei-Tang Huang -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# 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: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -offline=\u96E2\u7DDA +# TODO This label should distinguish between having and not having executors on the built-in node +Computers=\u5167\u5efa\u7bc0\u9ede{0,choice,0\# ({1} / {2} \u57f7\u884c\u7a0b\u5f0f\u5fd9\u788c)|1\# + {0,number} Agent ({1} / {2} \u57f7\u884c\u7a0b\u5f0f\u5fd9\u788c)|1< + {0,number} Agent ({1} / {2} \u57f7\u884c\u7a0b\u5f0f\u5fd9\u788c)} +confirm=\u60a8\u78ba\u5b9a\u8981\u4e2d\u6b62 {0} \u55ce\uff1f +launching=\u6b63\u5728\u555f\u52d5... +offline=\u96e2\u7dda suspended=\u66ab\u505c Dead=\u6b7b\u6389 -Offline=\u96e2\u7dda Idle=\u9592\u7f6e Building=\u5efa\u7f6e\u4e2d Unknown\ Task=\u4e0d\u660e\u7684\u4f5c\u696d terminate\ this\ build=\u4e2d\u65b7\u9019\u6b21\u5efa\u7f6e\u4f5c\u696d Build\ Executor\ Status=\u5efa\u7f6e\u57f7\u884c\u7a0b\u5f0f\u72c0\u614b Status=\u72c0\u614b -Master=\u4E3B\u7BC0\u9EDE +Master=\u4e3b\u7bc0\u9ede +Pending=\u64f1\u7f6e diff --git a/core/src/main/resources/lib/hudson/help.jelly b/core/src/main/resources/lib/hudson/help.jelly index faef6068b9030..6fb1d427b1f0a 100644 --- a/core/src/main/resources/lib/hudson/help.jelly +++ b/core/src/main/resources/lib/hudson/help.jelly @@ -33,10 +33,10 @@ THE SOFTWARE. The tooltip to display - Icon size, available are: small, medium, large, xlarge + Icon size, available are: small, medium, large, xlarge - - + + ? diff --git a/core/src/main/resources/lib/hudson/iconSize_pt_BR.properties b/core/src/main/resources/lib/hudson/iconSize_pt_BR.properties index a8b6703241090..d6d6791340b98 100644 --- a/core/src/main/resources/lib/hudson/iconSize_pt_BR.properties +++ b/core/src/main/resources/lib/hudson/iconSize_pt_BR.properties @@ -21,3 +21,6 @@ # THE SOFTWARE. Icon=\u00CDcone +L=L +S=S +M=M diff --git a/core/src/main/resources/lib/hudson/iconSize_zh_TW.properties b/core/src/main/resources/lib/hudson/iconSize_zh_TW.properties index 5427cb0d4ee90..f445f25b30d66 100644 --- a/core/src/main/resources/lib/hudson/iconSize_zh_TW.properties +++ b/core/src/main/resources/lib/hudson/iconSize_zh_TW.properties @@ -1,6 +1,6 @@ # The MIT License # -# Copyright (c) 2004-2010, Sun Microsystems, Inc. +# Copyright (c) 2018, linuxsuren # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -19,5 +19,7 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. - -Icon=\u5716\u793A +Icon=\u5716\u793a +S=\u5c0f +M=\u4e2d +L=\u5927 diff --git a/core/src/main/resources/lib/hudson/logRecords.jelly b/core/src/main/resources/lib/hudson/logRecords.jelly index ec5c47119dce5..493bf2ebc0724 100644 --- a/core/src/main/resources/lib/hudson/logRecords.jelly +++ b/core/src/main/resources/lib/hudson/logRecords.jelly @@ -27,14 +27,16 @@ THE SOFTWARE. Displays a list of log records. - Records to be displayed (assumed to be in reverse chronologic order). + Records to be displayed (assumed to be in reverse chronological order). - +
+
-
+ +
diff --git a/core/src/main/resources/lib/hudson/newFromList/form.jelly b/core/src/main/resources/lib/hudson/newFromList/form.jelly index 5a947d0322a3b..2f0c87de4bdb9 100644 --- a/core/src/main/resources/lib/hudson/newFromList/form.jelly +++ b/core/src/main/resources/lib/hudson/newFromList/form.jelly @@ -61,13 +61,13 @@ THE SOFTWARE.
- + -
+
${%View type} @@ -94,7 +94,7 @@ THE SOFTWARE.
diff --git a/core/src/main/resources/lib/hudson/newFromList/form_pt_BR.properties b/core/src/main/resources/lib/hudson/newFromList/form_pt_BR.properties index a80c0fe7d8b00..ab1ba3e093a73 100644 --- a/core/src/main/resources/lib/hudson/newFromList/form_pt_BR.properties +++ b/core/src/main/resources/lib/hudson/newFromList/form_pt_BR.properties @@ -20,4 +20,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -Copy\ from=Copiar de +Create=Criar +Type\ for\ suggestions=Digite\ para\ sugest\u00F5es +View\ type=Tipo diff --git a/core/src/main/resources/lib/hudson/newFromList/form_zh_TW.properties b/core/src/main/resources/lib/hudson/newFromList/form_zh_TW.properties index f4cd18bd5dfa5..8261520a00147 100644 --- a/core/src/main/resources/lib/hudson/newFromList/form_zh_TW.properties +++ b/core/src/main/resources/lib/hudson/newFromList/form_zh_TW.properties @@ -1,23 +1,4 @@ -# The MIT License -# -# Copyright (c) 2004-2010, Sun Microsystems, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# 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: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -Copy\ from=\u8907\u88FD\u4F86\u6E90 +View\ type=\u985e\u578b +Create=\u5efa\u7acb +Copy\ from=\u8907\u88fd\u81ea +Type\ for\ suggestions=\u8f38\u5165\u4ee5\u986f\u793a\u5efa\u8b70 diff --git a/core/src/main/resources/lib/hudson/node.jelly b/core/src/main/resources/lib/hudson/node.jelly index db88102acb184..07d2db51e7bb9 100644 --- a/core/src/main/resources/lib/hudson/node.jelly +++ b/core/src/main/resources/lib/hudson/node.jelly @@ -37,7 +37,7 @@ THE SOFTWARE. ${valueStr} - ${%builtin} + ${%built-in} \ No newline at end of file diff --git a/core/src/main/resources/lib/hudson/node_pt_BR.properties b/core/src/main/resources/lib/hudson/node_pt_BR.properties new file mode 100644 index 0000000000000..023011197b60c --- /dev/null +++ b/core/src/main/resources/lib/hudson/node_pt_BR.properties @@ -0,0 +1,24 @@ +# The MIT License +# +# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# 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: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +builtin=embutido +built-in=embutido diff --git a/core/src/main/resources/lib/hudson/node_zh_TW.properties b/core/src/main/resources/lib/hudson/node_zh_TW.properties new file mode 100644 index 0000000000000..a27a40b55dfc1 --- /dev/null +++ b/core/src/main/resources/lib/hudson/node_zh_TW.properties @@ -0,0 +1,23 @@ +# The MIT License +# +# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# 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: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +builtin=\u5167\u5efa diff --git a/core/src/main/resources/lib/hudson/progressiveText.jelly b/core/src/main/resources/lib/hudson/progressiveText.jelly index ea2ffbf07aa88..326784a96a64e 100644 --- a/core/src/main/resources/lib/hudson/progressiveText.jelly +++ b/core/src/main/resources/lib/hudson/progressiveText.jelly @@ -66,13 +66,7 @@ THE SOFTWARE. if(text!="") { var p = document.createElement("DIV"); e.appendChild(p); // Needs to be first for IE - // Use "outerHTML" for IE; workaround for: - // http://www.quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html - if (p.outerHTML) { - p.outerHTML = '
'+text+'
'; - p = e.lastElementChild; - } - else p.innerHTML = text; + p.innerHTML = text; Behaviour.applySubtree(p); ElementResizeTracker.fireResizeCheck(); if(stickToBottom) scroller.scrollToBottom(); diff --git a/core/src/main/resources/lib/hudson/project/config-concurrentBuild_zh_TW.properties b/core/src/main/resources/lib/hudson/project/config-concurrentBuild_zh_TW.properties index 8fbf17aa53e23..019ac84fa6d3f 100644 --- a/core/src/main/resources/lib/hudson/project/config-concurrentBuild_zh_TW.properties +++ b/core/src/main/resources/lib/hudson/project/config-concurrentBuild_zh_TW.properties @@ -1,17 +1,17 @@ -# The MIT License -# -# Copyright (c) 2013, Chunghwa Telecom Co., Ltd., Pei-Tang Huang -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights +# the mit license +# +# copyright (c) 2004-2012, sun microsystems, inc., kohsuke kawaguchi, eric lefevre-ardant +# +# permission is hereby granted, free of charge, to any person obtaining a copy +# 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: -# +# # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. -# +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -19,5 +19,4 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. - -title.concurrentbuilds=\u5FC5\u8981\u6642\u540C\u6642\u57F7\u884C\u591A\u500B\u5EFA\u69CB +title.concurrentbuilds=\u5fc5\u8981\u6642\u540c\u6642\u57f7\u884c\u591a\u500b\u5efa\u7f6e diff --git a/core/src/main/resources/lib/hudson/project/config-disableBuild_pt_BR.properties b/core/src/main/resources/lib/hudson/project/config-disableBuild_pt_BR.properties index dc0d7e5c8b9d4..e3bd451a8b8d9 100644 --- a/core/src/main/resources/lib/hudson/project/config-disableBuild_pt_BR.properties +++ b/core/src/main/resources/lib/hudson/project/config-disableBuild_pt_BR.properties @@ -21,4 +21,3 @@ # THE SOFTWARE. Disable\ this\ project=Desabilitar builds -No\ new\ builds\ will\ be\ executed\ until\ the\ project\ is\ re-enabled.=Nenhum novo build ser\u00e1 executado at\u00e9 que este projeto seja habilitado novamente. diff --git a/core/src/main/resources/lib/hudson/project/config-disableBuild_zh_TW.properties b/core/src/main/resources/lib/hudson/project/config-disableBuild_zh_TW.properties index e929ce787ae68..de744a52bf3cf 100644 --- a/core/src/main/resources/lib/hudson/project/config-disableBuild_zh_TW.properties +++ b/core/src/main/resources/lib/hudson/project/config-disableBuild_zh_TW.properties @@ -1,7 +1,6 @@ # The MIT License # -# Copyright (c) 2004-2013, Sun Microsystems, Inc., Chunghwa Telecom Co., Ltd., -# and Pei-Tang Huang +# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributors # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -21,5 +20,5 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -Disable\ this\ project=\u505C\u7528Build -No\ new\ builds\ will\ be\ executed\ until\ the\ project\ is\ re-enabled.=\u5728\u5C08\u6848\u88AB\u91CD\u65B0\u555F\u7528\u524D\u5C07\u4E0D\u518D\u57F7\u884C\u65B0\u7684\u5EFA\u69CB +Disable\ this\ project=\u505c\u7528\u6b64\u5c08\u6848 +No\ new\ builds\ will\ be\ executed\ until\ the\ project\ is\ re-enabled.=\u5728\u5c08\u6848\u88ab\u91cd\u65b0\u555f\u7528\u524d\u5c07\u4e0d\u518d\u57f7\u884c\u65b0\u7684\u5efa\u7f6e diff --git a/core/src/main/resources/lib/hudson/project/configurable.jelly b/core/src/main/resources/lib/hudson/project/configurable.jelly index eacf85006e08f..229385112ec8b 100644 --- a/core/src/main/resources/lib/hudson/project/configurable.jelly +++ b/core/src/main/resources/lib/hudson/project/configurable.jelly @@ -38,10 +38,10 @@ THE SOFTWARE. - + - + diff --git a/core/src/main/resources/lib/hudson/project/configurable_zh_TW.properties b/core/src/main/resources/lib/hudson/project/configurable_zh_TW.properties index 00be1418e9ad0..2416889e1af25 100644 --- a/core/src/main/resources/lib/hudson/project/configurable_zh_TW.properties +++ b/core/src/main/resources/lib/hudson/project/configurable_zh_TW.properties @@ -19,9 +19,8 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. - -delete=\u522a\u9664{0} +delete=\u522a\u9664 {0} delete.confirm=\u60a8\u78ba\u5b9a\u8981\u522a\u9664 {0} \u2018{1}\u2019 \u55ce\uff1f Build\ scheduled=\u5df2\u6392\u5165\u5efa\u7f6e Configure=\u7d44\u614b -View\ Configuration=\u6aa2\u8996\u8a2d\u5b9a +View\ Configuration=\u6aa2\u8996\u7d44\u614b diff --git a/core/src/main/resources/lib/hudson/project/console-link_zh_TW.properties b/core/src/main/resources/lib/hudson/project/console-link_zh_TW.properties new file mode 100644 index 0000000000000..5b1bcede02358 --- /dev/null +++ b/core/src/main/resources/lib/hudson/project/console-link_zh_TW.properties @@ -0,0 +1,24 @@ +# The MIT License +# +# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# 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: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Console\ Output=\u4e3b\u63a7\u53f0\u8f38\u51fa +View\ as\ plain\ text=\u4ee5\u7d14\u6587\u5b57\u6aa2\u8996 diff --git a/core/src/main/resources/lib/hudson/project/makeDisabled_zh_TW.properties b/core/src/main/resources/lib/hudson/project/makeDisabled_zh_TW.properties index b34b29e4e8129..d2e7c5a85553b 100644 --- a/core/src/main/resources/lib/hudson/project/makeDisabled_zh_TW.properties +++ b/core/src/main/resources/lib/hudson/project/makeDisabled_zh_TW.properties @@ -1,7 +1,6 @@ # The MIT License # -# Copyright (c) 2004-2013, Sun Microsystems, Inc., Chunghwa Telecom Co., Ltd., -# Pei-Tang Huang, and a number of other of contributers +# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributors # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -21,6 +20,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -This\ project\ is\ currently\ disabled=\u9019\u500B\u5C08\u6848\u5DF2\u7D93\u95DC\u9589 -Enable=\u555F\u7528 +This\ project\ is\ currently\ disabled=\u9019\u500b\u5c08\u6848\u5df2\u505c\u7528 +Enable=\u555f\u7528 Disable\ Project=\u505c\u7528\u5c08\u6848 diff --git a/core/src/main/resources/lib/hudson/projectView.jelly b/core/src/main/resources/lib/hudson/projectView.jelly index 0eff0e94e3975..cb32a417ce362 100644 --- a/core/src/main/resources/lib/hudson/projectView.jelly +++ b/core/src/main/resources/lib/hudson/projectView.jelly @@ -73,9 +73,6 @@ THE SOFTWARE. - - - diff --git a/core/src/main/resources/lib/hudson/projectViewRow.jelly b/core/src/main/resources/lib/hudson/projectViewRow.jelly index 0e623b850d1aa..f264e3fa00785 100644 --- a/core/src/main/resources/lib/hudson/projectViewRow.jelly +++ b/core/src/main/resources/lib/hudson/projectViewRow.jelly @@ -34,8 +34,5 @@ THE SOFTWARE. - - - diff --git a/core/src/main/resources/lib/hudson/queue_pt_BR.properties b/core/src/main/resources/lib/hudson/queue_pt_BR.properties index 6a41fc82b4056..2620067671b5a 100644 --- a/core/src/main/resources/lib/hudson/queue_pt_BR.properties +++ b/core/src/main/resources/lib/hudson/queue_pt_BR.properties @@ -20,11 +20,13 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -Build\ Queue=Fila de builds{0,choice,0#|0< ({0,number})} -No\ builds\ in\ the\ queue.=Nenhum build na fila. -Jenkins\ is\ going\ to\ shut\ down.\ No\ further\ builds\ will\ be\ performed.=O Jenkins est\u00e1 desligando. Nenhum build futuro ser\u00e1 executado. +Build\ Queue=Fila de constru\u00E7\u00F5es{0,choice,0#|0< ({0,number})} +No\ builds\ in\ the\ queue.=Nenhuma constru\u00E7\u00E3o na fila. +Jenkins\ is\ going\ to\ shut\ down.\ No\ further\ builds\ will\ be\ performed.=O Jenkins est\u00E1 desligando. Nenhuma constru\u00E7\u00E3o futura ser\u00E1 executada. WaitingFor=Aguardando por {0} cancel=cancelar -Unknown\ Task=Job n\u00e3o localizada +Unknown\ Task=Job n\u00E3o localizado # Filtered Build Queue{0,choice,0#|0< ({0,number})} -Filtered\ Build\ Queue=Fila de builds filtrada{0,choice,0#|0< ({0,number})} +Filtered\ Build\ Queue=Fila de constru\u00E7\u00F5es filtrada{0,choice,0#|0< ({0,number})} +cancel\ this\ build=cancelar\ esta\ constru\u00E7\u00E3o +confirm=Voc\u00EA tem certeza de que quer cancelara execu\u00E7\u00E3o enfileirada de {0}? diff --git a/core/src/main/resources/lib/hudson/queue_zh_TW.properties b/core/src/main/resources/lib/hudson/queue_zh_TW.properties index 7e62c92f28bde..4c4d29132ed1c 100644 --- a/core/src/main/resources/lib/hudson/queue_zh_TW.properties +++ b/core/src/main/resources/lib/hudson/queue_zh_TW.properties @@ -1,30 +1,9 @@ -# The MIT License -# -# Copyright (c) 2004-2013, Sun Microsystems, Inc., Chunghwa Telecom Co., Ltd., -# and Pei-Tang Huang -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# 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: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -Build\ Queue=\u5efa\u7f6e\u4f47\u5217{0,choice,0#|0< ({0,number})} +Build\ Queue=\u5efa\u7f6e\u4f47\u5217{0,choice,0\#|0< ({0,number})} +Filtered\ Build\ Queue=\u7be9\u9078\u7684\u5efa\u7f6e\u4f47\u5217{0,choice,0\#|0< ({0,number})} +WaitingFor=\u6b63\u5728\u7b49\u5f85 {0} +confirm=\u60a8\u78ba\u5b9a\u8981\u53d6\u6d88 {0} \u7684\u4f47\u5217\u55ce\uff1f Jenkins\ is\ going\ to\ shut\ down.\ No\ further\ builds\ will\ be\ performed.=Jenkins \u5373\u5c07\u505c\u6a5f\uff0c\u4e0d\u6703\u518d\u57f7\u884c\u4efb\u4f55\u65b0\u7684\u5efa\u7f6e\u4f5c\u696d\u3002 No\ builds\ in\ the\ queue.=\u4f47\u5217\u4e2d\u6c92\u6709\u5efa\u7f6e\u4f5c\u696d\u3002 -WaitingSince=\u5F9E {0} \u958B\u59CB\u7B49\u5F85 cancel=\u53d6\u6d88 -WaitingFor=\u6B63\u5728\u7B49\u5F85 {0} Unknown\ Task=\u4e0d\u660e\u7684\u4f5c\u696d +cancel\ this\ build=\u53d6\u6d88\u6b64\u5efa\u7f6e diff --git a/core/src/main/resources/lib/hudson/rssBar.jelly b/core/src/main/resources/lib/hudson/rssBar.jelly index 1735b831115ea..c40d59d7335b2 100644 --- a/core/src/main/resources/lib/hudson/rssBar.jelly +++ b/core/src/main/resources/lib/hudson/rssBar.jelly @@ -29,25 +29,19 @@ THE SOFTWARE. ${%Legend} - + Atom feed ${%for all} - + Atom feed ${%for failures} - + Atom feed ${%for just latest builds} diff --git a/core/src/main/resources/lib/hudson/rssBar_zh_TW.properties b/core/src/main/resources/lib/hudson/rssBar_zh_TW.properties index f7bed3de7ddd2..e1769aed4af0e 100644 --- a/core/src/main/resources/lib/hudson/rssBar_zh_TW.properties +++ b/core/src/main/resources/lib/hudson/rssBar_zh_TW.properties @@ -1,27 +1,4 @@ -# The MIT License -# -# Copyright (c) 2004-2013, Sun Microsystems, Inc., Chunghwa Telecom Co., Ltd., -# and Pei-Tang Huang -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# 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: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - Legend=\u5716\u4f8b -for\ all=\u6458\u8981: \u5168\u90e8 -for\ failures=\u6458\u8981: \u5931\u6557 -for\ just\ latest\ builds=\u6458\u8981: \u6700\u8fd1\u5e7e\u6b21\u5efa\u7f6e +for\ all=\u5168\u90e8 +for\ failures=\u5931\u6557 +for\ just\ latest\ builds=\u6700\u8fd1\u5e7e\u6b21\u5efa\u7f6e diff --git a/core/src/main/resources/lib/hudson/scriptConsole.jelly b/core/src/main/resources/lib/hudson/scriptConsole.jelly index 9cb0503151d98..58e43fe3d3a64 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole.jelly +++ b/core/src/main/resources/lib/hudson/scriptConsole.jelly @@ -27,19 +27,11 @@ THE SOFTWARE. --> - + - - - - - - - - -

${%Script Console}

+

${%Script Console}

diff --git a/core/src/main/resources/lib/hudson/scriptConsole.properties b/core/src/main/resources/lib/hudson/scriptConsole.properties index dc1489ad2abde..d1215285dbcce 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole.properties @@ -23,8 +23,8 @@ description=\ Type in an arbitrary Groovy script and \ execute it on the server. Useful for trouble-shooting and diagnostics. \ - Use the \u2018println\u2019 command to see the output (if you use System.out, \ + Use the \u2018println\u2019 command to see the output (if you use System.out, \ it will go to the server\u2019s stdout, which is harder to see.) Example: description2=\ - All the classes from all the plugins are visible. jenkins.*, jenkins.model.*, hudson.*, and hudson.model.* are pre-imported. + All the classes from all the plugins are visible. jenkins.*, jenkins.model.*, hudson.*, and hudson.model.* are pre-imported. diff --git a/core/src/main/resources/lib/hudson/scriptConsole_bg.properties b/core/src/main/resources/lib/hudson/scriptConsole_bg.properties index ca0923890d46e..e1f780cebf6d0 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_bg.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_bg.properties @@ -25,22 +25,22 @@ Result=\ Script\ Console=\ \u041a\u043e\u043d\u0437\u043e\u043b\u0430 \u0437\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432\u0435 # \ -# All the classes from all the plugins are visible. jenkins.*, jenkins.model.*, hudson.*, and hudson.model.* are pre-imported. +# All the classes from all the plugins are visible. jenkins.*, jenkins.model.*, hudson.*, and hudson.model.* are pre-imported. description2=\ \u0412\u0441\u0438\u0447\u043a\u0438 \u043a\u043b\u0430\u0441\u043e\u0432\u0435 \u043e\u0442 \u0432\u0441\u0438\u0447\u043a\u0438 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 \u0441\u0430 \u0432\u0438\u0434\u0438\u043c\u0438. \u0421\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u043f\u0430\u043a\u0435\u0442\u0438 \u0441\u0430 \u0432\u043d\u0435\u0441\u0435\u043d\u0438:\ - jenkins.*, jenkins.model.*, hudson.* \u0438\ - hudson.model.* + jenkins.*, jenkins.model.*, hudson.* \u0438\ + hudson.model.* It\ is\ not\ possible\ to\ run\ scripts\ when\ slave\ is\ offline.=\ \u041a\u043e\u0433\u0430\u0442\u043e \u043f\u043e\u0434\u0447\u0438\u043d\u0435\u043d\u0438\u044f\u0442 \u043a\u043e\u043c\u043f\u044e\u0442\u044a\u0440 \u043d\u0435 \u0435 \u043d\u0430 \u043b\u0438\u043d\u0438\u044f, \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0441\u0435 \u0438\u0437\u043f\u044a\u043b\u043d\u044f\u0432\u0430\u0442 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432\u0435. # \ # Type in an arbitrary Groovy script and \ # execute it on the server. Useful for trouble-shooting and diagnostics. \ -# Use the \u2018println\u2019 command to see the output (if you use System.out, \ +# Use the \u2018println\u2019 command to see the output (if you use System.out, \ # it will go to the server\u2019s stdout, which is harder to see.) Example: description=\ \u0412\u044a\u0432\u0435\u0434\u0435\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u0435\u043d \u0441\u043a\u0440\u0438\u043f\u0442 \u043d\u0430 Groovy\ \u0438 \u0433\u043e \u0438\u0437\u043f\u044a\u043b\u043d\u0435\u0442\u0435 \u043d\u0430 \u0441\u044a\u0440\u0432\u044a\u0440\u0430. \u041f\u043e\u043b\u0435\u0437\u043d\u043e \u0435 \u0437\u0430 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430 \u0438 \u043a\u043e\u0440\u0438\u0433\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0433\u0440\u0435\u0448\u043a\u0438.\ - \u0417\u0430 \u0434\u0430 \u0438\u0437\u0432\u0435\u0434\u0435\u0442\u0435 \u0434\u0430\u043d\u043d\u0438 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0439\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0442\u0430 \u201eprintln\u201c. (System.out\ + \u0417\u0430 \u0434\u0430 \u0438\u0437\u0432\u0435\u0434\u0435\u0442\u0435 \u0434\u0430\u043d\u043d\u0438 \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430\u0439\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0442\u0430 \u201eprintln\u201c. (System.out\ \u043e\u0442\u0438\u0432\u0430 \u043d\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0438\u044f \u0438\u0437\u0445\u043e\u0434 \u043d\u0430 \u0441\u044a\u0440\u0432\u044a\u0440\u0430, \u043a\u043e\u0435\u0442\u043e \u0441\u0435 \u0441\u043b\u0435\u0434\u0438 \u043f\u043e-\u0442\u0440\u0443\u0434\u043d\u043e.) \u041f\u0440\u0438\u043c\u0435\u0440: Run=\ \u0418\u0437\u043f\u044a\u043b\u043d\u0435\u043d\u0438\u0435 diff --git a/core/src/main/resources/lib/hudson/scriptConsole_da.properties b/core/src/main/resources/lib/hudson/scriptConsole_da.properties index 400c3e7123cb5..8c9753e9f538e 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_da.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_da.properties @@ -25,5 +25,5 @@ Run=K\u00f8r Script\ Console=Skriptkonsol description=Indtast et Groovyskript og \ k\u00f8r det p\u00e5 serveren. Nyttigt til fejlfinding og diagnostik. \ -Benyt ''println'' kommandoen for at se output (hvis du bruger System.out, \ +Benyt ''println'' kommandoen for at se output (hvis du bruger System.out, \ vil output g\u00e5 til serverens stdout, hvilket kan v\u00e6re sv\u00e6rere at finde.) Eksempel: diff --git a/core/src/main/resources/lib/hudson/scriptConsole_de.properties b/core/src/main/resources/lib/hudson/scriptConsole_de.properties index 1cc2ebf2d2c00..d4f585179e721 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_de.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_de.properties @@ -25,8 +25,8 @@ Result=Ergebnis Run=Ausf\u00FChren description=Geben Sie ein beliebiges Groovy-Skript \ ein und f\u00FChren Sie dieses auf dem Server aus. Dies ist n\u00FCtzlich bei der Fehlersuche und zur Diagnostik. \ - Verwenden Sie den println-Befehl, um Ausgaben sichtbar zu machen (wenn Sie System.out \ + Verwenden Sie den println-Befehl, um Ausgaben sichtbar zu machen (wenn Sie System.out \ verwenden, gehen die Ausgaben auf die Standardausgabe (STDOUT) des Servers, die schwieriger \ einzusehen ist). Beispiel: -description2=Alle Klassen aller Plugins sind verf\u00FCgbar. jenkins.*, jenkins.model.*, hudson.* sowie hudson.model.* werden standardm\u00E4\u00DFig importiert. +description2=Alle Klassen aller Plugins sind verf\u00FCgbar. jenkins.*, jenkins.model.*, hudson.* sowie hudson.model.* werden standardm\u00E4\u00DFig importiert. It\ is\ not\ possible\ to\ run\ scripts\ when\ agent\ is\ offline.=Es ist nicht m\u00F6glich, Skripte auf einem Agenten, der offline ist, auszuf\u00FChren diff --git a/core/src/main/resources/lib/hudson/scriptConsole_es.properties b/core/src/main/resources/lib/hudson/scriptConsole_es.properties index ddbe14b39f77f..c9de4031f18dd 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_es.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_es.properties @@ -23,11 +23,11 @@ description=\ Escribe un ''script'' Groovy script y \ ejecutal en el servidor. Es til para depurar e investigar problemas. \ - Usa ''println'' para ver la salida (si usas System.out, se escribir \ + Usa ''println'' para ver la salida (si usas System.out, se escribir \ en la salida ''stdout'' del servidor, lo que es ms difcil de visualizar). Ejemplo: Result=Resultado Run=Ejecutar Script\ Console=Consola de scripts description2=Todas las clases de todos los plugins son visibles. \ - Los paquetes: jenkins.*, jenkins.model.*, hudson.*, y hudson.model.*, se importarn automticamente. + Los paquetes: jenkins.*, jenkins.model.*, hudson.*, y hudson.model.*, se importarn automticamente. diff --git a/core/src/main/resources/lib/hudson/scriptConsole_fr.properties b/core/src/main/resources/lib/hudson/scriptConsole_fr.properties index 3dc31f8f916a8..f693edc096d08 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_fr.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_fr.properties @@ -23,6 +23,6 @@ Script\ Console=Console de script Result=Rsultat Run=Excuter -description=Vous pouvez saisir ici un script Groovy quelconque pour l\u2019ex\u00E9cuter sur le serveur.
Utile pour diagnostiquer et r\u00E9soudre des probl\u00E8mes.
Utilisez la commande "println" pour voir la sortie (si vous utilisez System.out, cela ira vers la sortie standard du serveur, qui est plus complexe \u00E0 retrouver.)
Par exemple : +description=Vous pouvez saisir ici un script Groovy quelconque pour l\u2019ex\u00E9cuter sur le serveur.
Utile pour diagnostiquer et r\u00E9soudre des probl\u00E8mes.
Utilisez la commande "println" pour voir la sortie (si vous utilisez System.out, cela ira vers la sortie standard du serveur, qui est plus complexe \u00E0 retrouver.)
Par exemple : -description2=Toutes les classes de tous les plugins sont visibles. jenkins.*, jenkins.model.*, hudson.*, et hudson.model.* sont pr\u00E9-import\u00E9es. +description2=Toutes les classes de tous les plugins sont visibles. jenkins.*, jenkins.model.*, hudson.*, et hudson.model.* sont pr\u00E9-import\u00E9es. diff --git a/core/src/main/resources/lib/hudson/scriptConsole_it.properties b/core/src/main/resources/lib/hudson/scriptConsole_it.properties index f00ed34b86233..772bad053cd1f 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_it.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_it.properties @@ -25,11 +25,11 @@ description=Immettere uno script \ Groovy arbitrario per eseguirlo sul server. Ci utile per eseguire \ operazioni di risoluzione dei problemi e di diagnostica. Utilizzare il \ comando "println" per visualizzare l''output (se si utilizza \ - System.out, questo sar inviato allo standard output del server, \ + System.out, questo sar inviato allo standard output del server, \ che pi difficile da visualizzare). Ad esempio: description2=Sono visibili tutte le classi di tutti i componenti aggiuntivi. \ - I package jenkins.*, jenkins.model.*, hudson.* e \ - hudson.model.* sono preimportati. + I package jenkins.*, jenkins.model.*, hudson.* e \ + hudson.model.* sono preimportati. It\ is\ not\ possible\ to\ run\ scripts\ when\ agent\ is\ offline.=Non \ possibile eseguire degli script quando l''agente non in linea. Result=Risultato diff --git a/core/src/main/resources/lib/hudson/scriptConsole_ja.properties b/core/src/main/resources/lib/hudson/scriptConsole_ja.properties index b06f35182d807..ae817e6ce1872 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_ja.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_ja.properties @@ -27,8 +27,8 @@ description= \ \u4efb\u610f\u306eGroovy\u30b9\u30af\u30ea\u30d7\u30c8\u3092\u5165\u529b\u3057\u3066\u3001 \ \u30b5\u30fc\u30d0\u30fc\u4e0a\u3067\u5b9f\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30c8\u30e9\u30d6\u30eb\u30b7\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0\u3084\u8a3a\u65ad\u306b\u4fbf\u5229\u3067\u3059\u3002 \ \u51fa\u529b\u3092\u898b\u308b\u306b\u306f''println''\u30b3\u30de\u30f3\u30c9\u3092\u4f7f\u7528\u3057\u307e\u3059 \ - (System.out\u3092\u4f7f\u7528\u3059\u308b\u3068\u30b5\u30fc\u30d0\u30fc\u306e\u6a19\u6e96\u51fa\u529b\u306b\u51fa\u529b\u3055\u308c\u307e\u3059\u304c\u3001\u898b\u306b\u304f\u3044\u3067\u3059\uff09\u3002\u4f8b: + (System.out\u3092\u4f7f\u7528\u3059\u308b\u3068\u30b5\u30fc\u30d0\u30fc\u306e\u6a19\u6e96\u51fa\u529b\u306b\u51fa\u529b\u3055\u308c\u307e\u3059\u304c\u3001\u898b\u306b\u304f\u3044\u3067\u3059\uff09\u3002\u4f8b: description2= \ \u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u3059\u3079\u3066\u306e\u30af\u30e9\u30b9\u3092\u5229\u7528\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 \ - \u307e\u305f\u3001jenkins.*\u3001jenkins.model.*\u3001hudson.*\u3001\u304a\u3088\u3073 hudson.model.* \u306f\u3042\u3089\u304b\u3058\u3081\u30a4\u30f3\u30dd\u30fc\u30c8\u6e08\u307f\u3067\u3059\u3002 + \u307e\u305f\u3001jenkins.*\u3001jenkins.model.*\u3001hudson.*\u3001\u304a\u3088\u3073 hudson.model.* \u306f\u3042\u3089\u304b\u3058\u3081\u30a4\u30f3\u30dd\u30fc\u30c8\u6e08\u307f\u3067\u3059\u3002 diff --git a/core/src/main/resources/lib/hudson/scriptConsole_ko.properties b/core/src/main/resources/lib/hudson/scriptConsole_ko.properties index 9a765078d5564..b10095ea404e1 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_ko.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_ko.properties @@ -23,4 +23,4 @@ Result=\uACB0\uACFC Run=\uC2E4\uD589 Script\ Console=\uC2A4\uD06C\uB9BD\uD2B8 \uCF58\uC194 -description=\uC784\uC758\uC758 Groovy\uC2A4\uD06C\uB9BD\uD2B8\uB97C \uC785\uB825\uD558\uC5EC \uC11C\uBC84\uC5D0\uC11C \uC2E4\uD589\uD569\uB2C8\uB2E4.
\uBB38\uC81C\uD574\uACB0\uACFC \uC9C4\uB2E8\uC2DC\uC5D0 \uC720\uC6A9\uD569\uB2C8\uB2E4. \uCD9C\uB825\uBB3C\uC744 \uBCF4\uB824\uBA74 ''println'' \uBA85\uB839\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.
(System.out\uB97C \uC0AC\uC6A9\uD558\uBA74 \uC11C\uBC84\uC758 \uD45C\uC900\uCD9C\uB825\uC73C\uB85C \uBCF4\uB0B4\uC9C0\uACE0, \uAC00\uB3C5\uC131\uC774 \uB5A8\uC5B4\uC9D1\uB2C8\uB2E4.)

\uC608\uC81C: +description=\uC784\uC758\uC758 Groovy\uC2A4\uD06C\uB9BD\uD2B8\uB97C \uC785\uB825\uD558\uC5EC \uC11C\uBC84\uC5D0\uC11C \uC2E4\uD589\uD569\uB2C8\uB2E4.
\uBB38\uC81C\uD574\uACB0\uACFC \uC9C4\uB2E8\uC2DC\uC5D0 \uC720\uC6A9\uD569\uB2C8\uB2E4. \uCD9C\uB825\uBB3C\uC744 \uBCF4\uB824\uBA74 ''println'' \uBA85\uB839\uC744 \uC0AC\uC6A9\uD558\uC138\uC694.
(System.out\uB97C \uC0AC\uC6A9\uD558\uBA74 \uC11C\uBC84\uC758 \uD45C\uC900\uCD9C\uB825\uC73C\uB85C \uBCF4\uB0B4\uC9C0\uACE0, \uAC00\uB3C5\uC131\uC774 \uB5A8\uC5B4\uC9D1\uB2C8\uB2E4.)

\uC608\uC81C: diff --git a/core/src/main/resources/lib/hudson/scriptConsole_nb_NO.properties b/core/src/main/resources/lib/hudson/scriptConsole_nb_NO.properties index 4156a7f96d219..a663dfaaaf9fb 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_nb_NO.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_nb_NO.properties @@ -22,4 +22,4 @@ Run=Kj\u00F8r Script\ Console=Skript-konsoll -description=Skriv inn et vilk\u00E5rlig Groovy script og kj\u00F8r det p\u00E5 serveren. Nyttig i forbindelse med feils\u00F8king og diagnostisering. Bruke "println"-kommandoen for \u00E5 se utdataene. (Hvis du bruker System.out havner det i serverens STDOUT, som er vanskeligere \u00E5 se. Eksempel: +description=Skriv inn et vilk\u00E5rlig Groovy script og kj\u00F8r det p\u00E5 serveren. Nyttig i forbindelse med feils\u00F8king og diagnostisering. Bruke "println"-kommandoen for \u00E5 se utdataene. (Hvis du bruker System.out havner det i serverens STDOUT, som er vanskeligere \u00E5 se. Eksempel: diff --git a/core/src/main/resources/lib/hudson/scriptConsole_nl.properties b/core/src/main/resources/lib/hudson/scriptConsole_nl.properties index d158314cd6386..25b25011bf0fc 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_nl.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_nl.properties @@ -23,4 +23,4 @@ Script\ Console=Scriptconsole Run=Voer uit Result=Resultaat -description=Geef een willekeurig Groovy script in en voer het uit op de server. Dit is nuttig voor troubleshooting en het stellen van diagnoses. Gebruik het "println"-commando om uitvoer te zien (wanneer je System.out gebruikt, gaat de uitvoer naar de stdout van de server, en deze is moeilijker te bekijken.) Bijvoorbeeld: +description=Geef een willekeurig Groovy script in en voer het uit op de server. Dit is nuttig voor troubleshooting en het stellen van diagnoses. Gebruik het "println"-commando om uitvoer te zien (wanneer je System.out gebruikt, gaat de uitvoer naar de stdout van de server, en deze is moeilijker te bekijken.) Bijvoorbeeld: diff --git a/core/src/main/resources/lib/hudson/scriptConsole_pl.properties b/core/src/main/resources/lib/hudson/scriptConsole_pl.properties index 39f1c15d29684..96f9ec609ac8b 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_pl.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_pl.properties @@ -3,6 +3,6 @@ Result=Rezultat Run=Wykonaj Script\ Console=Konsola Skrypt\u00F3w -description=Wpisz skrypt Groovy script i wykonaj go na serwerze. U\u017Cyteczne w przypadku problem\u00F3w i diagnostyki. U\u017Cyj komendy ''''println'''' aby zobaczy\u0107 wynik (je\u015Bli u\u017Cyjesz System.out, wynik b\u0119dzie trudniejszy do znalezienia). Przyk\u0142ad: +description=Wpisz skrypt Groovy script i wykonaj go na serwerze. U\u017Cyteczne w przypadku problem\u00F3w i diagnostyki. U\u017Cyj komendy ''''println'''' aby zobaczy\u0107 wynik (je\u015Bli u\u017Cyjesz System.out, wynik b\u0119dzie trudniejszy do znalezienia). Przyk\u0142ad: -description2=Wszystkie klasy ze wszystkich dodatk\u00F3w s\u0105 widoczne. jenkins.*, jenkins.model.*, hudson.*, i hudson.model.* s\u0105 wst\u0119pnie zaimportowane. +description2=Wszystkie klasy ze wszystkich dodatk\u00F3w s\u0105 widoczne. jenkins.*, jenkins.model.*, hudson.*, i hudson.model.* s\u0105 wst\u0119pnie zaimportowane. diff --git a/core/src/main/resources/lib/hudson/scriptConsole_pt_BR.properties b/core/src/main/resources/lib/hudson/scriptConsole_pt_BR.properties index 512d2bc7076e8..3bea8fe9d98a8 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_pt_BR.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_pt_BR.properties @@ -25,15 +25,16 @@ Run=Executar Result=Resultado # Type in an arbitrary Groovy script and \ # execute it on the server. Useful for trouble-shooting and diagnostics. \ -# Use the ''println'' command to see the output (if you use System.out, \ +# Use the ''println'' command to see the output (if you use System.out, \ # it will go to the server''s stdout, which is harder to see.) Example: description=Digite um comando Groovy script qualquer e \ execute-o no servidor. \u00DAtil para resolu\u00E7\u00E3o de problemas e diagn\u00F3sticos. \ - Use o comando "println" para ver a sa\u00EDda (se voc\u00EA usa System.out, \ + Use o comando "println" para ver a sa\u00EDda (se voc\u00EA usa System.out, \ ele ir\u00E1 para o log do servidor, que \u00E9 mais dif\u00EDcil de ver). Exemplo: # All the classes from all the plugins are visible. \ -# jenkins.*, jenkins.model.*, hudson.*, and \ -# hudson.model.* are pre-imported. -description2=Todas as classes de todos os plugins s\u00e3o vis\u00edveis. \ - jenkins.*, jenkins.model.*, hudson.*, e \ - hudson.model.* s\u00e3o pr\u00e9-importados. +# jenkins.*, jenkins.model.*, hudson.*, and \ +# hudson.model.* are pre-imported. +description2=Todas as classes de todos as estens\u00F5es s\u00E3o vis\u00EDveis. \ + jenkins.*, jenkins.model.*, hudson.*, e \ + hudson.model.* s\u00E3o pr\u00E9-importadas. +It\ is\ not\ possible\ to\ run\ scripts\ when\ agent\ is\ offline.=N\u00E3o\ \u00E9\ poss\u00EDvel\ executar\ scripts\ quando\ o\ agente\ est\u00E1\ fora\ do\ ar. diff --git a/core/src/main/resources/lib/hudson/scriptConsole_ru.properties b/core/src/main/resources/lib/hudson/scriptConsole_ru.properties index bdff9a3fa6cdb..6b0a4b308b3c9 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_ru.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_ru.properties @@ -2,5 +2,5 @@ It\ is\ not\ possible\ to\ run\ scripts\ when\ agent\ is\ offline.=\u041d\u0435\ Result=\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 Run=\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Script\ Console=\u041a\u043e\u043d\u0441\u043e\u043b\u044c -description2=\u0412\u0441\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0438\u0437 \u0432\u0441\u0435\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b. jenkins.*, jenkins.model.*, hudson.* \u0438 hudson.model.* \u0443\u0436\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. -description=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 Groovy \u0441\u043a\u0440\u0438\u043f\u0442 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u0435\u0433\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435. \u041f\u043e\u043b\u0435\u0437\u043d\u043e \u043f\u0440\u0438 \u0443\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u043d\u0435\u043f\u043e\u043b\u0430\u0434\u043e\u043a \u0438 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0438. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 ''''println'''' \u0434\u043b\u044f \u043f\u0435\u0447\u0430\u0442\u0438 \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434 (\u0435\u0441\u043b\u0438 \u0432\u044b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435\u0441\u044c System.out, \u0442\u043e \u0432\u044b\u0432\u043e\u0434 \u043f\u043e\u0439\u0434\u0451\u0442 \u0432 stdout \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u0443\u0432\u0438\u0434\u0435\u0442\u044c). \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: +description2=\u0412\u0441\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0438\u0437 \u0432\u0441\u0435\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b. jenkins.*, jenkins.model.*, hudson.* \u0438 hudson.model.* \u0443\u0436\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. +description=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 Groovy \u0441\u043a\u0440\u0438\u043f\u0442 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u0435\u0433\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435. \u041f\u043e\u043b\u0435\u0437\u043d\u043e \u043f\u0440\u0438 \u0443\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u043d\u0435\u043f\u043e\u043b\u0430\u0434\u043e\u043a \u0438 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0438. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 ''''println'''' \u0434\u043b\u044f \u043f\u0435\u0447\u0430\u0442\u0438 \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434 (\u0435\u0441\u043b\u0438 \u0432\u044b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435\u0441\u044c System.out, \u0442\u043e \u0432\u044b\u0432\u043e\u0434 \u043f\u043e\u0439\u0434\u0451\u0442 \u0432 stdout \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u0443\u0432\u0438\u0434\u0435\u0442\u044c). \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: diff --git a/core/src/main/resources/lib/hudson/scriptConsole_sr.properties b/core/src/main/resources/lib/hudson/scriptConsole_sr.properties index 8b7a38680b57e..a09e644fcd25d 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_sr.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_sr.properties @@ -5,9 +5,9 @@ description=\ \u0423\u043D\u0435\u0441\u0438\u0442\u0435 \u0430\u0440\u0431\u0438\u0442\u0440\u0430\u0440\u043D\u0438 Groovy \u0441\u043A\u0440\u0443\u043F\u0442\u0443 \u0438 \ \u0438\u0437\u0432\u0440\u0448\u0438 \u0458\u0435 \u043D\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0443. \u041A\u043E\u0440\u0438\u0441\u043D\u043E \u043A\u043E\u0434 \u0440\u0435\u0448\u0430\u0432\u0430\u045A\u0435 \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u0430 \u0438 \u0434\u0438\u0430\u0433\u043D\u043E\u0441\u0442\u0438\u043A\u043E\u043C. \ \u041A\u043E\u0440\u0438\u0441\u0442\u0438\u0442\u0435 \u043A\u043E\u043C\u0430\u043D\u0434\u0443 \u2018println\u2019 \u0434\u0430 \u0432\u0438\u0434\u0438\u0442\u0435 \u0438\u0441\u0445\u043E\u0434 (\u0431\u0438\u045B\u0435 \u043F\u0440\u0435\u0443\u0441\u043C\u0435\u0440\u0435\u043D\u043E \ - System.out \u043F\u0440\u0435\u043C\u0430 stdout \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0448\u0442\u043E \u0441\u0435 \u0442\u0435\u0436\u0435 \u0447\u0438\u0442\u0430.) \u041F\u0440\u0438\u043C\u0435\u0440: + System.out \u043F\u0440\u0435\u043C\u0430 stdout \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0448\u0442\u043E \u0441\u0435 \u0442\u0435\u0436\u0435 \u0447\u0438\u0442\u0430.) \u041F\u0440\u0438\u043C\u0435\u0440: description2=\ - \u0421\u0432\u0435 \u043A\u043B\u0430\u0441\u0435 \u0441\u0430 \u0441\u0432\u0438\u0445 \u043C\u043E\u0434\u0443\u043B\u0430 \u0441\u0443 \u0432\u0438\u0434\u0459\u0438\u0432\u0438. jenkins.*, jenkins.model.*, hudson.*, and hudson.model.* \u0441\u0443 \u043F\u0440\u0435\u0442\u0445\u043E\u0434\u043D\u043E \u0443\u0447\u0438\u0442\u0430\u043D\u0430. + \u0421\u0432\u0435 \u043A\u043B\u0430\u0441\u0435 \u0441\u0430 \u0441\u0432\u0438\u0445 \u043C\u043E\u0434\u0443\u043B\u0430 \u0441\u0443 \u0432\u0438\u0434\u0459\u0438\u0432\u0438. jenkins.*, jenkins.model.*, hudson.*, and hudson.model.* \u0441\u0443 \u043F\u0440\u0435\u0442\u0445\u043E\u0434\u043D\u043E \u0443\u0447\u0438\u0442\u0430\u043D\u0430. Run=\u0418\u0437\u0432\u0440\u0448\u0438 Result=\u0420\u0435\u0437\u0443\u043B\u0442\u0430\u0442 It\ is\ not\ possible\ to\ run\ scripts\ when\ agent\ is\ offline.=\u041D\u0438\u0458\u0435 \u043C\u043E\u0433\u0443\u045B\u0435 \u0438\u0437\u0432\u0440\u0448\u0438\u0442\u0438 \u0441\u043A\u0438\u043F\u0442\u043E\u0432\u0435 \u043A\u0430\u0434\u0430 \u0430\u0433\u0435\u043D\u0442 \u043D\u0438\u0458\u0435 \u043F\u043E\u0432\u0435\u0437\u0430\u043D. diff --git a/core/src/main/resources/lib/hudson/scriptConsole_sv_SE.properties b/core/src/main/resources/lib/hudson/scriptConsole_sv_SE.properties index 38aab9e28b9f5..74188a6c9710a 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_sv_SE.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_sv_SE.properties @@ -23,5 +23,5 @@ Result=Resultat Run=K\u00F6r Script\ Console=Skriptkonsoll -description=Skriv in ett godtyckligt Groovy skript och k\u00F6r den p\u00E5 noden. Detta \u00E4r anv\u00E4ndbart vid fels\u00F6kning och diagnostik. Anv\u00E4nd''''println''''kommandot f\u00F6r att se resultatet (om du anv\u00E4nder System.out kommer det att g\u00E5 till serverns standard ut, som \u00E4r sv\u00E5rare att se.) Exempel: -description2=Alla klasser fr\u00E5n pluginet \u00E4r synliga. jenkins.*, jenkins.model.*, hudson.*, and hudson.model.* are pre-imported. +description=Skriv in ett godtyckligt Groovy skript och k\u00F6r den p\u00E5 noden. Detta \u00E4r anv\u00E4ndbart vid fels\u00F6kning och diagnostik. Anv\u00E4nd''''println''''kommandot f\u00F6r att se resultatet (om du anv\u00E4nder System.out kommer det att g\u00E5 till serverns standard ut, som \u00E4r sv\u00E5rare att se.) Exempel: +description2=Alla klasser fr\u00E5n pluginet \u00E4r synliga. jenkins.*, jenkins.model.*, hudson.*, and hudson.model.* are pre-imported. diff --git a/core/src/main/resources/lib/hudson/scriptConsole_zh_TW.properties b/core/src/main/resources/lib/hudson/scriptConsole_zh_TW.properties index ba14d84e2b226..4382d765ec1b5 100644 --- a/core/src/main/resources/lib/hudson/scriptConsole_zh_TW.properties +++ b/core/src/main/resources/lib/hudson/scriptConsole_zh_TW.properties @@ -1,18 +1,17 @@ # The MIT License -# -# Copyright (c) 2004-2013, Sun Microsystems, Inc., Chunghwa Telecom Co., Ltd., -# and Pei-Tang Huang -# +# +# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe +# # Permission is hereby granted, free of charge, to any person obtaining a copy # 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: -# +# # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. -# +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -20,12 +19,9 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. - +description=\u8f38\u5165\u4efb\u610f\u7684 Groovy Script\uff0c\u5728\u4f3a\u670d\u5668\u4e0a\u57f7\u884c\u3002\u7591\u96e3\u6392\u89e3\u6216\u8a3a\u65b7\u6642\u5f88\u6709\u7528\u3002\u4f7f\u7528 "println" \u6307\u4ee4\u53ef\u4ee5\u770b\u5230\u8f38\u51fa\u7d50\u679c (\u5982\u679c\u60a8\u4f7f\u7528 System.out\uff0c\u5c07\u8f38\u51fa\u5230\u4f3a\u670d\u5668\u4e0a\u7684 stdout\uff0c\u6703\u6bd4\u8f03\u96e3\u770b\u5230)\u3002\u7bc4\u4f8b\: +description2=\u6240\u6709\u5916\u639b\u7a0b\u5f0f\u7684 class \u90fd\u53ef\u4ee5\u4f7f\u7528\u3002\u5df2\u9810\u5148 import \u4e86 jenkins.*, jenkins.model.*, hudson.* \u53ca hudson.model.* \u7b49 package\u3002 Script\ Console=Script \u4e3b\u63a7\u53f0 -description=\ - \u8f38\u5165\u4efb\u610f\u7684 Groovy Script\uff0c\u5728\u4f3a\u670d\u5668\u4e0a\u57f7\u884c\u3002\ - \u7591\u96e3\u6392\u89e3\u6216\u8a3a\u65b7\u6642\u5f88\u6709\u7528\u3002\u4f7f\u7528 "println" \u6307\u4ee4\u53ef\u4ee5\u770b\u5230\u8f38\u51fa\u7d50\u679c \ - (\u5982\u679c\u60a8\u4f7f\u7528 System.out\uff0c\u5c07\u8f38\u51fa\u5230\u4f3a\u670d\u5668\u4e0a\u7684 stdout\uff0c\u6703\u6bd4\u8f03\u96e3\u770b\u5230)\u3002\u7bc4\u4f8b: -description2=\u6240\u6709\u5916\u639B\u7A0B\u5F0F\u7684 class \u90FD\u53EF\u4EE5\u4F7F\u7528\u3002\u5DF2\u9810\u5148 import \u4E86 jenkins.*, jenkins.model.*, hudson.* \u53CA hudson.model.* \u7B49 package\u3002 Run=\u57f7\u884c -Result=\u7D50\u679C +Result=\u7d50\u679c +It\ is\ not\ possible\ to\ run\ scripts\ when\ agent\ is\ offline.=Agent \u96e2\u7dda\u6642\u7121\u6cd5\u57f7\u884c Script\u3002 diff --git a/core/src/main/resources/lib/hudson/summary.jelly b/core/src/main/resources/lib/hudson/summary.jelly index b4fc33c176564..a9945322b455f 100644 --- a/core/src/main/resources/lib/hudson/summary.jelly +++ b/core/src/main/resources/lib/hudson/summary.jelly @@ -28,11 +28,9 @@ THE SOFTWARE. Displays a link with a large icon. Used in the project top page. - The icon class name e.g. 'icon-folder'. - - On older versions of Jenkins, this attribute value used to be a link to the raw icon image, where relative - paths were resolved against images/48x48 and absolute paths (that start with '/') were resolved against - the context root of Hudson. + Supports Jenkins Symbols (e.g. 'symbol-search') + Supports path to bitmap image (e.g. '/plugin/foo/abc.gif') + Supports icon class specification (e.g. 'icon-help icon-sm', 'icon-blue icon-md', 'icon-blue-anime icon-xlg') where the summary icon links to. @@ -46,53 +44,9 @@ THE SOFTWARE. - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -109,4 +63,4 @@ THE SOFTWARE. -
\ No newline at end of file + diff --git a/core/src/main/resources/lib/hudson/thirdPartyLicenses.jelly b/core/src/main/resources/lib/hudson/thirdPartyLicenses.jelly index 8e454626ee986..3e1a1209cb769 100644 --- a/core/src/main/resources/lib/hudson/thirdPartyLicenses.jelly +++ b/core/src/main/resources/lib/hudson/thirdPartyLicenses.jelly @@ -1,7 +1,7 @@ - + @@ -55,7 +55,7 @@ THE SOFTWARE. - ${attrs.name}
+ ${attrs.name}
diff --git a/core/src/main/resources/lib/layout/breadcrumb.jelly b/core/src/main/resources/lib/layout/breadcrumb.jelly index a9ee93907046c..56117a62d83d0 100644 --- a/core/src/main/resources/lib/layout/breadcrumb.jelly +++ b/core/src/main/resources/lib/layout/breadcrumb.jelly @@ -40,9 +40,9 @@ THE SOFTWARE.
  • - + ${attrs.title}
  • -
    \ No newline at end of file + diff --git a/core/src/main/resources/lib/layout/breadcrumbBar.jelly b/core/src/main/resources/lib/layout/breadcrumbBar.jelly index 182f0106b4818..770e4ee15beb5 100644 --- a/core/src/main/resources/lib/layout/breadcrumbBar.jelly +++ b/core/src/main/resources/lib/layout/breadcrumbBar.jelly @@ -34,50 +34,47 @@ THE SOFTWARE. use the <l:breadcrumb> tag. - - - -
    -
    - + - - - \ No newline at end of file +
    +
    + diff --git a/core/src/main/resources/lib/layout/breadcrumbBar_pt_BR.properties b/core/src/main/resources/lib/layout/breadcrumbBar_pt_BR.properties new file mode 100644 index 0000000000000..4c2ad4e1b819c --- /dev/null +++ b/core/src/main/resources/lib/layout/breadcrumbBar_pt_BR.properties @@ -0,0 +1,23 @@ +# The MIT License +# +# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# 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: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Dashboard=Painel de controle diff --git a/core/src/main/resources/lib/layout/breadcrumbs.css b/core/src/main/resources/lib/layout/breadcrumbs.css deleted file mode 100644 index f808e93864e7e..0000000000000 --- a/core/src/main/resources/lib/layout/breadcrumbs.css +++ /dev/null @@ -1,154 +0,0 @@ -#left-top-nav { - text-align: left; - color: #222; -} - -#left-top-nav a { - color: black; -} - -#top-nav .a { - color: white; -} - -.breadcrumbs__wrapper { - display: flex; - justify-content: space-between; - align-items: center; - min-height: 2.5rem; - font-size: 1rem; - line-height: 1.5; - padding: 0 0.7rem; - background-color: #F8F8F8; - background-color: var(--breadcrumbs-bg); -} - -#breadcrumbs { - list-style-type: none; - margin: 0; - padding: 0; - min-height: 2.5rem; - display: block; - display: flex; - align-items: center; - flex: 1; - border-bottom: none; - flex-wrap: wrap; -} - -#breadcrumbs LI { - display:inline-block; - min-height: 2.5rem; -} - -#breadcrumbs LI A { - display: inline-block; - display: inline-flex; - align-items: center; - height: 2.5rem; - padding: 0 0.5rem; -} - -#breadcrumbs LI:hover, A.breadcrumbBarAnchor.mouseIsOverMenuSelector { - background-color: #e0e4dc; - background-color: var(--breadcrumbs-item-bg-color--hover); -} - - -#breadcrumbs LI A, #breadcrumbs LI A:link, #breadcrumbs LI A:visited { - /* is this still needed? */ - max-width: 1330px; - - text-overflow: ellipsis; - text-decoration: none; - overflow: hidden; - white-space: nowrap; - font-weight: bold; - - display: inline-block; - display: inline-flex; - color: #4d545d; - color: var(--breadcrumbs-text-color); -} - -#breadcrumbs LI A:hover, #breadcrumbs LI A:focus { - /* TODO: change hover state - add it in the LI element so that it applies to the menuSeparator */ - text-decoration: underline; - outline-color: #3FB3F7; - outline-color: var(--focus); -} - -#breadcrumbs LI A:active { - background-color: #C8CEC2; - background-color: var(--breadcrumbs-item-bg-color--hover); -} - -#breadcrumbs LI A { - cursor: pointer; -} - -#breadcrumbs LI.children, #breadcrumbs LI.separator {/* '>' separator between two items */ - width: 1.25rem; - height: 100%; - display: inline-block; - display: inline-flex; - align-items: center; - justify-content: center; -} - -#breadcrumbs LI.children:after, #breadcrumbs LI.separator:after { - /* Right arrow */ - content: ""; - border-left: 0.25em solid currentColor; - border-top: 0.25em solid transparent; - border-bottom: 0.25em solid transparent; - border-right: 0; -} - -#breadcrumbs LI.children { - cursor: pointer; -} - -#breadcrumbs LI.children:hover:after { - border-left-color: #4d545d; - border-left-color: var(--breadcrumbs-text-color); -} - -#breadcrumbs LI.separator:last-child {/* separators are for in-between only */ - display: none; -} - -#menuSelector {/* used for showing 'v' on the right of the anchor */ - width: 15px; - height:16px; - position: absolute; - visibility: hidden; - cursor: pointer; - z-index: 2000; - display: inline-block; - display: inline-flex; - align-items: center; - justify-content: center; -} -#menuSelector:after { - /* Down arrow */ - content: ""; - border-top: 0.30em solid #4d545d; - border-top: 0.30em solid var(--breadcrumbs-text-color); - border-left: 0.30em solid transparent; - border-right: 0.30em solid transparent; - border-bottom: 0; -} -#menuSelector.inverse:after { - border-top-color: #bcbcbc; -} - -A.model-link.inside, #breadcrumbs A.inside {/* additional 'inside' class allows pre-allocation of the context menu space */ - padding-right: 16px; -} - -#breadcrumb-menu .header { - font-weight: bold; - font-size: 0.875rem; -} diff --git a/core/src/main/resources/lib/layout/breadcrumbs.js b/core/src/main/resources/lib/layout/breadcrumbs.js index 98aba574d07f2..c30107a7a7b32 100644 --- a/core/src/main/resources/lib/layout/breadcrumbs.js +++ b/core/src/main/resources/lib/layout/breadcrumbs.js @@ -23,8 +23,13 @@ var breadcrumbs = (function() { var logger = function() {}; // logger = function() { console.log.apply(console,arguments) }; // uncomment this line to enable logging - function makeMenuHtml(icon,displayName) { + function makeMenuHtml(icon, iconXml, displayName) { var displaynameSpan = '' + displayName + ''; + + if (iconXml != null) { + return iconXml + displaynameSpan; + } + if (icon === null) return "" + displaynameSpan; // TODO: move this to the API response in a clean way @@ -99,84 +104,6 @@ var breadcrumbs = (function() { }; } - /** - * '>' control used to launch context menu. - */ - var menuSelector = (function() { - var menuSelector = $(document.createElement("div")); - var menuSelectorTarget; - var parentToUpdate; - - document.body.appendChild(menuSelector); - menuSelector.id = 'menuSelector'; - - /** - * @param target - * DOM node to attach this selector to. - */ - menuSelector.show = function(target) { - var xy = Dom.getXY(target); - - if ($(target).hasClassName("inside")) - xy[0] -= this.offsetWidth; // show the menu selector inside the text - - if ($(target).hasClassName("inverse")) { - menuSelector.addClassName("inverse"); - } else { - menuSelector.removeClassName("inverse"); - } - - xy[0] += target.offsetWidth; - xy[1] += target.offsetHeight/2 - this.offsetHeight/2; - Dom.setXY(this, xy); - this.target = target; - - this.style.visibility = "visible"; - - menuSelectorTarget = target; - var updateParentSelector = menuSelectorTarget.getAttribute('update-parent-class'); - if (updateParentSelector) { - parentToUpdate = $(menuSelectorTarget).up(updateParentSelector); - } - }; - menuSelector.hide = function() { - this.style.visibility = "hidden"; - menuSelectorTarget = undefined; - parentToUpdate = undefined; - }; - menuSelector.observe("click",function () { - invokeContextMenu(this.target); - }); - - // if the mouse leaves the selector, hide it - canceller = new Delayed(function () { - logger("hiding 'v'"); - menuSelector.hide(); - }.bind(menuSelector), 750); - - menuSelector.observe("mouseover",function () { - if (menuSelectorTarget) { - if (parentToUpdate) { - parentToUpdate.addClassName('model-link-active'); - } - menuSelectorTarget.addClassName('mouseIsOverMenuSelector'); - } - canceller.cancel(); - }); - menuSelector.observe("mouseout",function () { - canceller.schedule(); - if (menuSelectorTarget) { - if (parentToUpdate) { - parentToUpdate.removeClassName('model-link-active'); - } - menuSelectorTarget.removeClassName('mouseIsOverMenuSelector'); - } - }); - menuSelector.canceller = canceller; - - return menuSelector; - })(); - /** * Called when the user clicks a mouse to show a context menu. * @@ -187,8 +114,8 @@ var breadcrumbs = (function() { * @param {String} contextMenuUrl * The URL that renders JSON for context menu. Optional. */ - function invokeContextMenu(e,contextMenuUrl) { - contextMenuUrl = contextMenuUrl || "contextMenu"; + function invokeContextMenu(e, contextMenuUrl) { + contextMenuUrl = contextMenuUrl || "contextMenu"; function showMenu(items) { menu.hide(); @@ -207,15 +134,20 @@ var breadcrumbs = (function() { if (e.items) {// use what's already loaded showMenu(e.items()); - } else {// fetch menu on demand - xhr = new Ajax.Request(combinePath(e.getAttribute("href"),contextMenuUrl), { + } else { + // fetch menu on demand + xhr = new Ajax.Request(combinePath(e.getAttribute("href"), contextMenuUrl), { onComplete:function (x) { - var a = x.responseText.evalJSON().items; + var items = x.responseText.evalJSON().items; function fillMenuItem(e) { - if (e.header) { - e.text = makeMenuHtml(e.icon, "" + e.displayName + ""); + if (e.type === "HEADER") { + e.text = makeMenuHtml(e.icon, e.iconXml, "" + e.displayName + ""); + e.disabled = true; + } else if (e.type === "SEPARATOR") { + e.text = "--"; + e.disabled = true; } else { - e.text = makeMenuHtml(e.icon, e.displayName); + e.text = makeMenuHtml(e.icon, e.iconXml, e.displayName); } if (e.subMenu!=null) e.subMenu = {id:"submenu"+(iota++), itemdata:e.subMenu.items.each(fillMenuItem)}; @@ -227,10 +159,9 @@ var breadcrumbs = (function() { delete e.url; } } - a.each(fillMenuItem); - - e.items = function() { return a }; - showMenu(a); + items.each(fillMenuItem); + e.items = function() { return items }; + showMenu(items); } }); } @@ -238,40 +169,24 @@ var breadcrumbs = (function() { return false; } -// Behaviour.specify("#breadcrumbs LI", 'breadcrumbs', 0, function (e) { -// // when the mouse hovers over LI, activate the menu -// if (e.hasClassName("no-context-menu")) return; -// e.observe("mouseover", function () { handleHover(e.firstChild) }); -// }); - - Behaviour.specify("A.model-link", 'breadcrumbs', 0, function (a) { - // ditto for model-link, but give it a larger delay to avoid unintended menus to be displayed - // $(a).observe("mouseover", function () { handleHover(a,500); }); - - a.observe("mouseover",function () { - logger("mouse entered model-link %s",this.href); - menuSelector.canceller.cancel(); - menuSelector.show(this); - }); - a.observe("mouseout",function () { - logger("mouse left model-link %s",this.href); - menuSelector.canceller.schedule(); - }); + Behaviour.specify("A.model-link", 'breadcrumbs', 0, function (link) { + const isFirefox = (navigator.userAgent.indexOf("Firefox") !== -1) + // Firefox adds unwanted lines when copying buttons in text, so use a span instead + const dropdownChevron = document.createElement(isFirefox ? "span" : "button") + dropdownChevron.className = "jenkins-menu-dropdown-chevron" + dropdownChevron.addEventListener("click", function(e) { + e.preventDefault(); + invokeContextMenu(link); + }) + link.appendChild(dropdownChevron) }); Behaviour.specify("#breadcrumbs LI.children", 'breadcrumbs', 0, function (a) { - a.observe("mouseover",function() { - menuSelector.hide(); - }); - a.observe("click",function() { - invokeContextMenu(this,"childrenContextMenu"); + a.observe("click", function() { + invokeContextMenu(this, "childrenContextMenu"); }) }); - Behaviour.specify("#breadcrumbs A", 'breadcrumbs', 0, function (a) { - $(a).addClassName('breadcrumbBarAnchor'); - }); - /** * @namespace breadcrumbs * @class ContextMenu @@ -287,7 +202,7 @@ var breadcrumbs = (function() { * @return {breadcrumbs.MenuItem} */ "add" : function (url,icon,displayName) { - this.items.push({ url:url, text:makeMenuHtml(icon,displayName) }); + this.items.push({ url:url, text:makeMenuHtml(icon, null, displayName) }); return this; } }; @@ -304,7 +219,10 @@ var breadcrumbs = (function() { * populating the content. */ "attachMenu" : function (li,menu) { - $(li).firstChild.items = (typeof menu=="function") ? menu : function() { return menu.items }; + $(li).items = (typeof menu=="function") ? menu : function() { return menu.items }; + $(li).addEventListener("click", function() { + invokeContextMenu($(li)); + }) }, "ContextMenu" : ContextMenu diff --git a/core/src/main/resources/lib/layout/icon.jelly b/core/src/main/resources/lib/layout/icon.jelly index e4b4c47b2ea77..3d9b909cb65df 100644 --- a/core/src/main/resources/lib/layout/icon.jelly +++ b/core/src/main/resources/lib/layout/icon.jelly @@ -26,7 +26,15 @@ THE SOFTWARE. @since 1.576 - + + + Icon source + Supports Jenkins Symbols (e.g. 'symbol-search') + Supports path to bitmap image + Only relevant if the 'class' attribute is NOT specified. + + + The icon class specification e.g. 'icon-help icon-sm', 'icon-blue icon-md', 'icon-blue-anime icon-xlg'. @@ -34,56 +42,58 @@ THE SOFTWARE. ID of the icon element. Since TODO. - - Icon source raw URL. Only relevant if the 'class' attribute is NOT specified. - - onclick handler. Deprecated; assign an ID and look up the element that way to attach event handlers. - title + title, deprecated use tooltip instead style tooltip - alt + alt, adds invisible text suitable for screen-readers for symbols, sets the alt attribute for normal images - + + - - - - - - - - - - + + + + - - - + + + + + + + + + + + + + - - - + + + + + - - - + - - - + + + - - ${attrs.alt} + + ${attrs.alt} + + - diff --git a/core/src/main/resources/lib/layout/ionicon.jelly b/core/src/main/resources/lib/layout/ionicon.jelly deleted file mode 100644 index 15a7110197446..0000000000000 --- a/core/src/main/resources/lib/layout/ionicon.jelly +++ /dev/null @@ -1,18 +0,0 @@ - - - - Provides ionicon icons - - The name of the icon - - - Title to use for the icon - - - - - - - - - diff --git a/core/src/main/resources/lib/layout/layout.jelly b/core/src/main/resources/lib/layout/layout.jelly index 84396b3e6060e..577c5ecd4a503 100644 --- a/core/src/main/resources/lib/layout/layout.jelly +++ b/core/src/main/resources/lib/layout/layout.jelly @@ -187,10 +187,9 @@ THE SOFTWARE. - - + + - -
    diff --git a/core/src/main/resources/lib/layout/layout_pt_BR.properties b/core/src/main/resources/lib/layout/layout_pt_BR.properties index 9fdbe70f62cf7..5f9047d2664c1 100644 --- a/core/src/main/resources/lib/layout/layout_pt_BR.properties +++ b/core/src/main/resources/lib/layout/layout_pt_BR.properties @@ -25,3 +25,5 @@ search=pesquisar searchBox.url=https://www.jenkins.io/redirect/search-box # log out logout=sair +title=Jenkins +jenkinshead.alt=Jenkins diff --git a/core/src/main/resources/lib/layout/main-panel_pt_BR.properties b/core/src/main/resources/lib/layout/main-panel_pt_BR.properties index ef8a87e434ef6..e41a09e3bd444 100644 --- a/core/src/main/resources/lib/layout/main-panel_pt_BR.properties +++ b/core/src/main/resources/lib/layout/main-panel_pt_BR.properties @@ -20,4 +20,5 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -Jenkins\ is\ going\ to\ shut\ down=O Jenkins est\u00e1 desligando +Jenkins\ is\ going\ to\ shut\ down=O Jenkins est\u00E1 desligando +Shut\ down\ reason=Raz\u00E3o\ para\ desligamento diff --git a/core/src/main/resources/lib/layout/pane.jelly b/core/src/main/resources/lib/layout/pane.jelly index 5298a274f2e0d..c1f55e13d1020 100644 --- a/core/src/main/resources/lib/layout/pane.jelly +++ b/core/src/main/resources/lib/layout/pane.jelly @@ -30,7 +30,7 @@ THE SOFTWARE. The box is drawn as a table, and the body of this tag is expected to draw a series of <TR>s to fill in the contents of the box. - + Title of the box. Can include HTML. @@ -63,9 +63,8 @@ THE SOFTWARE. - - + +
    @@ -92,4 +91,4 @@ THE SOFTWARE. - \ No newline at end of file + diff --git a/core/src/main/resources/lib/layout/progressAnimation.jelly b/core/src/main/resources/lib/layout/progressAnimation.jelly index 1acc39a8c3af4..2e008f8cb391b 100644 --- a/core/src/main/resources/lib/layout/progressAnimation.jelly +++ b/core/src/main/resources/lib/layout/progressAnimation.jelly @@ -1,8 +1,18 @@ - + + + Display a CSS animation for progressive logging. This tag supersedes spinner.gif and is a drop in replacement: + + From + {noformat}<img src="${imagesURL}/spinner.gif" alt=""/>{noformat} + to + {noformat}<l:progressAnimation/>{noformat} + + @since 2.320 +
    -
    \ No newline at end of file +
    diff --git a/core/src/main/resources/lib/layout/rightspace.jelly b/core/src/main/resources/lib/layout/rightspace.jelly index 3e38e345d2a00..4b81c8bcf2d57 100644 --- a/core/src/main/resources/lib/layout/rightspace.jelly +++ b/core/src/main/resources/lib/layout/rightspace.jelly @@ -31,4 +31,4 @@ THE SOFTWARE.
    - \ No newline at end of file + diff --git a/core/src/main/resources/lib/layout/svgIcon.jelly b/core/src/main/resources/lib/layout/svgIcon.jelly index bd808215fe8df..8d79905c22b42 100644 --- a/core/src/main/resources/lib/layout/svgIcon.jelly +++ b/core/src/main/resources/lib/layout/svgIcon.jelly @@ -1,13 +1,13 @@ - Opinionated helper to use icons via <svg> tags. Can be used by passing an href or a body: # <l:svgIcon href="/path/to/my/sprite.svg#my-icon" /> # <l:svgIcon><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></l:svgIcon> + @since 2.222 Extra CSS classes passed to the icon. Currently only the 'svg-icon' class is applied by default. diff --git a/core/src/main/resources/lib/layout/tabNewItem.jelly b/core/src/main/resources/lib/layout/tabNewItem.jelly index b85769c75b778..f0d98237cfb37 100644 --- a/core/src/main/resources/lib/layout/tabNewItem.jelly +++ b/core/src/main/resources/lib/layout/tabNewItem.jelly @@ -11,7 +11,7 @@ diff --git a/core/src/main/resources/lib/layout/task.jelly b/core/src/main/resources/lib/layout/task.jelly index b130b15cfc3d1..5a7e61c9ffd93 100644 --- a/core/src/main/resources/lib/layout/task.jelly +++ b/core/src/main/resources/lib/layout/task.jelly @@ -37,6 +37,7 @@ THE SOFTWARE. Common values include: + # "symbol-search" / "symbol-terminal" / "symbol-settings" - use a Jenkins Symbol as the icon for your task # "icon-folder icon-md" is an example of using a class spec for a medium folder icon # "images/24x24/..." then points to the stock icon resources # "plugin/foobar/abc/def.png" that points to "src/main/webapp/abc/def.png" in your plugin resources @@ -56,7 +57,7 @@ THE SOFTWARE. This is useful for showing links to restricted pages, as showing them to unprivileged users don't make sense. - + If both permission and permissions is set, then permissions will be used @@ -113,6 +114,10 @@ THE SOFTWARE. + + + + - - - - - - - - - - - - - -
    - ${title} @@ -153,15 +144,11 @@ THE SOFTWARE.
    - - - ${taskTags!=null and attrs.contextMenu!='false' ? taskTags.add(href, iconMetadata.getQualifiedUrl(context), title, post == 'true', requiresConfirmation == 'true') : null} - - - ${taskTags!=null and attrs.contextMenu!='false' ? taskTags.add(href, icon, title, post == 'true', requiresConfirmation == 'true') : null} - - - + + + + + ${taskTags!=null and attrs.contextMenu!='false' ? taskTags.add(href, iconSrc, iconXml, title, post == 'true', requiresConfirmation == 'true') : null} "; String initialNodeName = "agent is a better name"; @@ -525,7 +529,7 @@ public void interruptOnDelete() throws Exception { j.jenkins.setNumExecutors(0); FreeStyleProject p = j.createFreeStyleProject(); - j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + j.buildAndAssertSuccess(p); node.setVirtualName(desiredNodeName); @@ -550,7 +554,7 @@ static class NameChangingNode extends Slave { private String virtualName; NameChangingNode(JenkinsRule j, String name) throws Exception { - super(name, "dummy", j.createTmpDir().getPath(), "1", Node.Mode.NORMAL, "", j.createComputerLauncher(null), RetentionStrategy.NOOP, new ArrayList<>()); + super(name, "dummy", j.createTmpDir().getPath(), "1", Node.Mode.NORMAL, "", j.createComputerLauncher(null), RetentionStrategy.NOOP, Collections.emptyList()); } public void setVirtualName(String virtualName) { diff --git a/test/src/test/java/hudson/model/LabelLoadStatisticsQueueLengthTest.java b/test/src/test/java/hudson/model/LabelLoadStatisticsQueueLengthTest.java index 0e29a791ca133..d977a8ed64a20 100644 --- a/test/src/test/java/hudson/model/LabelLoadStatisticsQueueLengthTest.java +++ b/test/src/test/java/hudson/model/LabelLoadStatisticsQueueLengthTest.java @@ -3,6 +3,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import edu.umd.cs.findbugs.annotations.NonNull; @@ -90,9 +91,9 @@ public void queueLengthReflectsBuildableItemsAssignedLabel() // Add the job to the build queue several times with an assigned label. for (int i = 0; i < 3; i++) { - project.scheduleBuild(0, CAUSE, new LabelAssignmentActionImpl(), + assertNotNull(project.scheduleBuild2(0, CAUSE, new LabelAssignmentActionImpl(), new ParametersAction(new StringParameterValue( - PARAMETER_NAME, String.valueOf(i)))); + PARAMETER_NAME, String.valueOf(i))))); } // Verify that the real queue length is 3. @@ -143,9 +144,9 @@ public void queueLengthReflectsJobsAssignedLabel() throws Exception { // Add the job to the build queue several times. for (int i = 0; i < 3; i++) { - project.scheduleBuild(0, CAUSE, + assertNotNull(project.scheduleBuild2(0, CAUSE, new ParametersAction(new StringParameterValue( - PARAMETER_NAME, String.valueOf(i)))); + PARAMETER_NAME, String.valueOf(i))))); } // Verify that the real queue length is 3. diff --git a/test/src/test/java/hudson/model/ListViewTest.java b/test/src/test/java/hudson/model/ListViewTest.java index 1ed5dc322d867..e21a81e2e60e6 100644 --- a/test/src/test/java/hudson/model/ListViewTest.java +++ b/test/src/test/java/hudson/model/ListViewTest.java @@ -87,7 +87,7 @@ public class ListViewTest { @Test public void nullJobNames() { assertTrue(j.jenkins.getView("v").getItems().isEmpty()); } - + @Test public void testJobLinksAreValid() throws Exception { /* @@ -101,7 +101,7 @@ public void testJobLinksAreValid() throws Exception { FreeStyleProject job1 = folder1.createProject(FreeStyleProject.class, "job1"); MockFolder folder2 = folder1.createProject(MockFolder.class, "folder2"); FreeStyleProject job2 = folder2.createProject(FreeStyleProject.class, "job2"); - + ListView lv = new ListView("myview"); lv.setRecurse(true); lv.setIncludeRegex(".*"); @@ -119,7 +119,7 @@ public void testJobLinksAreValid() throws Exception { checkLinkFromItemExistsAndIsValid(folder2, folder1, folder1, webClient); checkLinkFromViewExistsAndIsValid(job2, folder1, lv2, webClient); } - + private void checkLinkFromViewExistsAndIsValid(Item item, ItemGroup ig, View view, WebClient webClient) throws IOException, SAXException { HtmlPage page = webClient.goTo(view.getUrl()); HtmlAnchor link = page.getAnchorByText(Functions.getRelativeDisplayNameFrom(item, ig)); @@ -306,7 +306,7 @@ private void checkLinkFromItemExistsAndIsValid(Item item, ItemGroup ig, Item top names.add("f1/p3"); names.add("f2/p4"); lv.setJobNames(names); - assertThat(lv.getItems(), containsInAnyOrder(p1,p2)); + assertThat(lv.getItems(), containsInAnyOrder(p1, p2)); lv.setRecurse(true); assertThat(lv.getItems(), containsInAnyOrder(p1, p2, p3, p4)); } @@ -366,9 +366,11 @@ private static class AllButViewsAuthorizationStrategy extends AuthorizationStrat @Override public ACL getRootACL() { return UNSECURED.getRootACL(); } + @Override public Collection getGroups() { return Collections.emptyList(); } + @Override public ACL getACL(View item) { return new ACL() { @Override public boolean hasPermission2(Authentication a, Permission permission) { @@ -389,6 +391,7 @@ private static class Stream extends ServletInputStream { public int read() throws IOException { return inner.read(); } + @Override public int read(byte[] b) throws IOException { return inner.read(b); @@ -398,14 +401,17 @@ public int read(byte[] b) throws IOException { public int read(byte[] b, int off, int len) throws IOException { return inner.read(b, off, len); } + @Override public boolean isFinished() { throw new UnsupportedOperationException(); } + @Override public boolean isReady() { throw new UnsupportedOperationException(); } + @Override public void setReadListener(ReadListener readListener) { throw new UnsupportedOperationException(); diff --git a/test/src/test/java/hudson/model/ManagementLinkTest.java b/test/src/test/java/hudson/model/ManagementLinkTest.java index 4e7566a3d1440..8f6479a03be02 100644 --- a/test/src/test/java/hudson/model/ManagementLinkTest.java +++ b/test/src/test/java/hudson/model/ManagementLinkTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static org.junit.Assert.assertNull; @@ -52,13 +53,13 @@ public class ManagementLinkTest { public void links() throws Exception { WebClient wc = j.createWebClient(); - for (int i=0; ; i++) { + for (int i = 0; ; i++) { HtmlPage page = wc.goTo("manage"); List anchors = DomNodeUtil.selectNodes(page, "//div[contains(@class,'jenkins-section__item')]/a[not(contains(@class,'confirmation-link'))]"); - assertTrue(anchors.size()>=8); - if (i==anchors.size()) return; // done + assertTrue(anchors.size() >= 8); + if (i == anchors.size()) return; // done - ((HtmlAnchor)anchors.get(i)).click(); + ((HtmlAnchor) anchors.get(i)).click(); } } diff --git a/test/src/test/java/hudson/model/MyViewTest.java b/test/src/test/java/hudson/model/MyViewTest.java index efac83311e096..2392edfb396ad 100644 --- a/test/src/test/java/hudson/model/MyViewTest.java +++ b/test/src/test/java/hudson/model/MyViewTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static org.hamcrest.MatcherAssert.assertThat; @@ -49,7 +50,7 @@ * @author Lucie Votypkova */ public class MyViewTest { - + @Rule public JenkinsRule rule = new JenkinsRule(); @@ -60,11 +61,11 @@ public class MyViewTest { public void setup() { rule.jenkins.setSecurityRealm(rule.createDummySecurityRealm()); } - + @Test - public void testContains() throws Exception{ - - GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); + public void testContains() throws Exception { + + GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); rule.jenkins.setAuthorizationStrategy(auth); User user = User.getOrCreateByIdOrFullName("User1"); FreeStyleProject job = rule.createFreeStyleProject("job"); @@ -76,9 +77,9 @@ public void testContains() throws Exception{ auth.add(Item.CONFIGURE, "User1"); assertTrue("View " + view.getDisplayName() + " contain job " + job.getDisplayName(), view.contains(job)); } - + @Test - public void testDoCreateItem() throws Exception{ + public void testDoCreateItem() throws Exception { logs.record(AbstractItem.class, Level.ALL); MyView view = new MyView("My", rule.jenkins); rule.jenkins.addView(view); @@ -95,12 +96,12 @@ public void testDoCreateItem() throws Exception{ assumeThat("TODO sometimes on Windows CI the submission does not seem to be really processed (most log messages are missing)", item, notNullValue()); assertThat(view.getItems(), contains(equalTo(item))); } - + @Test public void testGetItems() throws IOException { User user = User.getOrCreateByIdOrFullName("User1"); - GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); - rule.jenkins.setAuthorizationStrategy(auth); + GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); + rule.jenkins.setAuthorizationStrategy(auth); FreeStyleProject job2 = rule.createFreeStyleProject("job2"); FreeStyleProject job = rule.createFreeStyleProject("job"); MyView view = new MyView("My", rule.jenkins); @@ -112,6 +113,6 @@ public void testGetItems() throws IOException { assertTrue("View " + view.getDisplayName() + " should contain job " + job.getDisplayName(), view.getItems().contains(job)); assertTrue("View " + view.getDisplayName() + " should contain job " + job2.getDisplayName(), view.getItems().contains(job2)); } - - + + } diff --git a/test/src/test/java/hudson/model/MyViewsPropertyTest.java b/test/src/test/java/hudson/model/MyViewsPropertyTest.java index 935ed5ab36de6..634eed0c9edcf 100644 --- a/test/src/test/java/hudson/model/MyViewsPropertyTest.java +++ b/test/src/test/java/hudson/model/MyViewsPropertyTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static org.junit.Assert.assertEquals; @@ -47,10 +48,10 @@ * @author Lucie Votypkova */ public class MyViewsPropertyTest { - + @Rule public JenkinsRule rule = new JenkinsRule(); - + @Test public void testReadResolve() throws IOException { User user = User.getOrCreateByIdOrFullName("User"); @@ -84,7 +85,7 @@ public void testSave() throws IOException { assertEquals("Property should have primary view " + view.name + " instead of " + property.getPrimaryViewName(), view.name, property.getPrimaryViewName()); } */ - + @Test public void testGetViews() throws IOException { User user = User.getOrCreateByIdOrFullName("User"); @@ -92,11 +93,11 @@ public void testGetViews() throws IOException { property.readResolve(); property.setUser(user); assertTrue("Property should contain " + AllView.DEFAULT_VIEW_NAME, property.getViews().contains(property.getView(AllView.DEFAULT_VIEW_NAME))); - View view = new ListView("foo",property); + View view = new ListView("foo", property); property.addView(view); assertTrue("Property should contain " + view.name, property.getViews().contains(view)); } - + @Test public void testGetView() throws IOException { User user = User.getOrCreateByIdOrFullName("User"); @@ -105,11 +106,11 @@ public void testGetView() throws IOException { property.setUser(user); assertNotNull("Property should contain " + AllView.DEFAULT_VIEW_NAME, property.getView( AllView.DEFAULT_VIEW_NAME)); - View view = new ListView("foo",property); + View view = new ListView("foo", property); property.addView(view); assertEquals("Property should contain " + view.name, view, property.getView(view.name)); } - + @Test public void testGetPrimaryView() throws IOException { User user = User.getOrCreateByIdOrFullName("User"); @@ -117,13 +118,13 @@ public void testGetPrimaryView() throws IOException { property.readResolve(); property.setUser(user); user.addProperty(property); - assertEquals("Property should have primary view " + AllView.DEFAULT_VIEW_NAME + " instead of " + property.getPrimaryView(). name,property.getView(AllView.DEFAULT_VIEW_NAME), property.getPrimaryView()); + assertEquals("Property should have primary view " + AllView.DEFAULT_VIEW_NAME + " instead of " + property.getPrimaryView(). name, property.getView(AllView.DEFAULT_VIEW_NAME), property.getPrimaryView()); View view = new ListView("foo", property); property.addView(view); property.setPrimaryViewName(view.name); assertEquals("Property should have primary view " + view.name + " instead of " + property.getPrimaryView().name, view, property.getPrimaryView()); } - + @Test public void testCanDelete() throws IOException { User user = User.getOrCreateByIdOrFullName("User"); @@ -134,9 +135,9 @@ public void testCanDelete() throws IOException { assertFalse("Property should not enable to delete view " + AllView.DEFAULT_VIEW_NAME, property.canDelete(property.getView(AllView.DEFAULT_VIEW_NAME))); View view = new ListView("foo", property); property.addView(view); - assertTrue("Property should enable to delete view " + view.name , property.canDelete(view)); + assertTrue("Property should enable to delete view " + view.name, property.canDelete(view)); property.setPrimaryViewName(view.name); - assertFalse("Property should not enable to delete view " + view.name , property.canDelete(view)); + assertFalse("Property should not enable to delete view " + view.name, property.canDelete(view)); assertTrue("Property should enable to delete view " + AllView.DEFAULT_VIEW_NAME, property.canDelete(property.getView(AllView.DEFAULT_VIEW_NAME))); } @@ -148,10 +149,10 @@ public void testDeleteView() throws IOException { property.setUser(user); user.addProperty(property); boolean ex = false; - try{ + try { property.deleteView(property.getView(AllView.DEFAULT_VIEW_NAME)); } - catch(IllegalStateException e){ + catch (IllegalStateException e) { ex = true; } assertTrue("Property should throw IllegalStateException.", ex); @@ -159,16 +160,16 @@ public void testDeleteView() throws IOException { View view = new ListView("foo", property); property.addView(view); ex = false; - try{ + try { property.deleteView(view); } - catch(IllegalStateException e){ + catch (IllegalStateException e) { ex = true; } - assertFalse("Property should not contain view " + view.name , property.getViews().contains(view)); + assertFalse("Property should not contain view " + view.name, property.getViews().contains(view)); property.addView(view); property.setPrimaryViewName(view.name); - assertTrue("Property should not contain view " + view.name , property.getViews().contains(view)); + assertTrue("Property should not contain view " + view.name, property.getViews().contains(view)); property.deleteView(property.getView(AllView.DEFAULT_VIEW_NAME)); assertFalse("Property should not contains view " + AllView.DEFAULT_VIEW_NAME, property.getViews().contains(property.getView(AllView.DEFAULT_VIEW_NAME))); } @@ -183,8 +184,8 @@ public void testOnViewRenamed() throws IOException, FormException { View view = new ListView("foo", property); property.addView(view); property.setPrimaryViewName(view.name); - view.rename("primary-renamed"); - assertEquals("Property should rename its primary view ", "primary-renamed", property.getPrimaryViewName()); + view.rename("primary-renamed"); + assertEquals("Property should rename its primary view ", "primary-renamed", property.getPrimaryViewName()); } @Test @@ -219,7 +220,7 @@ public void testDoCreateView() throws Exception { form.getInputByName("name").setValueAttribute("foo"); form.getRadioButtonsByName("mode").get(0).setChecked(true); rule.submit(form); - assertNotNull("Property should contain view foo", property.getView("foo")); + assertNotNull("Property should contain view foo", property.getView("foo")); } rule.jenkins.reload(); { @@ -235,7 +236,7 @@ public void testGetACL() throws IOException { property.readResolve(); property.setUser(user); user.addProperty(property); - for(Permission p : Permission.getAll()){ + for (Permission p : Permission.getAll()) { assertEquals("Property should have the same ACL as its user", property.hasPermission(p), user.hasPermission(p)); } } @@ -248,31 +249,31 @@ public void testCheckPermission() throws IOException { MyViewsProperty property = new MyViewsProperty(AllView.DEFAULT_VIEW_NAME); property.readResolve(); property.setUser(user); - GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); - rule.jenkins.setAuthorizationStrategy(auth); + GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); + rule.jenkins.setAuthorizationStrategy(auth); user.addProperty(property); boolean ex = false; SecurityContextHolder.getContext().setAuthentication(user2.impersonate2()); - try{ + try { property.checkPermission(Permission.CONFIGURE); } - catch(AccessDeniedException e){ + catch (AccessDeniedException e) { ex = true; } - assertTrue("Property should throw AccessDeniedException.",ex); + assertTrue("Property should throw AccessDeniedException.", ex); SecurityContextHolder.getContext().setAuthentication(user.impersonate2()); - try{ + try { property.checkPermission(Permission.CONFIGURE); } - catch(AccessDeniedException e){ + catch (AccessDeniedException e) { fail("Property should not throw AccessDeniedException - user should control of himself."); } SecurityContextHolder.getContext().setAuthentication(user2.impersonate2()); auth.add(Jenkins.ADMINISTER, "User2"); - try{ + try { property.checkPermission(Permission.CONFIGURE); } - catch(AccessDeniedException e){ + catch (AccessDeniedException e) { fail("Property should not throw AccessDeniedException."); } } @@ -285,15 +286,15 @@ public void testHasPermission() throws IOException { MyViewsProperty property = new MyViewsProperty(AllView.DEFAULT_VIEW_NAME); property.readResolve(); property.setUser(user); - GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); - rule.jenkins.setAuthorizationStrategy(auth); + GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); + rule.jenkins.setAuthorizationStrategy(auth); user.addProperty(property); SecurityContextHolder.getContext().setAuthentication(user2.impersonate2()); - assertFalse("User User2 should not configure permission for user User",property.hasPermission(Permission.CONFIGURE)); + assertFalse("User User2 should not configure permission for user User", property.hasPermission(Permission.CONFIGURE)); SecurityContextHolder.getContext().setAuthentication(user.impersonate2()); assertTrue("User should control of himself.", property.hasPermission(Permission.CONFIGURE)); auth.add(Jenkins.ADMINISTER, "User2"); - assertTrue("User User2 should configure permission for user User",property.hasPermission(Permission.CONFIGURE)); + assertTrue("User User2 should configure permission for user User", property.hasPermission(Permission.CONFIGURE)); } @Test @@ -310,5 +311,5 @@ public void shouldNotFailWhenMigratingLegacyViewsWithoutPrimaryOne() throws IOEx property.addView(new AllView("foobar")); property.readResolve(); } - + } diff --git a/test/src/test/java/hudson/model/NodeTest.java b/test/src/test/java/hudson/model/NodeTest.java index 250428e80b606..9fe57c86875ef 100644 --- a/test/src/test/java/hudson/model/NodeTest.java +++ b/test/src/test/java/hudson/model/NodeTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static org.hamcrest.MatcherAssert.assertThat; @@ -36,6 +37,7 @@ import com.gargoylesoftware.htmlunit.HttpMethod; import com.gargoylesoftware.htmlunit.Page; import com.gargoylesoftware.htmlunit.WebRequest; +import edu.umd.cs.findbugs.annotations.NonNull; import hudson.EnvVars; import hudson.FilePath; import hudson.model.Node.Mode; @@ -81,7 +83,7 @@ public class NodeTest { public static boolean notTake = false; @Before - public void before(){ + public void before() { addDynamicLabel = false; notTake = false; j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); @@ -94,7 +96,7 @@ public void testSetTemporaryOfflineCause() throws Exception { project.setAssignedLabel(j.jenkins.getLabel(node.getDisplayName())); OfflineCause cause = new OfflineCause.ByCLI("message"); node.setTemporaryOfflineCause(cause); - for(ComputerListener l : ComputerListener.all()){ + for (ComputerListener l : ComputerListener.all()) { l.onOnline(node.toComputer(), TaskListener.NULL); } assertEquals("Node should have offline cause which was set.", cause, node.toComputer().getOfflineCause()); @@ -165,10 +167,9 @@ public void testGetLabelCloud() throws Exception { label.reset(); // Make sure cached value is not used TagCloud cloud = node.getLabelCloud(); for (TagCloud.Entry e : cloud) { - if(e.item.equals(label)){ + if (e.item.equals(label)) { assertEquals("Label label1 should have one tied project.", 1, e.weight, 0); - } - else{ + } else { assertEquals("Label " + e.item + " should not have any tied project.", 0, e.weight, 0); } } @@ -203,7 +204,7 @@ public void testCanTake() throws Exception { assertNull("Node should take project which is assigned to its label.", node.canTake(item)); assertNull("Node should take project which is assigned to its label.", node.canTake(item2)); assertNotNull("Node should not take project which is not assigned to its label.", node.canTake(item3)); - String message = Messages._Node_LabelMissing(node.getNodeName(),j.jenkins.getLabel("notContained")).toString(); + String message = Messages._Node_LabelMissing(node.getNodeName(), j.jenkins.getLabel("notContained")).toString(); assertEquals("Cause of blockage should be missing label.", message, node.canTake(item3).getShortDescription()); node.setMode(Node.Mode.EXCLUSIVE); assertNotNull("Node should not take project which has null label because it is in exclusive mode.", node.canTake(item2)); @@ -223,7 +224,7 @@ public void testCanTake() throws Exception { notTake = false; QueueItemAuthenticatorConfiguration.get().getAuthenticators().add(new MockQueueItemAuthenticator(Collections.singletonMap(project.getFullName(), user.impersonate()))); assertNotNull("Node should not take project because user does not have build permission.", node.canTake(item)); - message = Messages._Node_LackingBuildPermission(item.authenticate2().getName(),node.getNodeName()).toString(); + message = Messages._Node_LackingBuildPermission(item.authenticate2().getName(), node.getNodeName()).toString(); assertEquals("Cause of blockage should be build permission label.", message, node.canTake(item).getShortDescription()); } @@ -248,7 +249,7 @@ public void testHasPermission() throws Exception { j.jenkins.setCrumbIssuer(null); HudsonPrivateSecurityRealm realm = new HudsonPrivateSecurityRealm(false); j.jenkins.setSecurityRealm(realm); - User user = realm.createAccount("John Smith","abcdef"); + User user = realm.createAccount("John Smith", "abcdef"); SecurityContextHolder.getContext().setAuthentication(user.impersonate2()); assertFalse("Current user should not have permission read.", node.hasPermission(Permission.READ)); auth.add(Computer.CONFIGURE, user.getId()); @@ -427,12 +428,13 @@ public void assertThatCloudLabelContains(TagCloud tagCloud, String ex } @TestExtension - public static class LabelFinderImpl extends LabelFinder{ + public static class LabelFinderImpl extends LabelFinder { + @NonNull @Override - public Collection findLabels(Node node) { + public Collection findLabels(@NonNull Node node) { List atoms = new ArrayList<>(); - if(addDynamicLabel){ + if (addDynamicLabel) { atoms.add(Jenkins.get().getLabelAtom("dynamicLabel")); } return atoms; @@ -442,11 +444,11 @@ public Collection findLabels(Node node) { } @TestExtension - public static class NodePropertyImpl extends NodeProperty{ + public static class NodePropertyImpl extends NodeProperty { @Override - public CauseOfBlockage canTake(Queue.BuildableItem item){ - if(notTake) + public CauseOfBlockage canTake(Queue.BuildableItem item) { + if (notTake) return new CauseOfBlockage.BecauseLabelIsBusy(item.getAssignedLabel()); return null; } diff --git a/test/src/test/java/hudson/model/ParametersTest.java b/test/src/test/java/hudson/model/ParametersTest.java index 96c81998384ae..e21afb4c10400 100644 --- a/test/src/test/java/hudson/model/ParametersTest.java +++ b/test/src/test/java/hudson/model/ParametersTest.java @@ -15,6 +15,7 @@ import com.gargoylesoftware.htmlunit.html.HtmlFormUtil; import com.gargoylesoftware.htmlunit.html.HtmlOption; import com.gargoylesoftware.htmlunit.html.HtmlPage; +import com.gargoylesoftware.htmlunit.html.HtmlSelect; import com.gargoylesoftware.htmlunit.html.HtmlTextInput; import edu.umd.cs.findbugs.annotations.NonNull; import hudson.markup.MarkupFormatter; @@ -46,7 +47,7 @@ public class ParametersTest { @Test public void parameterTypes() throws Exception { FreeStyleProject otherProject = j.createFreeStyleProject(); - otherProject.scheduleBuild2(0).get(); + j.buildAndAssertSuccess(otherProject); FreeStyleProject project = j.createFreeStyleProject(); ParametersDefinitionProperty pdp = new ParametersDefinitionProperty( @@ -66,7 +67,7 @@ public void parameterTypes() throws Exception { HtmlElement element = (HtmlElement) ((HtmlElement) DomNodeUtil.selectSingleNode(form, "//div[input/@value='string']")).getParentNode(); assertNotNull(element); - assertEquals("string description", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getNextSibling().getNextSibling(), "div[@class='setting-description']")).getTextContent()); + assertEquals("string description", element.getParentNode().querySelector(".jenkins-form-description").getTextContent()); HtmlTextInput stringParameterInput = DomNodeUtil.selectSingleNode(element, ".//input[@name='value']"); assertEquals("defaultValue", stringParameterInput.getAttribute("value")); @@ -75,27 +76,24 @@ public void parameterTypes() throws Exception { element = DomNodeUtil.selectSingleNode(form, "//div[input/@value='boolean']"); assertNotNull(element); - assertEquals("boolean description", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getParentNode().getNextSibling().getNextSibling().getNextSibling(), "div[@class='setting-description']")).getTextContent()); + assertEquals("boolean description", element.getParentNode().getParentNode().querySelector(".jenkins-form-description").getTextContent()); Object o = DomNodeUtil.selectSingleNode(element, ".//input[@name='value']"); - System.out.println(o); HtmlCheckBoxInput booleanParameterInput = (HtmlCheckBoxInput) o; assertTrue(booleanParameterInput.isChecked()); assertEquals("boolean", element.getTextContent()); element = (HtmlElement) ((HtmlElement) DomNodeUtil.selectSingleNode(form, ".//div[input/@value='choice']")).getParentNode(); assertNotNull(element); - assertEquals("choice description", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getNextSibling().getNextSibling(), "div[@class='setting-description']")).getTextContent()); + assertEquals("choice description", element.getParentNode().querySelector(".jenkins-form-description").getTextContent()); assertEquals("choice", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getParentNode(), "div[contains(@class, 'jenkins-form-label')]")).getTextContent()); element = (HtmlElement) ((HtmlElement) DomNodeUtil.selectSingleNode(form, ".//div[input/@value='run']")).getParentNode(); assertNotNull(element); - assertEquals("run description", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getNextSibling().getNextSibling(), "div[@class='setting-description']")).getTextContent()); + assertEquals("run description", element.getParentNode().querySelector(".jenkins-form-description").getTextContent()); assertEquals("run", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getParentNode(), "div[contains(@class, 'jenkins-form-label')]")).getTextContent()); j.submit(form); - Queue.Item q = j.jenkins.getQueue().getItem(project); - if (q != null) q.getFuture().get(); - else Thread.sleep(1000); + j.waitUntilNoActivity(); assertEquals("newValue", builder.getEnvVars().get("STRING")); assertEquals("true", builder.getEnvVars().get("BOOLEAN")); @@ -117,19 +115,20 @@ public void choiceWithLTGT() throws Exception { HtmlPage page = wc.goTo("job/" + project.getName() + "/build?delay=0sec"); HtmlForm form = page.getFormByName("parameters"); - HtmlElement element = (HtmlElement) ((HtmlElement) DomNodeUtil.selectSingleNode(form, ".//div[input/@value='choice']")).getParentNode(); + HtmlElement element = (HtmlElement) (form.getElementsByAttribute("input", "name", "name")).get(0).getParentNode(); assertNotNull(element); - assertEquals("choice description", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getNextSibling().getNextSibling(), "div[@class='setting-description']")).getTextContent()); - assertEquals("choice", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getParentNode(), "div[contains(@class, 'jenkins-form-label')]")).getTextContent()); - HtmlOption opt = DomNodeUtil.selectSingleNode(element.getParentNode(), "div/div/select/option[@value='Choice <2>']"); + assertEquals("choice description", ((HtmlElement) DomNodeUtil.selectSingleNode(form, "//div[contains(@class, 'jenkins-form-description')]")).getTextContent()); + assertEquals("choice", ((HtmlElement) DomNodeUtil.selectSingleNode(form, "//div[contains(@class, 'jenkins-form-label')]")).getTextContent()); + + HtmlSelect choiceSelect = (HtmlSelect) form.getElementsByAttribute("select", "name", "value").get(0); + + HtmlOption opt = DomNodeUtil.selectSingleNode(choiceSelect, "option[@value='Choice <2>']"); assertNotNull(opt); - assertEquals("Choice <2>", opt.asText()); + assertEquals("Choice <2>", opt.asNormalizedText()); opt.setSelected(true); j.submit(form); - Queue.Item q = j.jenkins.getQueue().getItem(project); - if (q != null) q.getFuture().get(); - else Thread.sleep(1000); + j.waitUntilNoActivity(); assertNotNull(builder.getEnvVars()); assertEquals("Choice <2>", builder.getEnvVars().get("CHOICE")); @@ -145,7 +144,7 @@ public void sensitiveParameters() throws Exception { CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); project.getBuildersList().add(builder); - FreeStyleBuild build = project.scheduleBuild2(0).get(); + FreeStyleBuild build = j.buildAndAssertSuccess(project); Set sensitiveVars = build.getSensitiveBuildVariables(); assertNotNull(sensitiveVars); @@ -162,7 +161,7 @@ public void nonSensitiveParameters() throws Exception { CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); project.getBuildersList().add(builder); - FreeStyleBuild build = project.scheduleBuild2(0).get(); + FreeStyleBuild build = j.buildAndAssertSuccess(project); Set sensitiveVars = build.getSensitiveBuildVariables(); assertNotNull(sensitiveVars); @@ -182,7 +181,7 @@ public void mixedSensitivity() throws Exception { CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); project.getBuildersList().add(builder); - FreeStyleBuild build = project.scheduleBuild2(0).get(); + FreeStyleBuild build = j.buildAndAssertSuccess(project); Set sensitiveVars = build.getSensitiveBuildVariables(); assertNotNull(sensitiveVars); @@ -205,9 +204,7 @@ public void fileParameterNotSet() throws Exception { HtmlForm form = page.getFormByName("parameters"); j.submit(form); - Queue.Item q = j.jenkins.getQueue().getItem(project); - if (q != null) q.getFuture().get(); - else Thread.sleep(1000); + j.waitUntilNoActivity(); assertFalse("file must not exist", project.getSomeWorkspace().child("filename").exists()); } @@ -231,6 +228,7 @@ public void unicodeParametersArePresetCorrectly() throws Exception { wc.setThrowExceptionOnFailingStatusCode(true); final HtmlForm form = page.getFormByName("parameters"); HtmlFormUtil.submit(form, HtmlFormUtil.getButtonByCaption(form, "Build")); + j.waitUntilNoActivity(); } @Issue("SECURITY-353") @@ -267,6 +265,7 @@ public void xss() throws Exception { collector.checkThat("parameters page should mark up param description", text, containsString("[param description]")); collector.checkThat("parameters page should not leave param description unescaped", text, not(containsString(""))); } + static class MyMarkupFormatter extends MarkupFormatter { @Override public void translate(String markup, @NonNull Writer output) throws IOException { diff --git a/test/src/test/java/hudson/model/PasswordParameterDefinitionTest.java b/test/src/test/java/hudson/model/PasswordParameterDefinitionTest.java index 67ee5e9638eb8..6541af0682a2a 100644 --- a/test/src/test/java/hudson/model/PasswordParameterDefinitionTest.java +++ b/test/src/test/java/hudson/model/PasswordParameterDefinitionTest.java @@ -53,7 +53,7 @@ public class PasswordParameterDefinitionTest { @Issue("JENKINS-36476") @Test public void defaultValueAlwaysAvailable() throws Exception { ApiTokenTestHelper.enableLegacyBehavior(); - + j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); j.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy(). grant(Jenkins.ADMINISTER).everywhere().to("admin"). diff --git a/test/src/test/java/hudson/model/PeriodicWorkTest.java b/test/src/test/java/hudson/model/PeriodicWorkTest.java index de76308fa2ff0..c6d828539c66f 100644 --- a/test/src/test/java/hudson/model/PeriodicWorkTest.java +++ b/test/src/test/java/hudson/model/PeriodicWorkTest.java @@ -24,7 +24,7 @@ public void newExtensionsAreScheduled() throws Exception { int size = PeriodicWork.all().size(); ExtensionList.lookup(PeriodicWork.class).add(tpw); - assertThat("we have one new PeriodicWork", PeriodicWork.all(), hasSize(size+1)); + assertThat("we have one new PeriodicWork", PeriodicWork.all(), hasSize(size + 1)); assertThat("The task was run within 15 seconds", tpw.doneSignal.await(15, TimeUnit.SECONDS), is(true)); } diff --git a/test/src/test/java/hudson/model/ProjectTest.java b/test/src/test/java/hudson/model/ProjectTest.java index 85e350f90b14c..8d2318fd11493 100644 --- a/test/src/test/java/hudson/model/ProjectTest.java +++ b/test/src/test/java/hudson/model/ProjectTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static org.junit.Assert.assertEquals; @@ -108,12 +109,12 @@ * @author Lucie Votypkova */ public class ProjectTest { - + @Rule public JenkinsRule j = new JenkinsRule(); public static boolean createAction = false; public static boolean getFilePath = false; public static boolean createSubTask = false; - + @Test public void testSave() throws IOException, InterruptedException, ReactorException { FreeStyleProject p = j.createFreeStyleProject("project"); @@ -126,9 +127,9 @@ public void testSave() throws IOException, InterruptedException, ReactorExceptio assertEquals("All persistent data should be saved.", 5, p.nextBuildNumber); assertTrue("All persistent data should be saved", p.disabled); } - + @Test - public void testOnCreateFromScratch() throws Exception{ + public void testOnCreateFromScratch() throws Exception { FreeStyleProject p = j.createFreeStyleProject("project"); j.buildAndAssertSuccess(p); p.removeRun(p.getLastBuild()); @@ -138,9 +139,9 @@ public void testOnCreateFromScratch() throws Exception{ assertNotNull("Project should have transient action TransientAction.", p.getAction(TransientAction.class)); createAction = false; } - + @Test - public void testOnLoad() throws Exception{ + public void testOnLoad() throws Exception { FreeStyleProject p = j.createFreeStyleProject("project"); j.buildAndAssertSuccess(p); p.removeRun(p.getLastBuild()); @@ -151,27 +152,27 @@ public void testOnLoad() throws Exception{ assertNotNull("Project should have Transient Action TransientAction.", p.getAction(TransientAction.class)); createAction = false; } - + @Test - public void testGetEnvironment() throws Exception{ + public void testGetEnvironment() throws Exception { FreeStyleProject p = j.createFreeStyleProject("project"); Slave slave = j.createOnlineSlave(); - EnvironmentVariablesNodeProperty.Entry entry = new EnvironmentVariablesNodeProperty.Entry("jdk","some_java"); + EnvironmentVariablesNodeProperty.Entry entry = new EnvironmentVariablesNodeProperty.Entry("jdk", "some_java"); slave.getNodeProperties().add(new EnvironmentVariablesNodeProperty(entry)); EnvVars var = p.getEnvironment(slave, TaskListener.NULL); assertEquals("Environment should have set jdk.", "some_java", var.get("jdk")); } - + @Test - public void testPerformDelete() throws Exception{ + public void testPerformDelete() throws Exception { FreeStyleProject p = j.createFreeStyleProject("project"); p.performDelete(); assertFalse("Project should be deleted from disk.", p.getConfigFile().exists()); assertTrue("Project should be disabled when deleting start.", p.isDisabled()); } - + @Test - public void testGetAssignedLabel() throws Exception{ + public void testGetAssignedLabel() throws Exception { FreeStyleProject p = j.createFreeStyleProject("project"); p.setAssignedLabel(j.jenkins.getSelfLabel()); Slave slave = j.createOnlineSlave(); @@ -181,9 +182,9 @@ public void testGetAssignedLabel() throws Exception{ p.setAssignedLabel(slave.getSelfLabel()); assertEquals("Project should have self label of slave", slave.getSelfLabel(), p.getAssignedLabel()); } - + @Test - public void testGetAssignedLabelString() throws Exception{ + public void testGetAssignedLabelString() throws Exception { FreeStyleProject p = j.createFreeStyleProject("project"); Slave slave = j.createOnlineSlave(); assertNull("Project should not have any label.", p.getAssignedLabelString()); @@ -193,9 +194,9 @@ public void testGetAssignedLabelString() throws Exception{ assertEquals("Project should return name of slave.", slave.getSelfLabel().name, p.getAssignedLabelString()); } - + @Test - public void testGetSomeWorkspace() throws Exception{ + public void testGetSomeWorkspace() throws Exception { FreeStyleProject p = j.createFreeStyleProject("project"); assertNull("Project which has never run should not have any workspace.", p.getSomeWorkspace()); getFilePath = true; @@ -206,9 +207,9 @@ public void testGetSomeWorkspace() throws Exception{ j.buildAndAssertSuccess(p); assertNotNull("Project should has any workspace.", p.getSomeWorkspace()); } - + @Test - public void testGetSomeBuildWithWorkspace() throws Exception{ + public void testGetSomeBuildWithWorkspace() throws Exception { FreeStyleProject p = j.createFreeStyleProject("project"); String cmd = "echo ahoj > some.log"; p.getBuildersList().add(Functions.isWindows() ? new BatchFile(cmd) : new Shell(cmd)); @@ -231,9 +232,9 @@ public void testGetSomeBuildWithWorkspace() throws Exception{ p.doDoWipeOutWorkspace(); wc.assertFails("job/project/ws/some.log", 404); } - + @Test - public void testGetQuietPeriod() throws IOException{ + public void testGetQuietPeriod() throws IOException { FreeStyleProject p = j.createFreeStyleProject("project"); assertEquals("Quiet period should be default.", j.jenkins.getQuietPeriod(), p.getQuietPeriod()); j.jenkins.setQuietPeriod(0); @@ -241,9 +242,9 @@ public void testGetQuietPeriod() throws IOException{ p.setQuietPeriod(10); assertEquals("Quiet period was set.", 10, p.getQuietPeriod()); } - + @Test - public void testGetScmCheckoutStrategy() throws IOException{ + public void testGetScmCheckoutStrategy() throws IOException { FreeStyleProject p = j.createFreeStyleProject("project"); p.setScmCheckoutStrategy(null); assertTrue("Project should return default checkout strategy if scm checkout strategy is not set.", p.getScmCheckoutStrategy() instanceof DefaultSCMCheckoutStrategyImpl); @@ -251,24 +252,24 @@ public void testGetScmCheckoutStrategy() throws IOException{ p.setScmCheckoutStrategy(strategy); assertEquals("Project should return its scm checkout strategy if this strategy is not null", strategy, p.getScmCheckoutStrategy()); } - + @Test - public void testGetScmCheckoutRetryCount() throws Exception{ + public void testGetScmCheckoutRetryCount() throws Exception { FreeStyleProject p = j.createFreeStyleProject("project"); assertEquals("Scm retry count should be default.", j.jenkins.getScmCheckoutRetryCount(), p.getScmCheckoutRetryCount()); j.jenkins.setScmCheckoutRetryCount(6); assertEquals("Scm retry count should be the same as global scm retry count.", 6, p.getScmCheckoutRetryCount()); HtmlForm form = j.createWebClient().goTo(p.getUrl() + "/configure").getFormByName("config"); - ((HtmlElement)form.getByXPath("//div[@class='advancedLink']//button").get(0)).click(); + ((HtmlElement) form.getByXPath("//div[@class='advancedLink']//button").get(0)).click(); // required due to the new default behavior of click form.getInputByName("hasCustomScmCheckoutRetryCount").click(new Event(), false, false, false, true); form.getInputByName("scmCheckoutRetryCount").setValueAttribute("7"); j.submit(form); assertEquals("Scm retry count was set.", 7, p.getScmCheckoutRetryCount()); } - + @Test - public void isBuildable() throws IOException{ + public void isBuildable() throws IOException { FreeStyleProject p = j.createFreeStyleProject("project"); assertTrue("Project should be buildable.", p.isBuildable()); p.disable(); @@ -279,9 +280,9 @@ public void isBuildable() throws IOException{ p2.save(); assertTrue("Project should be buildable after save.", p2.isBuildable()); } - + @Test - public void testMakeDisabled() throws IOException{ + public void testMakeDisabled() throws IOException { FreeStyleProject p = j.createFreeStyleProject("project"); p.makeDisabled(false); assertFalse("Project should be enabled.", p.isDisabled()); @@ -293,9 +294,9 @@ public void testMakeDisabled() throws IOException{ p.makeDisabled(true); assertNull("Project should be canceled.", Queue.getInstance().getItem(p)); } - + @Test - public void testAddProperty() throws IOException{ + public void testAddProperty() throws IOException { FreeStyleProject p = j.createFreeStyleProject("project"); JobProperty prop = new JobPropertyImp(); createAction = true; @@ -303,27 +304,27 @@ public void testAddProperty() throws IOException{ assertNotNull("Project does not contain added property.", p.getProperty(prop.getClass())); assertNotNull("Project did not update transient actions.", p.getAction(TransientAction.class)); } - + @Test - public void testScheduleBuild2() throws IOException, InterruptedException{ + public void testScheduleBuild2() throws IOException, InterruptedException { FreeStyleProject p = j.createFreeStyleProject("project"); p.setAssignedLabel(j.jenkins.getLabel("nonExist")); p.scheduleBuild(0, new UserIdCause()); assertNotNull("Project should be in queue.", Queue.getInstance().getItem(p)); p.setAssignedLabel(null); int count = 0; - while(count<5 && p.getLastBuild()==null){ + while (count < 5 && p.getLastBuild() == null) { Thread.sleep(1000); //give some time to start build count++; } assertNotNull("Build should be done or in progress.", p.getLastBuild()); } - + @Test - public void testSchedulePolling() throws IOException, ANTLRException{ + public void testSchedulePolling() throws IOException, ANTLRException { FreeStyleProject p = j.createFreeStyleProject("project"); - assertFalse("Project should not schedule polling because no scm trigger is set.",p.schedulePolling()); + assertFalse("Project should not schedule polling because no scm trigger is set.", p.schedulePolling()); SCMTrigger trigger = new SCMTrigger("0 0 * * *"); p.addTrigger(trigger); trigger.start(p, true); @@ -331,7 +332,7 @@ public void testSchedulePolling() throws IOException, ANTLRException{ p.disable(); assertFalse("Project should not schedule polling because project is disabled.", p.schedulePolling()); } - + @Test public void testSaveAfterSet() throws Exception { FreeStyleProject p = j.createFreeStyleProject("project"); @@ -353,9 +354,9 @@ public void testSaveAfterSet() throws Exception { assertNotNull("Project did not save jdk", p.getJDK()); assertEquals("Project did not save custom workspace.", "/some/path", p.getCustomWorkspace()); } - + @Test - public void testGetActions() throws IOException{ + public void testGetActions() throws IOException { FreeStyleProject p = j.createFreeStyleProject("project"); createAction = true; p.updateTransientActions(); @@ -397,10 +398,10 @@ public void testGetCauseOfBlockage() throws Exception { private QueueTaskFuture waitForStart(FreeStyleProject p) throws InterruptedException, ExecutionException { long start = System.nanoTime(); - LOGGER.info("Scheduling "+p); + LOGGER.info("Scheduling " + p); QueueTaskFuture f = p.scheduleBuild2(0); f.waitForStart(); - LOGGER.info("Wait:"+ TimeUnit.NANOSECONDS.toMillis(System.nanoTime()-start)); + LOGGER.info("Wait:" + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start)); return f; } @@ -409,29 +410,29 @@ private void assertInstanceOf(String msg, Object o, Class t) { return; fail(msg + ": " + o); } - + @Test - public void testGetSubTasks() throws IOException{ + public void testGetSubTasks() throws IOException { FreeStyleProject p = j.createFreeStyleProject("project"); p.addProperty(new JobPropertyImp()); createSubTask = true; List subtasks = p.getSubTasks(); boolean containsSubTaskImpl = false; boolean containsSubTaskImpl2 = false; - for(SubTask sub: subtasks){ - if(sub instanceof SubTaskImpl) + for (SubTask sub : subtasks) { + if (sub instanceof SubTaskImpl) containsSubTaskImpl = true; - if(sub instanceof SubTaskImpl2) + if (sub instanceof SubTaskImpl2) containsSubTaskImpl2 = true; } createSubTask = false; assertTrue("Project should return subtasks provided by SubTaskContributor.", containsSubTaskImpl2); assertTrue("Project should return subtasks provided by JobProperty.", containsSubTaskImpl); - + } - + @Test - public void testCreateExecutable() throws IOException{ + public void testCreateExecutable() throws IOException { FreeStyleProject p = j.createFreeStyleProject("project"); Build build = p.createExecutable(); assertNotNull("Project should create executable.", build); @@ -441,11 +442,11 @@ public void testCreateExecutable() throws IOException{ build = p.createExecutable(); assertNull("Disabled project should not create executable.", build); assertEquals("Next build number should not be increased.", 2, p.nextBuildNumber); - + } - + @Test - public void testCheckout() throws Exception{ + public void testCheckout() throws Exception { SCM scm = new NullSCM(); FreeStyleProject p = j.createFreeStyleProject("project"); Slave slave = j.createOnlineSlave(); @@ -455,14 +456,14 @@ public void testCheckout() throws Exception{ FilePath path = slave.toComputer().getWorkspaceList().allocate(ws, build).path; build.setWorkspace(path); BuildListener listener = new StreamBuildListener(TaskListener.NULL.getLogger(), Charset.defaultCharset()); - assertTrue("Project with null smc should perform checkout without problems.", p.checkout(build, new RemoteLauncher(listener, slave.getChannel(), true), listener, new File(build.getRootDir(),"changelog.xml"))); + assertTrue("Project with null smc should perform checkout without problems.", p.checkout(build, new RemoteLauncher(listener, slave.getChannel(), true), listener, new File(build.getRootDir(), "changelog.xml"))); p.setScm(scm); - assertTrue("Project should perform checkout without problems.",p.checkout(build, new RemoteLauncher(listener, slave.getChannel(), true), listener, new File(build.getRootDir(),"changelog.xml"))); + assertTrue("Project should perform checkout without problems.", p.checkout(build, new RemoteLauncher(listener, slave.getChannel(), true), listener, new File(build.getRootDir(), "changelog.xml"))); } @Ignore("randomly failed: Project should have polling result no change expected: but was:") @Test - public void testPoll() throws Exception{ + public void testPoll() throws Exception { FreeStyleProject p = j.createFreeStyleProject("project"); SCM scm = new NullSCM(); p.setScm(null); @@ -476,7 +477,7 @@ public void testPoll() throws Exception{ p.scheduleBuild2(0); assertEquals("Project which build is building should have polling result result no change.", PollingResult.Change.NONE, p.poll(TaskListener.NULL).change); p.setAssignedLabel(null); - while(p.getLastBuild()==null) + while (p.getLastBuild() == null) Thread.sleep(100); //wait until build start assertEquals("Project should have polling result no change", PollingResult.Change.NONE, p.poll(TaskListener.NULL).change); SCM alwaysChange = new AlwaysChangedSCM(); @@ -484,9 +485,9 @@ public void testPoll() throws Exception{ j.buildAndAssertSuccess(p); assertEquals("Project should have polling result significant", PollingResult.Change.SIGNIFICANT, p.poll(TaskListener.NULL).change); } - + @Test - public void testHasParticipant() throws Exception{ + public void testHasParticipant() throws Exception { User user = User.get("John Smith", true, Collections.emptyMap()); FreeStyleProject project = j.createFreeStyleProject("project"); FreeStyleProject project2 = j.createFreeStyleProject("project2"); @@ -495,13 +496,13 @@ public void testHasParticipant() throws Exception{ j.buildAndAssertSuccess(project2); assertFalse("Project should not have any participant.", project2.hasParticipant(user)); scm.addChange().withAuthor(user.getId()); - project.setScm(scm); + project.setScm(scm); j.buildAndAssertSuccess(project); assertTrue("Project should have participant.", project.hasParticipant(user)); } - + @Test - public void testGetRelationship() throws Exception{ + public void testGetRelationship() throws Exception { final FreeStyleProject upstream = j.createFreeStyleProject("upstream"); FreeStyleProject downstream = j.createFreeStyleProject("downstream"); j.buildAndAssertSuccess(upstream); @@ -515,7 +516,7 @@ public void testGetRelationship() throws Exception{ downstream.getPublishersList().add(new Fingerprinter("change.log", false)); downstream.getBuildersList().add(new TestBuilder() { @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) { - for (Run.Artifact a: upstream.getLastBuild().getArtifacts()) { + for (Run.Artifact a : upstream.getLastBuild().getArtifacts()) { Util.copyFile(a.getFile(), new File(build.getWorkspace().child(a.getFileName()).getRemote())); } return true; @@ -530,34 +531,34 @@ public void testGetRelationship() throws Exception{ j.buildAndAssertSuccess(upstream); j.buildAndAssertSuccess(downstream); - Map relationship = upstream.getRelationship(downstream); + Map relationship = upstream.getRelationship(downstream); assertFalse("Project upstream should have relationship with downstream", relationship.isEmpty()); assertTrue("Relationship should contain upstream #3", relationship.containsKey(3)); assertFalse("Relationship should not contain upstream #4 because previous fingerprinted file was not changed since #3", relationship.containsKey(4)); assertEquals("downstream #2 should be the first build which depends on upstream #3", 2, relationship.get(3).min()); - assertEquals("downstream #3 should be the last build which depends on upstream #3", 3, relationship.get(3).max()-1); + assertEquals("downstream #3 should be the last build which depends on upstream #3", 3, relationship.get(3).max() - 1); assertEquals("downstream #4 should depend only on upstream #5", 4, relationship.get(5).min()); - assertEquals("downstream #4 should depend only on upstream #5", 4, relationship.get(5).max()-1); + assertEquals("downstream #4 should depend only on upstream #5", 4, relationship.get(5).max() - 1); } - + @Test - public void testDoCancelQueue() throws Exception{ + public void testDoCancelQueue() throws Exception { FreeStyleProject project = j.createFreeStyleProject("project"); - GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); + GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); j.jenkins.setAuthorizationStrategy(auth); j.jenkins.setCrumbIssuer(null); HudsonPrivateSecurityRealm realm = new HudsonPrivateSecurityRealm(false); - j.jenkins.setSecurityRealm(realm); + j.jenkins.setSecurityRealm(realm); User user = realm.createAccount("John Smith", "password"); try (ACLContext as = ACL.as(user)) { assertThrows("User should not have permission to build project", AccessDeniedException3.class, () -> project.doCancelQueue(null, null)); } } - + @Test - public void testDoDoDelete() throws Exception{ + public void testDoDoDelete() throws Exception { FreeStyleProject project = j.createFreeStyleProject("project"); - GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); + GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); j.jenkins.setAuthorizationStrategy(auth); j.jenkins.setCrumbIssuer(null); j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); @@ -575,23 +576,23 @@ public void testDoDoDelete() throws Exception{ HtmlPage p = wc.goTo(project.getUrl() + "delete"); List forms = p.getForms(); - for(HtmlForm form:forms){ - if("doDelete".equals(form.getAttribute("action"))){ + for (HtmlForm form : forms) { + if ("doDelete".equals(form.getAttribute("action"))) { j.submit(form); } } assertNull("Project should be deleted form memory.", j.jenkins.getItem(project.getDisplayName())); assertFalse("Project should be deleted form disk.", project.getRootDir().exists()); } - + @Test - public void testDoDoWipeOutWorkspace() throws Exception{ + public void testDoDoWipeOutWorkspace() throws Exception { FreeStyleProject project = j.createFreeStyleProject("project"); - GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); + GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); j.jenkins.setAuthorizationStrategy(auth); j.jenkins.setCrumbIssuer(null); HudsonPrivateSecurityRealm realm = new HudsonPrivateSecurityRealm(false); - j.jenkins.setSecurityRealm(realm); + j.jenkins.setSecurityRealm(realm); User user = realm.createAccount("John Smith", "password"); try (ACLContext as = ACL.as(user)) { assertThrows("User should not have permission to build project", AccessDeniedException3.class, project::doDoWipeOutWorkspace); @@ -603,7 +604,7 @@ public void testDoDoWipeOutWorkspace() throws Exception{ Slave slave = j.createOnlineSlave(); project.setAssignedLabel(slave.getSelfLabel()); String cmd = "echo hello > change.log"; - project.getBuildersList().add(Functions.isWindows()? new BatchFile(cmd) : new Shell(cmd)); + project.getBuildersList().add(Functions.isWindows() ? new BatchFile(cmd) : new Shell(cmd)); j.buildAndAssertSuccess(project); JenkinsRule.WebClient wc = j.createWebClient(); @@ -615,15 +616,15 @@ public void testDoDoWipeOutWorkspace() throws Exception{ Thread.sleep(500); assertFalse("Workspace should not exist.", project.getSomeWorkspace().exists()); } - + @Test - public void testDoDisable() throws Exception{ + public void testDoDisable() throws Exception { FreeStyleProject project = j.createFreeStyleProject("project"); - GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); + GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); j.jenkins.setAuthorizationStrategy(auth); j.jenkins.setCrumbIssuer(null); HudsonPrivateSecurityRealm realm = new HudsonPrivateSecurityRealm(false); - j.jenkins.setSecurityRealm(realm); + j.jenkins.setSecurityRealm(realm); User user = realm.createAccount("John Smith", "password"); try (ACLContext as = ACL.as(user)) { assertThrows("User should not have permission to build project", AccessDeniedException3.class, project::doDisable); @@ -637,18 +638,18 @@ public void testDoDisable() throws Exception{ HtmlPage p = wc.goTo(project.getUrl()); List forms = p.getForms(); - for(HtmlForm form:forms){ - if("disable".equals(form.getAttribute("action"))){ + for (HtmlForm form : forms) { + if ("disable".equals(form.getAttribute("action"))) { j.submit(form); } } assertTrue("Project should be disabled.", project.isDisabled()); } - + @Test - public void testDoEnable() throws Exception{ + public void testDoEnable() throws Exception { FreeStyleProject project = j.createFreeStyleProject("project"); - GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); + GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); j.jenkins.setAuthorizationStrategy(auth); j.jenkins.setCrumbIssuer(null); HudsonPrivateSecurityRealm realm = new HudsonPrivateSecurityRealm(false); @@ -669,43 +670,43 @@ public void testDoEnable() throws Exception{ HtmlPage p = wc.goTo(project.getUrl()); List forms = p.getForms(); - for(HtmlForm form:forms){ - if("enable".equals(form.getAttribute("action"))){ + for (HtmlForm form : forms) { + if ("enable".equals(form.getAttribute("action"))) { j.submit(form); } } assertFalse("Project should be enabled.", project.isDisabled()); } - + /** * Job is un-restricted (no nabel), this is submitted to queue, which spawns an on demand slave */ @Test public void testJobSubmittedShouldSpawnCloud() throws Exception { /* - * Setup a project with an SCM. Jenkins should have no executors in itself. + * Setup a project with an SCM. Jenkins should have no executors in itself. */ - FreeStyleProject proj = j.createFreeStyleProject("JENKINS-21394-spawn"); + FreeStyleProject proj = j.createFreeStyleProject("JENKINS-21394-spawn"); RequiresWorkspaceSCM requiresWorkspaceScm = new RequiresWorkspaceSCM(true); - proj.setScm(requiresWorkspaceScm); - j.jenkins.setNumExecutors(0); + proj.setScm(requiresWorkspaceScm); + j.jenkins.setNumExecutors(0); /* * We have a cloud */ DummyCloudImpl2 c2 = new DummyCloudImpl2(j, 0); - c2.label = new LabelAtom("test-cloud-label"); + c2.label = new LabelAtom("test-cloud-label"); j.jenkins.clouds.add(c2); - + SCMTrigger t = new SCMTrigger("@daily", true); t.start(proj, true); proj.addTrigger(t); t.new Runner().run(); - + Thread.sleep(1000); //Assert that the job IS submitted to Queue. - assertEquals(1, j.jenkins.getQueue().getItems().length); + assertEquals(1, j.jenkins.getQueue().getItems().length); } - + /** * Job is restricted, but label can not be provided by any cloud, only normal agents. Then job will not submit, because no slave is available. */ @@ -714,68 +715,68 @@ public void testUnrestrictedJobNoLabelByCloudNoQueue() throws Exception { assertTrue(j.jenkins.clouds.isEmpty()); //Create slave. (Online) Slave s1 = j.createOnlineSlave(); - + //Create a project, and bind the job to the created slave FreeStyleProject proj = j.createFreeStyleProject("JENKINS-21394-noqueue"); proj.setAssignedLabel(s1.getSelfLabel()); - + //Add an SCM to the project. We require a workspace for the poll RequiresWorkspaceSCM requiresWorkspaceScm = new RequiresWorkspaceSCM(true); proj.setScm(requiresWorkspaceScm); - - j.buildAndAssertSuccess(proj); + + j.buildAndAssertSuccess(proj); //Now create another slave. And restrict the job to that slave. The slave is offline, leaving the job with no assignable nodes. - //We tell our mock SCM to return that it has got changes. But since there are no agents, we get the desired result. + //We tell our mock SCM to return that it has got changes. But since there are no agents, we get the desired result. Slave s2 = j.createSlave(); proj.setAssignedLabel(s2.getSelfLabel()); requiresWorkspaceScm.hasChange = true; - + //Poll (We now should have NO online agents, this should now return NO_CHANGES. PollingResult pr = proj.poll(j.createTaskListener()); assertFalse(pr.hasChanges()); - + SCMTrigger t = new SCMTrigger("@daily", true); t.start(proj, true); proj.addTrigger(t); - + t.new Runner().run(); - + /* * Assert that the log contains the correct message. */ HtmlPage log = j.createWebClient().getPage(proj, "scmPollLog"); - String logastext = log.asText(); + String logastext = log.asNormalizedText(); assertTrue(logastext.contains("(" + AbstractProject.WorkspaceOfflineReason.all_suitable_nodes_are_offline.name() + ")")); - + } - + /** * Job is restricted. Label is on slave that can be started in cloud. Job is submitted to queue, which spawns an on demand slave. */ @Test - public void testRestrictedLabelOnSlaveYesQueue() throws Exception { + public void testRestrictedLabelOnSlaveYesQueue() throws Exception { FreeStyleProject proj = j.createFreeStyleProject("JENKINS-21394-yesqueue"); RequiresWorkspaceSCM requiresWorkspaceScm = new RequiresWorkspaceSCM(true); - proj.setScm(requiresWorkspaceScm); + proj.setScm(requiresWorkspaceScm); j.jenkins.setNumExecutors(0); - + /* * We have a cloud */ DummyCloudImpl2 c2 = new DummyCloudImpl2(j, 0); - c2.label = new LabelAtom("test-cloud-label"); + c2.label = new LabelAtom("test-cloud-label"); j.jenkins.clouds.add(c2); proj.setAssignedLabel(c2.label); - + SCMTrigger t = new SCMTrigger("@daily", true); t.start(proj, true); proj.addTrigger(t); t.new Runner().run(); - + Thread.sleep(1000); //The job should be in queue - assertEquals(1, j.jenkins.getQueue().getItems().length); + assertEquals(1, j.jenkins.getQueue().getItems().length); } @Issue("JENKINS-22750") @@ -783,11 +784,11 @@ public void testRestrictedLabelOnSlaveYesQueue() throws Exception { public void testMasterJobPutInQueue() throws Exception { FreeStyleProject proj = j.createFreeStyleProject("JENKINS-21394-yes-master-queue"); RequiresWorkspaceSCM requiresWorkspaceScm = new RequiresWorkspaceSCM(true); - proj.setAssignedLabel(null); - proj.setScm(requiresWorkspaceScm); - j.jenkins.setNumExecutors(1); + proj.setAssignedLabel(null); + proj.setScm(requiresWorkspaceScm); + j.jenkins.setNumExecutors(1); proj.setScm(requiresWorkspaceScm); - + //First build is not important j.buildAndAssertSuccess(proj); @@ -801,55 +802,56 @@ public void testMasterJobPutInQueue() throws Exception { } public static class TransientAction extends InvisibleAction{ - + } - + @TestExtension - public static class TransientActionFactoryImpl extends TransientProjectActionFactory{ + public static class TransientActionFactoryImpl extends TransientProjectActionFactory { @Override public Collection createFor(AbstractProject target) { List actions = new ArrayList<>(); - if(createAction) + if (createAction) actions.add(new TransientAction()); return actions; } - + } - - @TestExtension + + @TestExtension public static class RequiresWorkspaceSCM extends NullSCM { - + public boolean hasChange = false; - + public RequiresWorkspaceSCM() { } - + public RequiresWorkspaceSCM(boolean hasChange) { this.hasChange = hasChange; } - + @Override public boolean pollChanges(AbstractProject project, Launcher launcher, FilePath workspace, TaskListener listener) { return hasChange; } - + @Override - public boolean requiresWorkspaceForPolling(){ + public boolean requiresWorkspaceForPolling() { return true; } + @Override public SCMDescriptor getDescriptor() { return new SCMDescriptor(null) {}; } - + @Override protected PollingResult compareRemoteRevisionWith(AbstractProject project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline) { - if(!hasChange) { + if (!hasChange) { return PollingResult.NO_CHANGES; } return PollingResult.SIGNIFICANT; } } - + @TestExtension public static class AlwaysChangedSCM extends NullSCM { @@ -857,9 +859,9 @@ public static class AlwaysChangedSCM extends NullSCM { public boolean pollChanges(AbstractProject project, Launcher launcher, FilePath workspace, TaskListener listener) { return true; } - + @Override - public boolean requiresWorkspaceForPolling(){ + public boolean requiresWorkspaceForPolling() { return false; } @@ -867,31 +869,31 @@ public boolean requiresWorkspaceForPolling(){ protected PollingResult compareRemoteRevisionWith(AbstractProject project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline) { return PollingResult.SIGNIFICANT; } - + } - + @TestExtension - public static class WorkspaceBrowserImpl extends WorkspaceBrowser{ + public static class WorkspaceBrowserImpl extends WorkspaceBrowser { @Override public FilePath getWorkspace(Job job) { - if(getFilePath) + if (getFilePath) return new FilePath(new File("some_file_path")); return null; } - + } - - public static class SCMCheckoutStrategyImpl extends DefaultSCMCheckoutStrategyImpl implements Serializable{ - - public SCMCheckoutStrategyImpl(){ - + + public static class SCMCheckoutStrategyImpl extends DefaultSCMCheckoutStrategyImpl implements Serializable { + + public SCMCheckoutStrategyImpl() { + } } - - public static class JobPropertyImp extends JobProperty{ + + public static class JobPropertyImp extends JobProperty { @Override public Collection getSubTasks() { @@ -899,29 +901,29 @@ public Collection getSubTasks() { list.add(new SubTaskImpl()); return list; } - - + + } - + @TestExtension - public static class SubTaskContributorImpl extends SubTaskContributor{ + public static class SubTaskContributorImpl extends SubTaskContributor { @Override public Collection forProject(AbstractProject p) { ArrayList list = new ArrayList<>(); - if(createSubTask){ + if (createSubTask) { list.add(new SubTaskImpl2()); } return list; } } - + public static class SubTaskImpl2 extends SubTaskImpl{ - + } - - public static class SubTaskImpl implements SubTask{ - + + public static class SubTaskImpl implements SubTask { + public String projectName; @Override @@ -939,13 +941,13 @@ public String getDisplayName() { return "some task"; } - + } - + public class ActionImpl extends InvisibleAction{ - + } - + @TestExtension public static class DummyCloudImpl2 extends Cloud { private final transient JenkinsRule caller; @@ -966,8 +968,8 @@ public static class DummyCloudImpl2 extends Cloud { * Only reacts to provisioning for this label. */ public Label label; - - public DummyCloudImpl2() { + + public DummyCloudImpl2() { super("test"); this.delay = 0; this.caller = null; @@ -984,19 +986,19 @@ public Collection provision(Label label, int excess List r = new ArrayList<>(); //Always provision...even if there is no workload. - while(excessWorkload >= 0) { + while (excessWorkload >= 0) { System.out.println("Provisioning"); numProvisioned++; Future f = Computer.threadPoolForRemoting.submit(new ProjectTest.DummyCloudImpl2.Launcher(delay)); - r.add(new NodeProvisioner.PlannedNode(name+" #"+numProvisioned,f,1)); - excessWorkload-=1; + r.add(new NodeProvisioner.PlannedNode(name + " #" + numProvisioned, f, 1)); + excessWorkload -= 1; } return r; } @Override public boolean canProvision(Label label) { - //This cloud can ALWAYS provision + //This cloud can ALWAYS provision return true; /* return label==this.label; */ } @@ -1023,7 +1025,7 @@ public Node call() throws Exception { computer = slave.toComputer(); computer.connect(false).get(); synchronized (ProjectTest.DummyCloudImpl2.this) { - System.out.println(computer.getName()+" launch"+(computer.isOnline()?"ed successfully":" failed")); + System.out.println(computer.getName() + " launch" + (computer.isOnline() ? "ed successfully" : " failed")); System.out.println(computer.getLog()); } return slave; diff --git a/test/src/test/java/hudson/model/QueueRestartTest.java b/test/src/test/java/hudson/model/QueueRestartTest.java index b984d4bfa9bff..540e6754e6cf1 100644 --- a/test/src/test/java/hudson/model/QueueRestartTest.java +++ b/test/src/test/java/hudson/model/QueueRestartTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static org.junit.Assert.assertEquals; diff --git a/test/src/test/java/hudson/model/QueueTest.java b/test/src/test/java/hudson/model/QueueTest.java index c384cb1cb99bf..f49b4dd30ca79 100644 --- a/test/src/test/java/hudson/model/QueueTest.java +++ b/test/src/test/java/hudson/model/QueueTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static org.hamcrest.MatcherAssert.assertThat; @@ -132,7 +133,6 @@ import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.StringUtils; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.servlet.ServletHandler; @@ -174,21 +174,21 @@ public class QueueTest { r.jenkins.setNumExecutors(0); FreeStyleProject testProject = r.createFreeStyleProject("test"); - testProject.scheduleBuild(new UserIdCause()); + assertNotNull(testProject.scheduleBuild2(0, new UserIdCause())); q.save(); System.out.println(FileUtils.readFileToString(new File(r.jenkins.getRootDir(), "queue.xml"), StandardCharsets.UTF_8)); assertEquals(1, q.getItems().length); q.clear(); - assertEquals(0,q.getItems().length); + assertEquals(0, q.getItems().length); // load the contents back q.load(); assertEquals(1, q.getItems().length); // did it bind back to the same object? - assertSame(q.getItems()[0].task,testProject); + assertSame(q.getItems()[0].task, testProject); } /** @@ -222,19 +222,19 @@ public void recover_from_legacy_list() { r.jenkins.setNumExecutors(0); FreeStyleProject testProject = r.createFreeStyleProject("test"); - testProject.scheduleBuild(new UserIdCause()); + assertNotNull(testProject.scheduleBuild2(0, new UserIdCause())); q.save(); System.out.println(FileUtils.readFileToString(new File(r.jenkins.getRootDir(), "queue.xml"))); assertEquals(1, q.getItems().length); q.clear(); - assertEquals(0,q.getItems().length); + assertEquals(0, q.getItems().length); // delete the project before loading the queue back testProject.delete(); q.load(); - assertEquals(0,q.getItems().length); + assertEquals(0, q.getItems().length); // The counter state should be maintained. assertEquals(1, Queue.WaitingItem.getCurrentCounterValue()); @@ -254,7 +254,7 @@ private void resetQueueState() throws IOException { @Test public void queue_id_to_run_mapping() throws Exception { FreeStyleProject testProject = r.createFreeStyleProject("test"); - FreeStyleBuild build = r.assertBuildStatusSuccess(testProject.scheduleBuild2(0)); + FreeStyleBuild build = r.buildAndAssertSuccess(testProject); Assert.assertNotEquals(Run.QUEUE_ID_UNKNOWN, build.getQueueId()); } @@ -277,26 +277,29 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen }); Future b1 = p.scheduleBuild2(0); + assertNotNull(b1); seq.phase(1); // and make sure we have one build under way // get another going Future b2 = p.scheduleBuild2(0); + assertNotNull(b2); q.scheduleMaintenance().get(); Queue.Item[] items = q.getItems(); - assertEquals(1,items.length); - assertTrue("Got "+items[0], items[0] instanceof BlockedItem); + assertEquals(1, items.length); + assertTrue("Got " + items[0], items[0] instanceof BlockedItem); q.save(); } public static final class FileItemPersistenceTestServlet extends HttpServlet { private static final long serialVersionUID = 1L; + @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { resp.setContentType("text/html"); resp.getWriter().println( "
    " + - ""+ + "" + "
    " ); } @@ -305,7 +308,7 @@ public static final class FileItemPersistenceTestServlet extends HttpServlet { try { ServletFileUpload f = new ServletFileUpload(new DiskFileItemFactory()); List v = f.parseRequest(req); - assertEquals(1,v.size()); + assertEquals(1, v.size()); XStream2 xs = new XStream2(); System.out.println(xs.toXML(v.get(0))); } catch (FileUploadException e) { @@ -317,7 +320,7 @@ public static final class FileItemPersistenceTestServlet extends HttpServlet { @Test public void fileItemPersistence() throws Exception { // TODO: write a synchronous connector? byte[] testData = new byte[1024]; - for( int i=0; i build, Launcher launcher, BuildListen }); // Start one build to block others - assertTrue(project.scheduleBuild(new UserIdCause())); + project.scheduleBuild2(0, new UserIdCause()).waitForStart(); buildStarted.block(); // wait for the build to really start // Schedule a new build, and trigger it many ways while it sits in queue - Future fb = project.scheduleBuild2(0, new UserIdCause()); + final Future fb = project.scheduleBuild2(0, new UserIdCause()); assertNotNull(fb); - assertTrue(project.scheduleBuild(new SCMTriggerCause(""))); - assertTrue(project.scheduleBuild(new UserIdCause())); - assertTrue(project.scheduleBuild(new TimerTriggerCause())); - assertTrue(project.scheduleBuild(new RemoteCause("1.2.3.4", "test"))); - assertTrue(project.scheduleBuild(new RemoteCause("4.3.2.1", "test"))); - assertTrue(project.scheduleBuild(new SCMTriggerCause(""))); - assertTrue(project.scheduleBuild(new RemoteCause("1.2.3.4", "test"))); - assertTrue(project.scheduleBuild(new RemoteCause("1.2.3.4", "foo"))); - assertTrue(project.scheduleBuild(new SCMTriggerCause(""))); - assertTrue(project.scheduleBuild(new TimerTriggerCause())); + assertNotNull(project.scheduleBuild2(0, new SCMTriggerCause(""))); + assertNotNull(project.scheduleBuild2(0, new UserIdCause())); + assertNotNull(project.scheduleBuild2(0, new TimerTriggerCause())); + assertNotNull(project.scheduleBuild2(0, new RemoteCause("1.2.3.4", "test"))); + assertNotNull(project.scheduleBuild2(0, new RemoteCause("4.3.2.1", "test"))); + assertNotNull(project.scheduleBuild2(0, new SCMTriggerCause(""))); + assertNotNull(project.scheduleBuild2(0, new RemoteCause("1.2.3.4", "test"))); + assertNotNull(project.scheduleBuild2(0, new RemoteCause("1.2.3.4", "foo"))); + assertNotNull(project.scheduleBuild2(0, new SCMTriggerCause(""))); + assertNotNull(project.scheduleBuild2(0, new TimerTriggerCause())); // Wait for 2nd build to finish buildShouldComplete.signal(); @@ -399,14 +402,13 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen // View for build should group duplicates JenkinsRule.WebClient wc = r.createWebClient(); - String nl = System.getProperty("line.separator"); - String buildPage = wc.getPage(build, "").asText().replace(nl," "); + String buildPage = wc.getPage(build, "").asNormalizedText(); assertTrue("Build page should combine duplicates and show counts: " + buildPage, - buildPage.contains("Started by user SYSTEM (2 times) " - + "Started by an SCM change (3 times) " - + "Started by timer (2 times) " - + "Started by remote host 1.2.3.4 with note: test (2 times) " - + "Started by remote host 4.3.2.1 with note: test " + buildPage.contains("Started by user SYSTEM (2 times)\n" + + "Started by an SCM change (3 times)\n" + + "Started by timer (2 times)\n" + + "Started by remote host 1.2.3.4 with note: test (2 times)\n" + + "Started by remote host 4.3.2.1 with note: test\n" + "Started by remote host 1.2.3.4 with note: foo")); System.out.println(new XmlFile(new File(build.getRootDir(), "build.xml")).asString()); } @@ -415,14 +417,14 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen @Test public void flyweightTasks() throws Exception { MatrixProject m = r.jenkins.createProject(MatrixProject.class, "p"); m.addProperty(new ParametersDefinitionProperty( - new StringParameterDefinition("FOO","value") + new StringParameterDefinition("FOO", "value") )); if (Functions.isWindows()) { m.getBuildersList().add(new BatchFile("ping -n 3 127.0.0.1 >nul")); } else { m.getBuildersList().add(new Shell("sleep 3")); } - m.setAxes(new AxisList(new TextAxis("DoesntMatter", "aaa","bbb"))); + m.setAxes(new AxisList(new TextAxis("DoesntMatter", "aaa", "bbb"))); List> futures = new ArrayList<>(); @@ -532,7 +534,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen String tagName = queueItem.getDocumentElement().getTagName(); assertTrue(tagName.equals("blockedItem") || tagName.equals("buildableItem")); } - + @Issue("JENKINS-28926") @Test public void upstreamDownstreamCycle() throws Exception { @@ -568,16 +570,20 @@ public void upstreamDownstreamCycle() throws Exception { public static class TestFlyweightTask extends TestTask implements Queue.FlyweightTask { Executor exec; private final Label assignedLabel; + public TestFlyweightTask(AtomicInteger cnt, Label assignedLabel) { super(cnt); this.assignedLabel = assignedLabel; } + @Override protected void doRun() { exec = Executor.currentExecutor(); } + @Override public Label getAssignedLabel() { return assignedLabel; } + public Computer getOwner() { return exec == null ? null : exec.getOwner(); } @@ -595,6 +601,7 @@ public Computer getOwner() { r.waitUntilNoActivity(); assertEquals(1, cnt.get()); } + static class TestTask implements Queue.Task { private final AtomicInteger cnt; boolean isBlocked; @@ -611,22 +618,53 @@ static class TestTask implements Queue.Task { @Override public boolean equals(Object o) { return o instanceof TestTask && cnt == ((TestTask) o).cnt; } + @Override public int hashCode() { return cnt.hashCode(); } - @Override public CauseOfBlockage getCauseOfBlockage() {return isBlocked ? CauseOfBlockage.fromMessage(Messages._Queue_Unknown()) : null;} - @Override public String getName() {return "test";} - @Override public String getFullDisplayName() {return "Test";} + + @Override public CauseOfBlockage getCauseOfBlockage() { + return isBlocked ? CauseOfBlockage.fromMessage(Messages._Queue_Unknown()) : null; + } + + @Override public String getName() { + return "test"; + } + + @Override public String getFullDisplayName() { + return "Test"; + } + @Override public void checkAbortPermission() {} - @Override public boolean hasAbortPermission() {return true;} - @Override public String getUrl() {return "test/";} - @Override public String getDisplayName() {return "Test";} - @Override public ResourceList getResourceList() {return new ResourceList();} + + @Override public boolean hasAbortPermission() { + return true; + } + + @Override public String getUrl() { + return "test/"; + } + + @Override public String getDisplayName() { + return "Test"; + } + + @Override public ResourceList getResourceList() { + return new ResourceList(); + } + protected void doRun() {} + @Override public Executable createExecutable() { return new Executable() { - @Override public SubTask getParent() {return TestTask.this;} - @Override public long getEstimatedDuration() {return -1;} + @Override public SubTask getParent() { + return TestTask.this; + } + + @Override public long getEstimatedDuration() { + return -1; + } + @Override public void run() { doRun(); cnt.incrementAndGet(); @@ -648,7 +686,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen QueueTaskFuture v = p.scheduleBuild2(0); FreeStyleBuild b = v.waitForStart(); - assertEquals(1,b.getNumber()); + assertEquals(1, b.getNumber()); assertTrue(b.isBuilding()); assertSame(p, b.getProject()); @@ -670,10 +708,10 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen return true; } }); - r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + r.buildAndAssertSuccess(p); } - private static Authentication alice2 = new UsernamePasswordAuthenticationToken("alice","alice", Collections.emptySet()); + private static Authentication alice2 = new UsernamePasswordAuthenticationToken("alice", "alice", Collections.emptySet()); private static org.acegisecurity.Authentication alice = org.acegisecurity.Authentication.fromSpring(alice2); @@ -698,8 +736,8 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen } }); - final FreeStyleBuild b1 = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); - final FreeStyleBuild b2 = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + final FreeStyleBuild b1 = r.buildAndAssertSuccess(p); + final FreeStyleBuild b2 = r.buildAndAssertSuccess(p); // scheduling algorithm would prefer running the same job on the same node // kutzi: 'prefer' != 'enforce', therefore disabled this assertion: assertSame(b1.getBuiltOn(),b2.getBuiltOn()); @@ -707,17 +745,20 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen r.jenkins.setAuthorizationStrategy(new AliceCannotBuild(b1.getBuiltOnStr())); // now that we prohibit alice to do a build on the same node, the build should run elsewhere - for (int i=0; i<3; i++) { - FreeStyleBuild b3 = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + for (int i = 0; i < 3; i++) { + FreeStyleBuild b3 = r.buildAndAssertSuccess(p); assertNotSame(b3.getBuiltOnStr(), b1.getBuiltOnStr()); } } + private static class AliceCannotBuild extends GlobalMatrixAuthorizationStrategy { private final String blocked; + AliceCannotBuild(String blocked) { add(Jenkins.ADMINISTER, "anonymous"); this.blocked = blocked; } + @Override public ACL getACL(Node node) { if (node.getNodeName().equals(blocked)) { @@ -731,15 +772,15 @@ public ACL getACL(Node node) { } } - @Test public void pendingsConsistenceAfterErrorDuringMaintain() throws IOException, InterruptedException{ + @Test public void pendingsConsistenceAfterErrorDuringMaintain() throws IOException, InterruptedException { FreeStyleProject project1 = r.createFreeStyleProject(); FreeStyleProject project2 = r.createFreeStyleProject(); - TopLevelItemDescriptor descriptor = new TopLevelItemDescriptor(FreeStyleProject.class){ + TopLevelItemDescriptor descriptor = new TopLevelItemDescriptor(FreeStyleProject.class) { @Override public FreeStyleProject newInstance(ItemGroup parent, String name) { - return new FreeStyleProject(parent,name){ + return new FreeStyleProject(parent, name) { @Override - public Label getAssignedLabel(){ + public Label getAssignedLabel() { throw new IllegalArgumentException("Test exception"); //cause dead of executor } @@ -759,24 +800,24 @@ public void save(){ projectError.scheduleBuild2(0); Executor e = r.jenkins.toComputer().getExecutors().get(0); Thread.sleep(2000); - while(project2.getLastBuild()==null){ - if(!e.isAlive()){ + while (project2.getLastBuild() == null) { + if (!e.isAlive()) { break; // executor is dead due to exception } - if(e.isIdle()){ + if (e.isIdle()) { assertTrue("Node went to idle before project had" + project2.getDisplayName() + " been started", v.isDone()); } Thread.sleep(1000); } - if(project2.getLastBuild()!=null) + if (project2.getLastBuild() != null) return; Queue.getInstance().cancel(projectError); // cancel job which cause dead of executor - while(!e.isIdle()){ //executor should take project2 from queue + while (!e.isIdle()) { //executor should take project2 from queue Thread.sleep(1000); } //project2 should not be in pendings List items = Queue.getInstance().getPendingItems(); - for(Queue.BuildableItem item : items){ + for (Queue.BuildableItem item : items) { assertNotEquals("Project " + project2.getDisplayName() + " stuck in pendings", item.task.getName(), project2.getName()); } } @@ -832,32 +873,32 @@ public void run() { @Test public void testBlockBuildWhenUpstreamBuildingLock() throws Exception { final String prefix = "JENKINS-27871"; r.getInstance().setNumExecutors(4); - - final FreeStyleProject projectA = r.createFreeStyleProject(prefix+"A"); + + final FreeStyleProject projectA = r.createFreeStyleProject(prefix + "A"); projectA.getBuildersList().add(new SleepBuilder(5000)); - - final FreeStyleProject projectB = r.createFreeStyleProject(prefix+"B"); - projectB.getBuildersList().add(new SleepBuilder(10000)); + + final FreeStyleProject projectB = r.createFreeStyleProject(prefix + "B"); + projectB.getBuildersList().add(new SleepBuilder(10000)); projectB.setBlockBuildWhenUpstreamBuilding(true); - final FreeStyleProject projectC = r.createFreeStyleProject(prefix+"C"); + final FreeStyleProject projectC = r.createFreeStyleProject(prefix + "C"); projectC.getBuildersList().add(new SleepBuilder(10000)); projectC.setBlockBuildWhenUpstreamBuilding(true); - + projectA.getPublishersList().add(new BuildTrigger(Collections.singletonList(projectB), Result.SUCCESS)); projectB.getPublishersList().add(new BuildTrigger(Collections.singletonList(projectC), Result.SUCCESS)); - + final QueueTaskFuture taskA = projectA.scheduleBuild2(0, new TimerTriggerCause()); Thread.sleep(1000); final QueueTaskFuture taskB = projectB.scheduleBuild2(0, new TimerTriggerCause()); final QueueTaskFuture taskC = projectC.scheduleBuild2(0, new TimerTriggerCause()); - - final FreeStyleBuild buildA = taskA.get(60, TimeUnit.SECONDS); - final FreeStyleBuild buildB = taskB.get(60, TimeUnit.SECONDS); + + final FreeStyleBuild buildA = taskA.get(60, TimeUnit.SECONDS); + final FreeStyleBuild buildB = taskB.get(60, TimeUnit.SECONDS); final FreeStyleBuild buildC = taskC.get(60, TimeUnit.SECONDS); long buildBEndTime = buildB.getStartTimeInMillis() + buildB.getDuration(); assertTrue("Project B build should be finished before the build of project C starts. " + - "B finished at " + buildBEndTime + ", C started at " + buildC.getStartTimeInMillis(), + "B finished at " + buildBEndTime + ", C started at " + buildC.getStartTimeInMillis(), buildC.getStartTimeInMillis() >= buildBEndTime); } @@ -877,7 +918,7 @@ public void shouldRunFlyweightTaskOnProvisionedNodeWhenNodeRestricted() throws E dummyCloud.label = label; r.jenkins.clouds.add(dummyCloud); matrixProject.setAssignedLabel(label); - r.assertBuildStatusSuccess(matrixProject.scheduleBuild2(0)); + r.buildAndAssertSuccess(matrixProject); assertEquals("aws-linux-dummy", matrixProject.getBuilds().getLastBuild().getBuiltOn().getLabelString()); } @@ -1006,13 +1047,13 @@ public void queueApiOutputShouldBeFilteredByUserPermission() throws Exception { XmlPage p = webClient.goToXml("queue/api/xml"); //bob has permission on the project and will be able to see it in the queue together with information such as the URL and the name. - for (DomNode element: p.getFirstChild().getFirstChild().getChildNodes()){ + for (DomNode element : p.getFirstChild().getFirstChild().getChildNodes()) { if (element.getNodeName().equals("task")) { - for (DomNode child: ((DomElement) element).getChildNodes()) { + for (DomNode child : ((DomElement) element).getChildNodes()) { if (child.getNodeName().equals("name")) { - assertEquals("project", child.asText()); + assertEquals("project", child.asNormalizedText()); } else if (child.getNodeName().equals("url")) { - assertNotNull(child.asText()); + assertNotNull(child.asNormalizedText()); } } } @@ -1084,6 +1125,7 @@ public void load_queue_xml() { @TestExtension("load_queue_xml") public static final class QueueSaveSniffer extends SaveableListener { private static int count = 0; + @Override public void onChange(Saveable o, XmlFile file) { if (o instanceof Queue) { count++; @@ -1124,7 +1166,7 @@ private void checkCancelOperationUsingUrl(Function urlProvid assertThat(q.getItems().length, equalTo(0)); FreeStyleProject testProject = r.createFreeStyleProject("test"); - testProject.scheduleBuild(new UserIdCause()); + assertNotNull(testProject.scheduleBuild2(0, new UserIdCause())); Queue.Item[] items = q.getItems(); assertThat(items.length, equalTo(1)); @@ -1138,7 +1180,7 @@ private void checkCancelOperationUsingUrl(Function urlProvid .withRedirectEnabled(false) .withThrowExceptionOnFailingStatusCode(false); wc.login("user"); - if(legacyRedirect) { + if (legacyRedirect) { Page p = wc.getPage(request); // the legacy endpoint returns a redirection to the previously visited page, none in our case // (so force no redirect to avoid false positive error) @@ -1240,7 +1282,7 @@ private String buildAndExtractTooltipAttribute() throws Exception { DomElement buildQueue = page.getElementById("buildQueue"); DomNodeList anchors = buildQueue.getElementsByTagName("a"); HtmlAnchor anchorWithTooltip = (HtmlAnchor) anchors.stream() - .filter(a -> StringUtils.isNotEmpty(a.getAttribute("tooltip"))) + .filter(a -> a.getAttribute("tooltip") != null && !a.getAttribute("tooltip").isEmpty()) .findFirst().orElseThrow(IllegalStateException::new); String tooltip = anchorWithTooltip.getAttribute("tooltip"); @@ -1251,24 +1293,29 @@ public static class BrokenAffinityKeyProject extends Project getBuildClass() { return BrokenAffinityKeyBuild.class; } + @Override public TopLevelItemDescriptor getDescriptor() { return ExtensionList.lookupSingleton(DescriptorImpl.class); } + @TestExtension("brokenAffinityKey") public static class DescriptorImpl extends AbstractProjectDescriptor { @Override public TopLevelItem newInstance(ItemGroup parent, String name) { return new BrokenAffinityKeyProject(parent, name); } + @Override public String getDisplayName() { return "Broken Affinity Key Project"; @@ -1280,9 +1327,11 @@ public static class BrokenAffinityKeyBuild extends Build owner; // oops, should have been transient and used RunAction2 + BadAction(Run owner) { this.owner = owner; } diff --git a/test/src/test/java/hudson/model/RunMapTest.java b/test/src/test/java/hudson/model/RunMapTest.java index 3dd69e257a40b..979453dc110f0 100644 --- a/test/src/test/java/hudson/model/RunMapTest.java +++ b/test/src/test/java/hudson/model/RunMapTest.java @@ -18,19 +18,21 @@ import java.util.SortedMap; import java.util.Spliterator; import java.util.TreeMap; +import java.util.logging.Level; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.LoggerRule; import org.jvnet.hudson.test.RunLoadCounter; import org.jvnet.hudson.test.SleepBuilder; public class RunMapTest { @Rule public JenkinsRule r = new JenkinsRule(); - // TODO https://github.com/jenkinsci/jenkins/pull/2438: @Rule public LoggerRule logs = new LoggerRule(); + @Rule public LoggerRule logs = new LoggerRule(); /** * Makes sure that reloading the project while a build is in progress won't clobber that in-progress build. @@ -40,10 +42,10 @@ public class RunMapTest { FreeStyleProject p = r.createFreeStyleProject(); // want some completed build records - FreeStyleBuild b1 = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + FreeStyleBuild b1 = r.buildAndAssertSuccess(p); // now create a build that hangs until we signal the OneShotEvent - p.getBuildersList().add(new SleepBuilder(9999999)); + p.getBuildersList().add(new SleepBuilder(Long.MAX_VALUE)); FreeStyleBuild b2 = p.scheduleBuild2(0).waitForStart(); assertEquals(2, b2.number); @@ -65,9 +67,9 @@ public class RunMapTest { @Issue("JENKINS-27530") @Test public void reloadWhileBuildIsInQueue() throws Exception { - //logs.record(Queue.class, Level.FINE); + logs.record(Queue.class, Level.FINE); FreeStyleProject p = r.createFreeStyleProject("p"); - p.getBuildersList().add(new SleepBuilder(9999999)); + p.getBuildersList().add(new SleepBuilder(Long.MAX_VALUE)); r.jenkins.setNumExecutors(1); assertEquals(1, p.scheduleBuild2(0).waitForStart().number); p.scheduleBuild2(0); @@ -103,7 +105,7 @@ public class RunMapTest { @Issue("JENKINS-15533") @Test public void runtimeExceptionInUnmarshalling() throws Exception { FreeStyleProject p = r.createFreeStyleProject(); - FreeStyleBuild b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + FreeStyleBuild b = r.buildAndAssertSuccess(p); b.addAction(new BombAction()); b.save(); diff --git a/test/src/test/java/hudson/model/RunParameterDefinitionTest.java b/test/src/test/java/hudson/model/RunParameterDefinitionTest.java index 2b8e6fd8f5e67..f31f8cd66c573 100644 --- a/test/src/test/java/hudson/model/RunParameterDefinitionTest.java +++ b/test/src/test/java/hudson/model/RunParameterDefinitionTest.java @@ -63,9 +63,9 @@ public class RunParameterDefinitionTest { MockFolder dir = j.createFolder("dir"); MockFolder subdir = dir.createProject(MockFolder.class, "sub dir"); FreeStyleProject p = subdir.createProject(FreeStyleProject.class, "some project"); - p.scheduleBuild2(0).get(); - FreeStyleBuild build2 = p.scheduleBuild2(0).get(); - p.scheduleBuild2(0).get(); + j.buildAndAssertSuccess(p); + FreeStyleBuild build2 = j.buildAndAssertSuccess(p); + j.buildAndAssertSuccess(p); String id = build2.getExternalizableId(); assertEquals("dir/sub dir/some project#2", id); assertEquals(build2, Run.fromExternalizableId(id)); @@ -91,61 +91,61 @@ public class RunParameterDefinitionTest { public void testNULLFilter() throws Exception { FreeStyleProject project = j.createFreeStyleProject("project"); - FreeStyleBuild successfulBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild successfulBuild = j.buildAndAssertSuccess(project); project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.UNSTABLE))); - FreeStyleBuild unstableBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild unstableBuild = j.buildAndAssertStatus(Result.UNSTABLE, project); project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.FAILURE))); - FreeStyleBuild failedBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild failedBuild = j.buildAndAssertStatus(Result.FAILURE, project); project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.NOT_BUILT))); - FreeStyleBuild notBuiltBuild = project.scheduleBuild2(0).get(); - + FreeStyleBuild notBuiltBuild = j.buildAndAssertStatus(Result.NOT_BUILT, project); + project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.ABORTED))); - FreeStyleBuild abortedBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild abortedBuild = j.buildAndAssertStatus(Result.ABORTED, project); FreeStyleProject paramProject = j.createFreeStyleProject("paramProject"); - ParametersDefinitionProperty pdp = - new ParametersDefinitionProperty(new RunParameterDefinition("RUN", + ParametersDefinitionProperty pdp = + new ParametersDefinitionProperty(new RunParameterDefinition("RUN", project.getName(), "run description", null)); paramProject.addProperty(pdp); - FreeStyleBuild build = paramProject.scheduleBuild2(0).get(); + FreeStyleBuild build = j.buildAndAssertSuccess(paramProject); assertEquals(Integer.toString(project.getLastBuild().getNumber()), build.getEnvironment(new LogTaskListener(LOGGER, Level.INFO)).get("RUN_NUMBER")); } - + @Test public void testALLFilter() throws Exception { FreeStyleProject project = j.createFreeStyleProject("project"); - FreeStyleBuild successfulBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild successfulBuild = j.buildAndAssertSuccess(project); project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.UNSTABLE))); - FreeStyleBuild unstableBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild unstableBuild = j.buildAndAssertStatus(Result.UNSTABLE, project); project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.FAILURE))); - FreeStyleBuild failedBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild failedBuild = j.buildAndAssertStatus(Result.FAILURE, project); project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.NOT_BUILT))); - FreeStyleBuild notBuiltBuild = project.scheduleBuild2(0).get(); - + FreeStyleBuild notBuiltBuild = j.buildAndAssertStatus(Result.NOT_BUILT, project); + project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.ABORTED))); - FreeStyleBuild abortedBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild abortedBuild = j.buildAndAssertStatus(Result.ABORTED, project); FreeStyleProject paramProject = j.createFreeStyleProject("paramProject"); - ParametersDefinitionProperty pdp = - new ParametersDefinitionProperty(new RunParameterDefinition("RUN", + ParametersDefinitionProperty pdp = + new ParametersDefinitionProperty(new RunParameterDefinition("RUN", project.getName(), "run description", RunParameterFilter.ALL)); paramProject.addProperty(pdp); - FreeStyleBuild build = paramProject.scheduleBuild2(0).get(); + FreeStyleBuild build = j.buildAndAssertSuccess(paramProject); assertEquals(Integer.toString(project.getLastBuild().getNumber()), build.getEnvironment(new LogTaskListener(LOGGER, Level.INFO)).get("RUN_NUMBER")); } @@ -154,102 +154,102 @@ public void testALLFilter() throws Exception { public void testCOMPLETEDFilter() throws Exception { FreeStyleProject project = j.createFreeStyleProject("project"); - FreeStyleBuild successfulBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild successfulBuild = j.buildAndAssertSuccess(project); project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.UNSTABLE))); - FreeStyleBuild unstableBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild unstableBuild = j.buildAndAssertStatus(Result.UNSTABLE, project); project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.FAILURE))); - FreeStyleBuild failedBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild failedBuild = j.buildAndAssertStatus(Result.FAILURE, project); project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.NOT_BUILT))); - FreeStyleBuild notBuiltBuild = project.scheduleBuild2(0).get(); - + FreeStyleBuild notBuiltBuild = j.buildAndAssertStatus(Result.NOT_BUILT, project); + project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.ABORTED))); - FreeStyleBuild abortedBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild abortedBuild = j.buildAndAssertStatus(Result.ABORTED, project); FreeStyleProject paramProject = j.createFreeStyleProject("paramProject"); - ParametersDefinitionProperty pdp = - new ParametersDefinitionProperty(new RunParameterDefinition("RUN", + ParametersDefinitionProperty pdp = + new ParametersDefinitionProperty(new RunParameterDefinition("RUN", project.getName(), "run description", RunParameterFilter.COMPLETED)); paramProject.addProperty(pdp); - FreeStyleBuild build = paramProject.scheduleBuild2(0).get(); + FreeStyleBuild build = j.buildAndAssertSuccess(paramProject); assertEquals(Integer.toString(abortedBuild.getNumber()), build.getEnvironment(new LogTaskListener(LOGGER, Level.INFO)).get("RUN_NUMBER")); } - + @Test public void testSUCCESSFULFilter() throws Exception { FreeStyleProject project = j.createFreeStyleProject("project"); - FreeStyleBuild successfulBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild successfulBuild = j.buildAndAssertSuccess(project); project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.UNSTABLE))); - FreeStyleBuild unstableBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild unstableBuild = j.buildAndAssertStatus(Result.UNSTABLE, project); project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.FAILURE))); - FreeStyleBuild failedBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild failedBuild = j.buildAndAssertStatus(Result.FAILURE, project); project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.NOT_BUILT))); - FreeStyleBuild notBuiltBuild = project.scheduleBuild2(0).get(); - + FreeStyleBuild notBuiltBuild = j.buildAndAssertStatus(Result.NOT_BUILT, project); + project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.ABORTED))); - FreeStyleBuild abortedBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild abortedBuild = j.buildAndAssertStatus(Result.ABORTED, project); FreeStyleProject paramProject = j.createFreeStyleProject("paramProject"); - ParametersDefinitionProperty pdp = - new ParametersDefinitionProperty(new RunParameterDefinition("RUN", + ParametersDefinitionProperty pdp = + new ParametersDefinitionProperty(new RunParameterDefinition("RUN", project.getName(), "run description", RunParameterFilter.SUCCESSFUL)); paramProject.addProperty(pdp); - FreeStyleBuild build = paramProject.scheduleBuild2(0).get(); + FreeStyleBuild build = j.buildAndAssertSuccess(paramProject); assertEquals(Integer.toString(unstableBuild.getNumber()), build.getEnvironment(new LogTaskListener(LOGGER, Level.INFO)).get("RUN_NUMBER")); } - - + + @Test public void testSTABLEFilter() throws Exception { FreeStyleProject project = j.createFreeStyleProject("project"); - FreeStyleBuild successfulBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild successfulBuild = j.buildAndAssertSuccess(project); project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.UNSTABLE))); - FreeStyleBuild unstableBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild unstableBuild = j.buildAndAssertStatus(Result.UNSTABLE, project); project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.FAILURE))); - FreeStyleBuild failedBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild failedBuild = j.buildAndAssertStatus(Result.FAILURE, project); project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.NOT_BUILT))); - FreeStyleBuild notBuiltBuild = project.scheduleBuild2(0).get(); - + FreeStyleBuild notBuiltBuild = j.buildAndAssertStatus(Result.NOT_BUILT, project); + project.getPublishersList().replaceBy(Collections.singleton(new ResultPublisher(Result.ABORTED))); - FreeStyleBuild abortedBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild abortedBuild = j.buildAndAssertStatus(Result.ABORTED, project); FreeStyleProject paramProject = j.createFreeStyleProject("paramProject"); - ParametersDefinitionProperty pdp = - new ParametersDefinitionProperty(new RunParameterDefinition("RUN", + ParametersDefinitionProperty pdp = + new ParametersDefinitionProperty(new RunParameterDefinition("RUN", project.getName(), "run description", RunParameterFilter.STABLE)); paramProject.addProperty(pdp); - FreeStyleBuild build = paramProject.scheduleBuild2(0).get(); + FreeStyleBuild build = j.buildAndAssertSuccess(paramProject); assertEquals(Integer.toString(successfulBuild.getNumber()), build.getEnvironment(new LogTaskListener(LOGGER, Level.INFO)).get("RUN_NUMBER")); } - - + + @Test public void testLoadEnvironmentVariablesWhenRunParameterJobHasBeenDeleted() throws Exception { FreeStyleProject project = j.createFreeStyleProject("project"); - FreeStyleBuild successfulBuild = project.scheduleBuild2(0).get(); + FreeStyleBuild successfulBuild = j.buildAndAssertSuccess(project); FreeStyleProject paramProject = j.createFreeStyleProject("paramProject"); ParametersDefinitionProperty pdp = @@ -259,7 +259,7 @@ public void testLoadEnvironmentVariablesWhenRunParameterJobHasBeenDeleted() thro RunParameterFilter.ALL)); paramProject.addProperty(pdp); - FreeStyleBuild build = paramProject.scheduleBuild2(0).get(); + FreeStyleBuild build = j.buildAndAssertSuccess(paramProject); assertEquals(Integer.toString(project.getLastBuild().getNumber()), build.getEnvironment(new LogTaskListener(LOGGER, Level.INFO)).get("RUN_NUMBER")); diff --git a/test/src/test/java/hudson/model/RunTest.java b/test/src/test/java/hudson/model/RunTest.java index 24159b701fc35..d828c73b2964e 100644 --- a/test/src/test/java/hudson/model/RunTest.java +++ b/test/src/test/java/hudson/model/RunTest.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Jorg Heymans - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static org.hamcrest.CoreMatchers.containsString; @@ -75,16 +76,18 @@ public class RunTest { @Override public String getDisplayName() { return "Test"; } + @Override public String getIconFileName() { return null; } + @Override public String getUrlName() { return null; } }); } }); - j.assertBuildStatusSuccess(j.createFreeStyleProject("stuff").scheduleBuild2(0)); + j.buildAndAssertSuccess(j.createFreeStyleProject("stuff")); j.createWebClient().assertFails("job/stuff/1/nonexistent", HttpURLConnection.HTTP_NOT_FOUND); } @@ -110,6 +113,7 @@ public class RunTest { b.delete(); assertTrue(Mgr.deleted.get()); } + @Issue("SECURITY-1902") @Test public void preventXssInBadgeTooltip() throws Exception { j.jenkins.setQuietPeriod(0); @@ -217,22 +221,29 @@ public FullNameChangingProject newInstance(ItemGroup parent, String name) { } } } - + public static final class Mgr extends ArtifactManager { static final AtomicBoolean deleted = new AtomicBoolean(); + @Override public boolean delete() { return !deleted.getAndSet(true); } + @Override public void onLoad(Run build) {} + @Override public void archive(FilePath workspace, Launcher launcher, BuildListener listener, Map artifacts) {} + @Override public VirtualFile root() { return VirtualFile.forFile(Jenkins.get().getRootDir()); // irrelevant } + public static final class Factory extends ArtifactManagerFactory { @DataBoundConstructor public Factory() {} + @Override public ArtifactManager managerFor(Run build) { return new Mgr(); } + @TestExtension("deleteArtifactsCustom") public static final class DescriptorImpl extends ArtifactManagerFactoryDescriptor {} } } diff --git a/test/src/test/java/hudson/model/SimpleJobTest.java b/test/src/test/java/hudson/model/SimpleJobTest.java index e623b61110477..6512c5116fe3a 100644 --- a/test/src/test/java/hudson/model/SimpleJobTest.java +++ b/test/src/test/java/hudson/model/SimpleJobTest.java @@ -18,101 +18,101 @@ public class SimpleJobTest { @Rule public JenkinsRule rule = new JenkinsRule(); - + @Test public void testGetEstimatedDuration() throws IOException { - + final SortedMap runs = new TreeMap<>(); - + Job project = createMockProject(runs); - + TestBuild previousPreviousBuild = new TestBuild(project, Result.SUCCESS, 20, null); runs.put(3, previousPreviousBuild); - + TestBuild previousBuild = new TestBuild(project, Result.SUCCESS, 15, previousPreviousBuild); runs.put(2, previousBuild); - + TestBuild lastBuild = new TestBuild(project, Result.SUCCESS, 42, previousBuild); runs.put(1, lastBuild); // without assuming to know too much about the internal calculation // we can only assume that the result is between the maximum and the minimum - assertTrue("Expected < 42, but was "+project.getEstimatedDuration(), project.getEstimatedDuration() < 42); - assertTrue("Expected > 15, but was "+project.getEstimatedDuration(), project.getEstimatedDuration() > 15); + assertTrue("Expected < 42, but was " + project.getEstimatedDuration(), project.getEstimatedDuration() < 42); + assertTrue("Expected > 15, but was " + project.getEstimatedDuration(), project.getEstimatedDuration() > 15); } - + @Test public void testGetEstimatedDurationWithOneRun() throws IOException { - + final SortedMap runs = new TreeMap<>(); - + Job project = createMockProject(runs); - + TestBuild lastBuild = new TestBuild(project, Result.SUCCESS, 42, null); runs.put(1, lastBuild); assertEquals(42, project.getEstimatedDuration()); } - + @Test public void testGetEstimatedDurationWithFailedRun() throws IOException { - + final SortedMap runs = new TreeMap<>(); - + Job project = createMockProject(runs); - + TestBuild lastBuild = new TestBuild(project, Result.FAILURE, 42, null); runs.put(1, lastBuild); assertEquals(42, project.getEstimatedDuration()); } - + @Test public void testGetEstimatedDurationWithNoRuns() { - + final SortedMap runs = new TreeMap<>(); - + Job project = createMockProject(runs); - + assertEquals(-1, project.getEstimatedDuration()); } - + @Test public void testGetEstimatedDurationIfPrevious3BuildsFailed() throws IOException { - + final SortedMap runs = new TreeMap<>(); - + Job project = createMockProject(runs); - + TestBuild prev5Build = new TestBuild(project, Result.UNSTABLE, 1, null); runs.put(6, prev5Build); - + TestBuild prev4Build = new TestBuild(project, Result.SUCCESS, 1, prev5Build); runs.put(5, prev4Build); - + TestBuild prev3Build = new TestBuild(project, Result.SUCCESS, 1, prev4Build); runs.put(4, prev3Build); - + TestBuild previous2Build = new TestBuild(project, Result.FAILURE, 50, prev3Build); runs.put(3, previous2Build); - + TestBuild previousBuild = new TestBuild(project, Result.FAILURE, 50, previous2Build); runs.put(2, previousBuild); - + TestBuild lastBuild = new TestBuild(project, Result.FAILURE, 50, previousBuild); runs.put(1, lastBuild); // failed builds must not be used, if there are successfulBuilds available. assertEquals(1, project.getEstimatedDuration()); } - + @Test public void testGetEstimatedDurationIfNoSuccessfulBuildTakeDurationOfFailedBuild() throws IOException { - + final SortedMap runs = new TreeMap<>(); - + Job project = createMockProject(runs); - + TestBuild lastBuild = new TestBuild(project, Result.FAILURE, 50, null); runs.put(1, lastBuild); @@ -125,29 +125,29 @@ private Job createMockProject(final SortedMap runs) { @SuppressWarnings("unchecked") private static class TestBuild extends Run { - + TestBuild(Job project, Result result, long duration, TestBuild previousBuild) throws IOException { super(project); this.result = result; this.duration = duration; this.previousBuild = previousBuild; } - + @Override public int compareTo(Run o) { return 0; } - + @Override public Result getResult() { return result; } - + @Override public boolean isBuilding() { return false; } - + } private class TestJob extends Job implements TopLevelItem { diff --git a/test/src/test/java/hudson/model/SlaveTest.java b/test/src/test/java/hudson/model/SlaveTest.java index 66a26ea9c0d6f..5f4216790723b 100644 --- a/test/src/test/java/hudson/model/SlaveTest.java +++ b/test/src/test/java/hudson/model/SlaveTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static org.hamcrest.MatcherAssert.assertThat; diff --git a/test/src/test/java/hudson/model/UpdateCenter2Test.java b/test/src/test/java/hudson/model/UpdateCenter2Test.java index 128e7448de133..c292906601616 100644 --- a/test/src/test/java/hudson/model/UpdateCenter2Test.java +++ b/test/src/test/java/hudson/model/UpdateCenter2Test.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static org.junit.Assert.assertEquals; diff --git a/test/src/test/java/hudson/model/UpdateCenterConnectionStatusTest.java b/test/src/test/java/hudson/model/UpdateCenterConnectionStatusTest.java index 56685a2ca986c..3a2cb6a0367a3 100644 --- a/test/src/test/java/hudson/model/UpdateCenterConnectionStatusTest.java +++ b/test/src/test/java/hudson/model/UpdateCenterConnectionStatusTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static hudson.model.UpdateCenter.ConnectionStatus; diff --git a/test/src/test/java/hudson/model/UpdateCenterCustomTest.java b/test/src/test/java/hudson/model/UpdateCenterCustomTest.java index 69d95d7f9469f..dc37e2b3c875d 100644 --- a/test/src/test/java/hudson/model/UpdateCenterCustomTest.java +++ b/test/src/test/java/hudson/model/UpdateCenterCustomTest.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2016 CloudBees, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; @@ -36,10 +37,10 @@ * Tests of the custom {@link UpdateCenter} implementation. */ public class UpdateCenterCustomTest { - + @Rule public final JenkinsRule j = new CustomUpdateCenterRule(CustomUpdateCenter.class); - + @Test public void shouldStartupWithCustomUpdateCenter() { UpdateCenter uc = j.jenkins.getUpdateCenter(); @@ -50,8 +51,8 @@ public void shouldStartupWithCustomUpdateCenter() { private static final class CustomUpdateCenterRule extends JenkinsRule { private final String updateCenterClassName; private String _oldValue = null; - - private static final String PROPERTY_NAME = UpdateCenter.class.getName()+".className"; + + private static final String PROPERTY_NAME = UpdateCenter.class.getName() + ".className"; CustomUpdateCenterRule(Class ucClass) { this.updateCenterClassName = ucClass.getName(); @@ -75,15 +76,15 @@ public String getUpdateCenterClassName() { return updateCenterClassName; } } - + public static final class CustomUpdateCenter extends UpdateCenter { public CustomUpdateCenter() { } - + public CustomUpdateCenter(UpdateCenterConfiguration config) { super(config); } - + } } diff --git a/test/src/test/java/hudson/model/UpdateCenterPluginInstallTest.java b/test/src/test/java/hudson/model/UpdateCenterPluginInstallTest.java index 00d3a21b570c7..d9450e0ab9c53 100644 --- a/test/src/test/java/hudson/model/UpdateCenterPluginInstallTest.java +++ b/test/src/test/java/hudson/model/UpdateCenterPluginInstallTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static org.junit.Assume.assumeFalse; diff --git a/test/src/test/java/hudson/model/UpdateCenterTest.java b/test/src/test/java/hudson/model/UpdateCenterTest.java index 630522f62d5a0..998e9badd67eb 100644 --- a/test/src/test/java/hudson/model/UpdateCenterTest.java +++ b/test/src/test/java/hudson/model/UpdateCenterTest.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static java.util.Objects.requireNonNull; @@ -42,7 +43,7 @@ /** * Quick test for {@link UpdateCenter}. - * + * * @author Kohsuke Kawaguchi */ public class UpdateCenterTest { @@ -55,6 +56,7 @@ public class UpdateCenterTest { assumeNoException("Might be no Internet connectivity, or might start failing due to expiring certificate through no fault of code changes", x); } } + private void doData(String location) throws Exception { URL url = new URL(location); String jsonp = DownloadService.loadJSON(url); diff --git a/test/src/test/java/hudson/model/UpdateSiteTest.java b/test/src/test/java/hudson/model/UpdateSiteTest.java index 2928162f0e572..d95b97dce6cb5 100644 --- a/test/src/test/java/hudson/model/UpdateSiteTest.java +++ b/test/src/test/java/hudson/model/UpdateSiteTest.java @@ -39,6 +39,7 @@ import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -75,7 +76,7 @@ private String getResource(String resourceName) throws IOException { try { URL url = UpdateSiteTest.class.getResource(resourceName); return url != null ? FileUtils.readFileToString(new File(url.toURI())) : null; - } catch(URISyntaxException e) { + } catch (URISyntaxException e) { return null; } } @@ -99,7 +100,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques baseRequest.setHandled(true); response.setContentType("text/plain; charset=utf-8"); response.setStatus(HttpServletResponse.SC_OK); - response.getOutputStream().write(responseBody.getBytes()); + response.getOutputStream().write(responseBody.getBytes(StandardCharsets.UTF_8)); } } }); @@ -111,7 +112,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques public void shutdownWebserver() throws Exception { server.stop(); } - + @Test public void relativeURLs() throws Exception { URL url = new URL(baseUrl, "/plugins/htmlpublisher-update-center.json"); UpdateSite site = new UpdateSite(UpdateCenter.ID_DEFAULT, url.toString()); @@ -139,7 +140,7 @@ public void shutdownWebserver() throws Exception { UpdateSite site = getUpdateSite("/plugins/htmlpublisher-update-center.json"); UpdateSite alternativeSite = getUpdateSite("/plugins/alternative-update-center.json", "alternative"); overrideUpdateSite(site, alternativeSite); - // sites use different Wiki URL for dummy -> use URL from manifest + // sites use different Wiki URL for dummy -> use URL from manifest PluginWrapper wrapper = buildPluginWrapper("dummy", "https://wiki.jenkins.io/display/JENKINS/dummy"); assertEquals("https://wiki.jenkins.io/display/JENKINS/dummy", wrapper.getUrl()); // sites use the same Wiki URL for HTML Publisher -> use it @@ -205,11 +206,11 @@ public void isPluginUpdateCompatible() throws Exception { @Issue("JENKINS-31448") @Test public void isLegacyDefault() { - assertFalse("isLegacyDefault should be false with null id",new UpdateSite(null,"url").isLegacyDefault()); - assertFalse("isLegacyDefault should be false when id is not default and url is http://hudson-ci.org/",new UpdateSite("dummy","http://hudson-ci.org/").isLegacyDefault()); - assertTrue("isLegacyDefault should be true when id is default and url is http://hudson-ci.org/",new UpdateSite(UpdateCenter.PREDEFINED_UPDATE_SITE_ID,"http://hudson-ci.org/").isLegacyDefault()); - assertTrue("isLegacyDefault should be true when url is http://updates.hudson-labs.org/",new UpdateSite("dummy","http://updates.hudson-labs.org/").isLegacyDefault()); - assertFalse("isLegacyDefault should be false with null url",new UpdateSite(null,null).isLegacyDefault()); + assertFalse("isLegacyDefault should be false with null id", new UpdateSite(null, "url").isLegacyDefault()); + assertFalse("isLegacyDefault should be false when id is not default and url is http://hudson-ci.org/", new UpdateSite("dummy", "http://hudson-ci.org/").isLegacyDefault()); + assertTrue("isLegacyDefault should be true when id is default and url is http://hudson-ci.org/", new UpdateSite(UpdateCenter.PREDEFINED_UPDATE_SITE_ID, "http://hudson-ci.org/").isLegacyDefault()); + assertTrue("isLegacyDefault should be true when url is http://updates.hudson-labs.org/", new UpdateSite("dummy", "http://updates.hudson-labs.org/").isLegacyDefault()); + assertFalse("isLegacyDefault should be false with null url", new UpdateSite(null, null).isLegacyDefault()); } @Test public void getAvailables() throws Exception { diff --git a/test/src/test/java/hudson/model/UsageStatisticsTest.java b/test/src/test/java/hudson/model/UsageStatisticsTest.java index fd8851fe727b0..7ff80714065f3 100644 --- a/test/src/test/java/hudson/model/UsageStatisticsTest.java +++ b/test/src/test/java/hudson/model/UsageStatisticsTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static org.hamcrest.MatcherAssert.assertThat; @@ -107,11 +108,11 @@ public void roundtrip() throws Exception { String data = new UsageStatistics(publicKey).getStatData(); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - RSAPrivateKey priv = (RSAPrivateKey)keyFactory.generatePrivate(new PKCS8EncodedKeySpec(Util.fromHexString(privateKey))); + RSAPrivateKey priv = (RSAPrivateKey) keyFactory.generatePrivate(new PKCS8EncodedKeySpec(Util.fromHexString(privateKey))); byte[] cipherText = Base64.getDecoder().decode(data.getBytes(StandardCharsets.UTF_8)); InputStreamReader r = new InputStreamReader(new GZIPInputStream( - new CombinedCipherInputStream(new ByteArrayInputStream(cipherText),priv,"AES")), StandardCharsets.UTF_8); + new CombinedCipherInputStream(new ByteArrayInputStream(cipherText), priv, "AES")), StandardCharsets.UTF_8); JSONObject o = JSONObject.fromObject(IOUtils.toString(r)); Jenkins jenkins = j.jenkins; // A bit intrusive with UsageStatistics internals, but done to prevent undetected changes @@ -131,7 +132,7 @@ public void roundtrip() throws Exception { keys.add("name"); keys.add("version"); Set reported = new TreeSet<>(); - for (JSONObject plugin: plugins) { + for (JSONObject plugin : plugins) { assertThat(plugin.keySet(), is(keys)); assertThat(plugin.get("name"), instanceOf(String.class)); assertThat(plugin.get("version"), instanceOf(String.class)); diff --git a/test/src/test/java/hudson/model/UserIdMigratorTest.java b/test/src/test/java/hudson/model/UserIdMigratorTest.java index 90fffb7ee04fa..81af07c3d44dc 100644 --- a/test/src/test/java/hudson/model/UserIdMigratorTest.java +++ b/test/src/test/java/hudson/model/UserIdMigratorTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static org.hamcrest.CoreMatchers.is; diff --git a/test/src/test/java/hudson/model/UserRestartTest.java b/test/src/test/java/hudson/model/UserRestartTest.java index 5b56e3a0abd5c..dfb2323931f70 100644 --- a/test/src/test/java/hudson/model/UserRestartTest.java +++ b/test/src/test/java/hudson/model/UserRestartTest.java @@ -84,8 +84,10 @@ public void badSerialization() throws Throwable { assertEquals(User.get("pqhacker"), u); }); } + static class BadProperty extends JobProperty { final User user; + BadProperty(User user) { this.user = user; } diff --git a/test/src/test/java/hudson/model/UserTest.java b/test/src/test/java/hudson/model/UserTest.java index 390165df9e6bf..a3e35cf2f6c1e 100644 --- a/test/src/test/java/hudson/model/UserTest.java +++ b/test/src/test/java/hudson/model/UserTest.java @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static org.hamcrest.MatcherAssert.assertThat; @@ -54,6 +55,8 @@ import hudson.security.GroupDetails; import hudson.security.HudsonPrivateSecurityRealm; import hudson.security.Permission; +import hudson.security.SecurityRealm; +import hudson.security.UserMayOrMayNotExistException; import hudson.security.UserMayOrMayNotExistException2; import hudson.tasks.MailAddressResolver; import java.io.File; @@ -195,7 +198,7 @@ public void testGetUser() throws Exception { User user3 = User.get("John Smith"); user3.setFullName("Alice Smith"); assertEquals("What was this asserting exactly?", "John Smith", user3.getId()); - User user4 = User.get("Marie",false, Collections.EMPTY_MAP); + User user4 = User.get("Marie", false, Collections.EMPTY_MAP); assertNull("User should not be created because Marie does not exists.", user4); } } @@ -233,10 +236,12 @@ public void caseSensitivityEmail() { private static class IdStrategySpecifyingSecurityRealm extends HudsonPrivateSecurityRealm { private final IdStrategy idStrategy; + IdStrategySpecifyingSecurityRealm(IdStrategy idStrategy) { super(true, false, null); this.idStrategy = idStrategy; } + @Override public IdStrategy getUserIdStrategy() { return idStrategy; @@ -378,8 +383,8 @@ public void testDelete() throws Exception { j.jenkins.reload(); { boolean contained = false; - for(User u: User.getAll()){ - if(u.getId().equals("John Smith")){ + for (User u : User.getAll()) { + if (u.getId().equals("John Smith")) { contained = true; break; } @@ -442,7 +447,7 @@ public void testDoDoDelete() throws Exception { fail("User should not have permission to delete another user."); } catch(Exception e){ - if(!(e.getClass().isAssignableFrom(AccessDeniedException3.class))){ + if (!(e.getClass().isAssignableFrom(AccessDeniedException3.class))){ fail("AccessDeniedException should be thrown."); } } @@ -469,7 +474,7 @@ public void testHasPermission() throws IOException { j.jenkins.setCrumbIssuer(null); HudsonPrivateSecurityRealm realm = new HudsonPrivateSecurityRealm(false); j.jenkins.setSecurityRealm(realm); - User user = realm.createAccount("John Smith","password"); + User user = realm.createAccount("John Smith", "password"); User user2 = realm.createAccount("John Smith2", "password"); SecurityContextHolder.getContext().setAuthentication(user.impersonate2()); assertFalse("Current user should not have permission read.", user2.hasPermission(Permission.READ)); @@ -488,8 +493,8 @@ public void testCanDelete() throws IOException { j.jenkins.setCrumbIssuer(null); HudsonPrivateSecurityRealm realm = new HudsonPrivateSecurityRealm(false); j.jenkins.setSecurityRealm(realm); - User user = realm.createAccount("John Smith","password"); - User user2 = realm.createAccount("John Smith2","password"); + User user = realm.createAccount("John Smith", "password"); + User user2 = realm.createAccount("John Smith2", "password"); user2.save(); SecurityContextHolder.getContext().setAuthentication(user.impersonate2()); @@ -510,7 +515,7 @@ public void testCanDelete() throws IOException { // @Issue("SECURITY-180") public void security180() throws Exception { ApiTokenTestHelper.enableLegacyBehavior(); - + final GlobalMatrixAuthorizationStrategy auth = new GlobalMatrixAuthorizationStrategy(); j.jenkins.setAuthorizationStrategy(auth); j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); @@ -540,7 +545,7 @@ public void security180() throws Exception { @Issue("SECURITY-243") @Test - public void resolveByIdThenName() throws Exception{ + public void resolveByIdThenName() throws Exception { j.jenkins.setSecurityRealm(new HudsonPrivateSecurityRealm(true, false, null)); User u1 = User.get("user1"); @@ -620,10 +625,12 @@ public UserDetails loadUserByUsername2(String username) throws UsernameNotFoundE return new org.springframework.security.core.userdetails.User(canonicalName, "", true, true, true, true, Collections.singleton(AUTHENTICATED_AUTHORITY2)); } } + @Override protected UserDetails authenticate2(String username, String password) throws AuthenticationException { return loadUserByUsername2(username); // irrelevant } + @Override public GroupDetails loadGroupByGroupname2(String groupname, boolean fetchMembers) throws UsernameNotFoundException { throw new UsernameNotFoundException(groupname); // irrelevant @@ -770,4 +777,26 @@ public WebResponse getResponse(WebRequest request) throws IOException { assertThat(failingResources, empty()); } + @Test + public void legacyCallerGetsUserMayOrMayNotExistException() { + final SecurityRealm realm = new NonEnumeratingAcegiSecurityRealm(); + assertThrows(UserMayOrMayNotExistException.class, () -> realm.loadUserByUsername("unknown")); + + final SecurityRealm realm2 = new NonEnumeratingSpringSecurityRealm(); + assertThrows(UserMayOrMayNotExistException.class, () -> realm2.loadUserByUsername("unknown")); + } + + private static class NonEnumeratingAcegiSecurityRealm extends AbstractPasswordBasedSecurityRealm { + @Override + public org.acegisecurity.userdetails.UserDetails loadUserByUsername(String username) throws org.acegisecurity.userdetails.UsernameNotFoundException { + throw new UserMayOrMayNotExistException(username + " not found"); + } + } + + private static class NonEnumeratingSpringSecurityRealm extends AbstractPasswordBasedSecurityRealm { + @Override + public UserDetails loadUserByUsername2(String username) throws UsernameNotFoundException { + throw new UserMayOrMayNotExistException2(username + " not found"); + } + } } diff --git a/test/src/test/java/hudson/model/ViewDescriptorTest.java b/test/src/test/java/hudson/model/ViewDescriptorTest.java index 34d8f29e4f039..15c36e953c98f 100644 --- a/test/src/test/java/hudson/model/ViewDescriptorTest.java +++ b/test/src/test/java/hudson/model/ViewDescriptorTest.java @@ -116,7 +116,7 @@ public void invisiblePropertiesOnViewShoudBePersisted() throws Exception { //THEN the invisible property is not displayed on page assertFalse("CustomInvisibleProperty should not be displayed on the View edition page UI.", - editViewPage.asText().contains("CustomInvisibleProperty")); + editViewPage.asNormalizedText().contains("CustomInvisibleProperty")); HtmlForm editViewForm = editViewPage.getFormByName("viewConfig"); @@ -125,7 +125,7 @@ public void invisiblePropertiesOnViewShoudBePersisted() throws Exception { //Check that the description is updated on view Awaitility.waitAtMost(10, TimeUnit.SECONDS).until(() -> webClient.getPage(myListView) - .asText() + .asNormalizedText() .contains("This list view is awesome !")); diff --git a/test/src/test/java/hudson/model/ViewJobTest.java b/test/src/test/java/hudson/model/ViewJobTest.java index 358a9dd120bcd..024c2c134dbab 100644 --- a/test/src/test/java/hudson/model/ViewJobTest.java +++ b/test/src/test/java/hudson/model/ViewJobTest.java @@ -50,7 +50,7 @@ public class ViewJobTest { } @SuppressWarnings({"rawtypes", "deprecation"}) - public static final class J extends ViewJob implements TopLevelItem { + public static final class J extends ViewJob implements TopLevelItem { public J(ItemGroup parent, String name) { super(parent, name); @@ -85,7 +85,7 @@ R nue() throws IOException { } - public static final class R extends Run { + public static final class R extends Run { public R(J j) throws IOException { super(j); diff --git a/test/src/test/java/hudson/model/ViewPropertyTest.java b/test/src/test/java/hudson/model/ViewPropertyTest.java index b9d918bd44826..69d0822879f79 100644 --- a/test/src/test/java/hudson/model/ViewPropertyTest.java +++ b/test/src/test/java/hudson/model/ViewPropertyTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static org.junit.Assert.assertEquals; @@ -56,14 +57,14 @@ public void testRoundtrip() throws Exception { ((HtmlLabel) DomNodeUtil.selectSingleNode(f, ".//LABEL[text()='ViewPropertyImpl']")).click(); j.submit(f); ViewPropertyImpl vp = foo.getProperties().get(ViewPropertyImpl.class); - assertEquals("Duke",vp.name); + assertEquals("Duke", vp.name); // make sure it roundtrips correctly vp.name = "Kohsuke"; j.configRoundtrip(foo); ViewPropertyImpl vp2 = foo.getProperties().get(ViewPropertyImpl.class); - assertNotSame(vp,vp2); - j.assertEqualDataBoundBeans(vp,vp2); + assertNotSame(vp, vp2); + j.assertEqualDataBoundBeans(vp, vp2); } public static class ViewPropertyImpl extends ViewProperty { @@ -91,7 +92,7 @@ public void testInvisibleProperty() throws Exception { InvisiblePropertyImpl vp = new InvisiblePropertyImpl(); foo.getProperties().add(vp); j.configRoundtrip(foo); - assertSame(vp,foo.getProperties().get(InvisiblePropertyImpl.class)); + assertSame(vp, foo.getProperties().get(InvisiblePropertyImpl.class)); } public static class InvisiblePropertyImpl extends ViewProperty { diff --git a/test/src/test/java/hudson/model/ViewTest.java b/test/src/test/java/hudson/model/ViewTest.java index 82bc39c922a32..dabbdda434a7d 100644 --- a/test/src/test/java/hudson/model/ViewTest.java +++ b/test/src/test/java/hudson/model/ViewTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model; import static hudson.model.Messages.Hudson_ViewName; @@ -40,8 +41,6 @@ import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; import com.cloudbees.hudson.plugins.folder.Folder; import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; @@ -54,7 +53,6 @@ import com.gargoylesoftware.htmlunit.html.HtmlForm; import com.gargoylesoftware.htmlunit.html.HtmlLabel; import com.gargoylesoftware.htmlunit.html.HtmlPage; -import com.gargoylesoftware.htmlunit.html.HtmlRadioButtonInput; import com.gargoylesoftware.htmlunit.javascript.host.html.HTMLElement; import com.gargoylesoftware.htmlunit.util.NameValuePair; import edu.umd.cs.findbugs.annotations.CheckForNull; @@ -133,7 +131,7 @@ public class ViewTest { final Map values = new HashMap<>(); - for(NameValuePair p : responseHeaders) { + for (NameValuePair p : responseHeaders) { values.put(p.getName(), p.getValue()); } @@ -174,9 +172,9 @@ public class ViewTest { HtmlAnchor privateViewsLink = userPage.getAnchorByText("My Views"); assertNotNull("My Views link not available", privateViewsLink); - HtmlPage privateViewsPage = (HtmlPage) privateViewsLink.click(); + HtmlPage privateViewsPage = privateViewsLink.click(); - Text viewLabel = (Text) privateViewsPage.getFirstByXPath("//div[@class='tabBar']//div[@class='tab active']/a/text()"); + Text viewLabel = privateViewsPage.getFirstByXPath("//div[@class='tabBar']//div[@class='tab active']/a/text()"); assertTrue("'All' view should be selected", viewLabel.getTextContent().contains(Hudson_ViewName())); View listView = listView("listView"); @@ -184,7 +182,7 @@ public class ViewTest { HtmlPage newViewPage = wc.goTo("user/me/my-views/newView"); HtmlForm form = newViewPage.getFormByName("createItem"); form.getInputByName("name").setValueAttribute("proxy-view"); - ((HtmlRadioButtonInput) form.getInputByValue("hudson.model.ProxyView")).setChecked(true); + form.getInputByValue("hudson.model.ProxyView").setChecked(true); HtmlPage proxyViewConfigurePage = j.submit(form); View proxyView = user.getProperty(MyViewsProperty.class).getView("proxy-view"); assertNotNull(proxyView); @@ -236,7 +234,7 @@ public class ViewTest { // boolean folderPluginClassesLoaded = (j.jenkins.getDescriptor("com.cloudbees.hudson.plugins.folder.Folder") != null); if (!folderPluginActive && folderPluginClassesLoaded) { // reset the icon added by Folder because the plugin resources are not reachable - IconSet.icons.addIcon(new Icon("icon-folder icon-md", "24x24/folder.gif", "width: 24px; height: 24px;")); + IconSet.icons.addIcon(new Icon("icon-folder icon-md", "svgs/folder.svg", "width: 24px; height: 24px;")); } WebClient webClient = j.createWebClient() @@ -308,7 +306,7 @@ public class ViewTest { } @Test - public void testGetQueueItems() throws Exception{ + public void testGetQueueItems() throws Exception { ListView view1 = listView("view1"); view1.filterQueue = true; ListView view2 = listView("view2"); @@ -344,7 +342,7 @@ public void testGetQueueItems() throws Exception{ } private void assertContainsItems(View view, Task... items) { - for (Task job: items) { + for (Task job : items) { assertTrue( "Queued items for " + view.getDisplayName() + " should contain " + job.getDisplayName(), view.getQueueItems().contains(Queue.getInstance().getItem(job)) @@ -353,7 +351,7 @@ private void assertContainsItems(View view, Task... items) { } private void assertNotContainsItems(View view, Task... items) { - for (Task job: items) { + for (Task job : items) { assertFalse( "Queued items for " + view.getDisplayName() + " should not contain " + job.getDisplayName(), view.getQueueItems().contains(Queue.getInstance().getItem(job)) @@ -362,13 +360,13 @@ private void assertNotContainsItems(View view, Task... items) { } @Test - public void testGetComputers() throws Exception{ + public void testGetComputers() throws Exception { ListView view1 = listView("view1"); ListView view2 = listView("view2"); ListView view3 = listView("view3"); - view1.filterExecutors=true; - view2.filterExecutors=true; - view3.filterExecutors=true; + view1.filterExecutors = true; + view2.filterExecutors = true; + view3.filterExecutors = true; Slave slave0 = j.createOnlineSlave(j.jenkins.getLabel("label0")); Slave slave1 = j.createOnlineSlave(j.jenkins.getLabel("label1")); @@ -428,7 +426,7 @@ public void testGetComputersNPE() throws Exception { } private void assertContainsNodes(View view, Node... slaves) { - for (Node slave: slaves) { + for (Node slave : slaves) { assertTrue( "Filtered executors for " + view.getDisplayName() + " should contain " + slave.getDisplayName(), view.getComputers().contains(slave.toComputer()) @@ -437,7 +435,7 @@ private void assertContainsNodes(View view, Node... slaves) { } private void assertNotContainsNodes(View view, Node... slaves) { - for (Node slave: slaves) { + for (Node slave : slaves) { assertFalse( "Filtered executors for " + view.getDisplayName() + " should not contain " + slave.getDisplayName(), view.getComputers().contains(slave.toComputer()) @@ -446,14 +444,14 @@ private void assertNotContainsNodes(View view, Node... slaves) { } @Test - public void testGetItem() throws Exception{ + public void testGetItem() throws Exception { ListView view = listView("foo"); FreeStyleProject job1 = j.createFreeStyleProject("free"); MatrixProject job2 = j.jenkins.createProject(MatrixProject.class, "matrix"); FreeStyleProject job3 = j.createFreeStyleProject("not-included"); view.jobNames.add(job2.getDisplayName()); view.jobNames.add(job1.getDisplayName()); - assertEquals("View should return job " + job1.getDisplayName(),job1, view.getItem("free")); + assertEquals("View should return job " + job1.getDisplayName(), job1, view.getItem("free")); assertNotNull("View should return null.", view.getItem("not-included")); } @@ -470,25 +468,25 @@ public void testRename() throws Exception { @Test public void testGetOwnerItemGroup() throws Exception { ListView view = listView("foo"); - assertEquals("View should have owner jenkins.",j.jenkins.getItemGroup(), view.getOwner().getItemGroup()); + assertEquals("View should have owner jenkins.", j.jenkins.getItemGroup(), view.getOwner().getItemGroup()); } @Test - public void testGetOwnerPrimaryView() throws Exception{ + public void testGetOwnerPrimaryView() throws Exception { ListView view = listView("foo"); j.jenkins.setPrimaryView(view); - assertEquals("View should have primary view " + view.getDisplayName(),view, view.getOwner().getPrimaryView()); + assertEquals("View should have primary view " + view.getDisplayName(), view, view.getOwner().getPrimaryView()); } @Test - public void testSave() throws Exception{ + public void testSave() throws Exception { ListView view = listView("foo"); FreeStyleProject job = j.createFreeStyleProject("free"); view.jobNames.add("free"); view.save(); j.jenkins.doReload(); //wait until all configuration are reloaded - if(j.jenkins.servletContext.getAttribute("app") instanceof HudsonIsLoading){ + if (j.jenkins.servletContext.getAttribute("app") instanceof HudsonIsLoading) { Thread.sleep(500); } assertTrue("View does not contains job free after load.", j.jenkins.getView(view.getDisplayName()).contains(j.jenkins.getItem(job.getName()))); @@ -539,7 +537,7 @@ public String getDisplayName() { grant(Jenkins.READ).everywhere().toEveryone(). grant(Item.READ).everywhere().toEveryone(). grant(Item.CREATE).onFolders(d1).to("dev")); // not on root or d2 - ACL.impersonate2(Jenkins.ANONYMOUS2, new NotReallyRoleSensitiveCallable() { + ACL.impersonate2(Jenkins.ANONYMOUS2, new NotReallyRoleSensitiveCallable() { @Override public Void call() { try { @@ -551,7 +549,7 @@ public Void call() { return null; } }); - ACL.impersonate2(User.get("dev").impersonate2(), new NotReallyRoleSensitiveCallable() { + ACL.impersonate2(User.get("dev").impersonate2(), new NotReallyRoleSensitiveCallable() { @Override public Void call() { try { @@ -570,7 +568,7 @@ public Void call() { return null; } }); - ACL.impersonate2(User.get("admin").impersonate2(), new NotReallyRoleSensitiveCallable() { + ACL.impersonate2(User.get("admin").impersonate2(), new NotReallyRoleSensitiveCallable() { @Override public Void call() { assertCheckJobName(j.jenkins, "whatever", FormValidation.Kind.OK); @@ -614,11 +612,14 @@ public void brokenGetItems() throws Exception { } assertTrue(found); } + private static class BrokenView extends ListView { static final String ERR = "oops I cannot retrieve items"; + BrokenView() { super("broken"); } + @Override public List getItems() { throw new IllegalStateException(ERR); @@ -644,9 +645,9 @@ public void testAllViewNotCreatedIfPrimary() { public void shouldFindNestedViewByName() throws Exception { //given String testNestedViewName = "right2ndNestedView"; - View right2ndNestedView = mockedViewWithName(testNestedViewName); + View right2ndNestedView = new ListView(testNestedViewName); //and - View left2ndNestedView = mockedViewWithName("left2ndNestedView"); + View left2ndNestedView = new ListView("left2ndNestedView"); DummyCompositeView rightNestedGroupView = new DummyCompositeView("rightNestedGroupView", left2ndNestedView, right2ndNestedView); //and listView("leftTopLevelView"); @@ -657,10 +658,6 @@ public void shouldFindNestedViewByName() throws Exception { assertEquals(right2ndNestedView, foundNestedView); } - private View mockedViewWithName(String viewName) { - return given(mock(View.class).getViewName()).willReturn(viewName).getMock(); - } - public void prepareSec1923() { j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); MockAuthorizationStrategy mas = new MockAuthorizationStrategy(); @@ -982,7 +979,7 @@ public TopLevelItem newInstance(ItemGroup parent, String name) { } } - + //Duplication with ViewTest.CompositeView from core unit test module - unfortunately it is inaccessible from here private static class DummyCompositeView extends View implements ViewGroup { @@ -993,8 +990,10 @@ private static class DummyCompositeView extends View implements ViewGroup { private final transient ViewGroupMixIn viewGroupMixIn = new ViewGroupMixIn(this) { @Override protected List views() { return views; } + @Override protected String primaryView() { return primaryView; } + @Override protected void primaryView(String name) { primaryView = name; } }; diff --git a/test/src/test/java/hudson/model/WorkspaceCleanupThreadTest.java b/test/src/test/java/hudson/model/WorkspaceCleanupThreadTest.java index 8e9a511ab2ac2..c62fe7742f72e 100644 --- a/test/src/test/java/hudson/model/WorkspaceCleanupThreadTest.java +++ b/test/src/test/java/hudson/model/WorkspaceCleanupThreadTest.java @@ -61,7 +61,7 @@ public class WorkspaceCleanupThreadTest { FilePath ws1 = createOldWorkspaceOn(r.createOnlineSlave(), p); p.setAssignedNode(r.jenkins); - FreeStyleBuild b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + FreeStyleBuild b = r.buildAndAssertSuccess(p); assertEquals(r.jenkins, b.getBuiltOn()); FilePath ws2 = b.getWorkspace(); @@ -189,7 +189,7 @@ public void deleteTemporaryDirectory() throws Exception { private FilePath createOldWorkspaceOn(Node slave, FreeStyleProject p) throws Exception { p.setAssignedNode(slave); - FreeStyleBuild b1 = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + FreeStyleBuild b1 = r.buildAndAssertSuccess(p); assertEquals(slave, b1.getBuiltOn()); FilePath ws = b1.getWorkspace(); assertNotNull(ws); @@ -203,6 +203,7 @@ private void performCleanup() throws InterruptedException, IOException { private static final class VetoSCM extends NullSCM { private final boolean answer; + VetoSCM(boolean answer) { this.answer = answer; } diff --git a/test/src/test/java/hudson/model/labels/LabelAtomPropertyTest.java b/test/src/test/java/hudson/model/labels/LabelAtomPropertyTest.java index a92fc185d9968..a13494a94521e 100644 --- a/test/src/test/java/hudson/model/labels/LabelAtomPropertyTest.java +++ b/test/src/test/java/hudson/model/labels/LabelAtomPropertyTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.labels; import static org.junit.Assert.assertEquals; @@ -65,7 +66,7 @@ public void configRoundtrip() throws Exception { // it should survive the configuration roundtrip j.submit(j.createWebClient().goTo("label/foo/configure").getFormByName("config")); - assertEquals(1,foo.getProperties().size()); + assertEquals(1, foo.getProperties().size()); j.assertEqualDataBoundBeans(old, foo.getProperties().get(LabelAtomPropertyImpl.class)); } } diff --git a/test/src/test/java/hudson/model/labels/LabelAtomSecurity1986Test.java b/test/src/test/java/hudson/model/labels/LabelAtomSecurity1986Test.java index 7f8061191015f..3f24c4b563bf8 100644 --- a/test/src/test/java/hudson/model/labels/LabelAtomSecurity1986Test.java +++ b/test/src/test/java/hudson/model/labels/LabelAtomSecurity1986Test.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.labels; import static org.hamcrest.MatcherAssert.assertThat; diff --git a/test/src/test/java/hudson/model/labels/LabelAtomTest.java b/test/src/test/java/hudson/model/labels/LabelAtomTest.java index f9dbdb96367e0..bd4be0e27e9bc 100644 --- a/test/src/test/java/hudson/model/labels/LabelAtomTest.java +++ b/test/src/test/java/hudson/model/labels/LabelAtomTest.java @@ -39,9 +39,9 @@ public void getNodes() throws Exception { Label l2 = j.jenkins.getLabel("label2"); Label l3 = j.jenkins.getLabel("label3"); assertThat(l.getNodes().size(), is(2)); - assertThat(l.getNodes(), containsInAnyOrder(n1,n2)); + assertThat(l.getNodes(), containsInAnyOrder(n1, n2)); assertThat(l2.getNodes().size(), is(2)); - assertThat(l2.getNodes(), containsInAnyOrder(n3,n2)); + assertThat(l2.getNodes(), containsInAnyOrder(n3, n2)); assertThat(l3.getNodes(), is(empty())); } diff --git a/test/src/test/java/hudson/model/labels/LabelExpressionTest.java b/test/src/test/java/hudson/model/labels/LabelExpressionTest.java index 812ebdd855511..064ac72f79bf2 100644 --- a/test/src/test/java/hudson/model/labels/LabelExpressionTest.java +++ b/test/src/test/java/hudson/model/labels/LabelExpressionTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.labels; import static org.hamcrest.CoreMatchers.instanceOf; @@ -100,18 +101,18 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen Thread.sleep(1000); // time window to ensure queue has tried to assign f2 build // p3 is tied to 'win', so even though p1 is busy, this should still go ahead and complete - FreeStyleBuild b3 = j.assertBuildStatusSuccess(p3.scheduleBuild2(0)); - assertSame(w64,b3.getBuiltOn()); + FreeStyleBuild b3 = j.buildAndAssertSuccess(p3); + assertSame(w64, b3.getBuiltOn()); seq.phase(3); // once we confirm that p3 build is over, we let p1 proceed // p1 should have been built on w32 FreeStyleBuild b1 = j.assertBuildStatusSuccess(f1); - assertSame(w32,b1.getBuiltOn()); + assertSame(w32, b1.getBuiltOn()); // and so is p2 FreeStyleBuild b2 = j.assertBuildStatusSuccess(f2); - assertSame(w32,b2.getBuiltOn()); + assertSame(w32, b2.getBuiltOn()); } /** @@ -125,16 +126,16 @@ public void queueBehavior2() throws Exception { FreeStyleProject p = j.createFreeStyleProject(); p.setAssignedLabel(j.jenkins.getLabel("!win")); - FreeStyleBuild b = j.assertBuildStatusSuccess(p.scheduleBuild2(0)); - assertSame(j.jenkins,b.getBuiltOn()); + FreeStyleBuild b = j.buildAndAssertSuccess(p); + assertSame(j.jenkins, b.getBuiltOn()); p.setAssignedLabel(j.jenkins.getLabel("win")); - b = j.assertBuildStatusSuccess(p.scheduleBuild2(0)); - assertSame(s,b.getBuiltOn()); + b = j.buildAndAssertSuccess(p); + assertSame(s, b.getBuiltOn()); p.setAssignedLabel(j.jenkins.getLabel("!win")); - b = j.assertBuildStatusSuccess(p.scheduleBuild2(0)); - assertSame(j.jenkins,b.getBuiltOn()); + b = j.buildAndAssertSuccess(p); + assertSame(j.jenkins, b.getBuiltOn()); } /** @@ -175,7 +176,7 @@ public void parser1() throws Exception { @Issue("JENKINS-8537") @Test public void parser2() throws Exception { - parseAndVerify("aaa&&bbb&&ccc","aaa&&bbb&&ccc"); + parseAndVerify("aaa&&bbb&&ccc", "aaa&&bbb&&ccc"); } private void parseAndVerify(String expected, String expr) throws ANTLRException { @@ -213,27 +214,27 @@ public void dataCompatibilityWithHostNameWithWhitespace() throws Exception { FreeStyleProject p = j.createFreeStyleProject(); p.setAssignedLabel(j.jenkins.getLabel("abc def")); - assertEquals("abc def",p.getAssignedLabel().getName()); - assertEquals("\"abc def\"",p.getAssignedLabel().getExpression()); + assertEquals("abc def", p.getAssignedLabel().getName()); + assertEquals("\"abc def\"", p.getAssignedLabel().getExpression()); // expression should be persisted, not the name Field f = AbstractProject.class.getDeclaredField("assignedNode"); f.setAccessible(true); - assertEquals("\"abc def\"",f.get(p)); + assertEquals("\"abc def\"", f.get(p)); // but if the name is set, we'd still like to parse it - f.set(p,"a:b c"); - assertEquals("a:b c",p.getAssignedLabel().getName()); + f.set(p, "a:b c"); + assertEquals("a:b c", p.getAssignedLabel().getName()); } @Test public void quote() { Label l = j.jenkins.getLabel("\"abc\\\\\\\"def\""); - assertEquals("abc\\\"def",l.getName()); + assertEquals("abc\\\"def", l.getName()); l = j.jenkins.getLabel("label1||label2"); // create label expression l = j.jenkins.getLabel("\"label1||label2\""); - assertEquals("label1||label2",l.getName()); + assertEquals("label1||label2", l.getName()); } /** @@ -242,9 +243,9 @@ public void quote() { @Test public void composite() { LabelAtom x = j.jenkins.getLabelAtom("x"); - assertEquals("!!x",x.not().not().getName()); - assertEquals("(x||x)&&x",x.or(x).and(x).getName()); - assertEquals("x&&x||x",x.and(x).or(x).getName()); + assertEquals("!!x", x.not().not().getName()); + assertEquals("(x||x)&&x", x.or(x).and(x).getName()); + assertEquals("x&&x||x", x.and(x).or(x).getName()); } @Test @@ -371,7 +372,7 @@ public void parseLabel() { Set result = Label.parse("one two three"); String[] expected = {"one", "two", "three"}; - for(String e : expected) { + for (String e : expected) { assertTrue(result.contains(new LabelAtom(e))); } diff --git a/test/src/test/java/hudson/model/listeners/ItemListenerTest.java b/test/src/test/java/hudson/model/listeners/ItemListenerTest.java index 520bb87838756..6209790f1a974 100644 --- a/test/src/test/java/hudson/model/listeners/ItemListenerTest.java +++ b/test/src/test/java/hudson/model/listeners/ItemListenerTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.listeners; import static org.hamcrest.MatcherAssert.assertThat; @@ -30,6 +31,7 @@ import hudson.cli.CLICommandInvoker; import hudson.model.Item; import java.io.ByteArrayInputStream; +import java.nio.charset.Charset; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -52,6 +54,7 @@ public void setUp() { @Override public void onCreated(Item item) { events.append('C'); } + @Override public void onCopied(Item src, Item item) { events.append('Y'); } @@ -62,7 +65,7 @@ public void setUp() { @Test public void onCreatedViaCLI() { CLICommandInvoker.Result result = new CLICommandInvoker(j, "create-job"). - withStdin(new ByteArrayInputStream("".getBytes())). + withStdin(new ByteArrayInputStream("".getBytes(Charset.defaultCharset()))). invokeWithArgs("testJob"); assertThat(result, CLICommandInvoker.Matcher.succeeded()); assertNotNull("job should be created: " + result, j.jenkins.getItem("testJob")); diff --git a/test/src/test/java/hudson/model/queue/BuildKeepsRunningWhenFaultySubTasksTest.java b/test/src/test/java/hudson/model/queue/BuildKeepsRunningWhenFaultySubTasksTest.java index 7c81f20bf9765..f5e50f4124eff 100644 --- a/test/src/test/java/hudson/model/queue/BuildKeepsRunningWhenFaultySubTasksTest.java +++ b/test/src/test/java/hudson/model/queue/BuildKeepsRunningWhenFaultySubTasksTest.java @@ -24,7 +24,7 @@ public class BuildKeepsRunningWhenFaultySubTasksTest { public JenkinsRule j = new JenkinsRule(); public static final String ERROR_MESSAGE = "My unexpected exception"; - + // When using SubTaskContributor (FailingSubTaskContributor) the build never ends @Test @Issue("JENKINS-59793") @@ -36,7 +36,7 @@ public void buildFinishesWhenSubTaskFails() throws Exception { // We don't get stalled waiting the finalization of the job future.get(5, TimeUnit.SECONDS); } - + // A SubTask failing with an exception @TestExtension public static class FailingSubTaskContributor extends SubTaskContributor { @@ -69,26 +69,32 @@ public long getEstimatedDuration() { public Label getAssignedLabel() { return null; } + @Override public Node getLastBuiltOn() { return null; } + @Override public long getEstimatedDuration() { return 0; } + @Override public Queue.Task getOwnerTask() { return p; } + @Override public Object getSameNodeConstraint() { return null; } + @Override public ResourceList getResourceList() { return ResourceList.EMPTY; } + @Override public String getDisplayName() { return "Subtask of " + p.getDisplayName(); diff --git a/test/src/test/java/hudson/model/queue/LoadPredictorTest.java b/test/src/test/java/hudson/model/queue/LoadPredictorTest.java index d48574b130a6a..74b2832342001 100644 --- a/test/src/test/java/hudson/model/queue/LoadPredictorTest.java +++ b/test/src/test/java/hudson/model/queue/LoadPredictorTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.model.queue; import static org.junit.Assert.assertEquals; @@ -86,11 +87,11 @@ public void test1() throws Exception { // the test load predictor should have pushed down the executor count to 0 assertTrue(mw.executors.isEmpty()); - assertEquals(1,mw.works.size()); + assertEquals(1, mw.works.size()); } private BuildableItem wrap(Queue.Task t) { - return new BuildableItem(new WaitingItem(new GregorianCalendar(),t,new ArrayList<>())); + return new BuildableItem(new WaitingItem(new GregorianCalendar(), t, new ArrayList<>())); } private JobOffer createMockOffer(Executor e) { @@ -106,7 +107,7 @@ private Computer createMockComputer(int nExecutors) throws Exception { List executors = new CopyOnWriteArrayList(); - for (int i=0; i0); + assertTrue(du.size > 0); } @Test @WithoutJenkins public void parse() throws Exception { - assertEquals(1,DiskSpace.parse("1").size); - assertEquals(1024,DiskSpace.parse("1KB").size); - assertEquals(1024,DiskSpace.parse("1K").size); - assertEquals(1024,DiskSpace.parse("1kb").size); - assertEquals(1024*1024,DiskSpace.parse("1MB").size); - assertEquals(1024*1024*1024,DiskSpace.parse("1GB").size); - assertEquals(512*1024*1024,DiskSpace.parse("0.5GB").size); + assertEquals(1, DiskSpace.parse("1").size); + assertEquals(1024, DiskSpace.parse("1KB").size); + assertEquals(1024, DiskSpace.parse("1K").size); + assertEquals(1024, DiskSpace.parse("1kb").size); + assertEquals(1024 * 1024, DiskSpace.parse("1MB").size); + assertEquals(1024 * 1024 * 1024, DiskSpace.parse("1GB").size); + assertEquals(512 * 1024 * 1024, DiskSpace.parse("0.5GB").size); } @Test @WithoutJenkins @Issue("JENKINS-59383") public void string() { - DiskSpace du = new DiskSpace("/tmp", 123*1024*1024); + DiskSpace du = new DiskSpace("/tmp", 123 * 1024 * 1024); assertEquals("0.123GB left on /tmp.", du.toString()); du.setTriggered(true); assertEquals("Disk space is too low. Only 0.123GB left on /tmp.", du.toString()); diff --git a/test/src/test/java/hudson/pages/SystemConfigurationTestCase.java b/test/src/test/java/hudson/pages/SystemConfigurationTestCase.java index 1bc4d88558f2b..1004ce908aadb 100644 --- a/test/src/test/java/hudson/pages/SystemConfigurationTestCase.java +++ b/test/src/test/java/hudson/pages/SystemConfigurationTestCase.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Erik Ramfelt - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.pages; import static org.junit.Assert.assertEquals; diff --git a/test/src/test/java/hudson/scm/AbstractScmTagActionTest.java b/test/src/test/java/hudson/scm/AbstractScmTagActionTest.java index 065bcbfdfa6f1..b9fecd1223ff3 100644 --- a/test/src/test/java/hudson/scm/AbstractScmTagActionTest.java +++ b/test/src/test/java/hudson/scm/AbstractScmTagActionTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scm; import static org.hamcrest.MatcherAssert.assertThat; @@ -55,29 +56,29 @@ public class AbstractScmTagActionTest { @Test public void regularTextDisplayedCorrectly() throws Exception { FreeStyleProject p = j.createFreeStyleProject(); - + String tagToKeep = "Nice tag with space"; p.setScm(new FakeSCM(tagToKeep)); - j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + j.buildAndAssertSuccess(p); String tooltip = buildAndExtractTooltipAttribute(p); assertEquals(tagToKeep, tooltip); } - + @Test @Issue("SECURITY-1537") public void preventXssInTagAction() throws Exception { FreeStyleProject p = j.createFreeStyleProject(); p.setScm(new FakeSCM("XSS")); - j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + j.buildAndAssertSuccess(p); String tooltip = buildAndExtractTooltipAttribute(p); assertThat(tooltip, not(containsString("<"))); assertThat(tooltip, startsWith("<")); } - + private String buildAndExtractTooltipAttribute(FreeStyleProject p) throws Exception { JenkinsRule.WebClient wc = j.createWebClient(); diff --git a/test/src/test/java/hudson/scm/ChangeLogSetTest.java b/test/src/test/java/hudson/scm/ChangeLogSetTest.java index 74e4c16699ed7..295b8afa724a6 100644 --- a/test/src/test/java/hudson/scm/ChangeLogSetTest.java +++ b/test/src/test/java/hudson/scm/ChangeLogSetTest.java @@ -33,7 +33,7 @@ public void catchingExceptionDuringAnnotation() { @Extension public static final class ThrowExceptionChangeLogAnnotator extends ChangeLogAnnotator { @Override - public void annotate(AbstractBuild build, ChangeLogSet.Entry change, MarkupText text ) { + public void annotate(AbstractBuild build, ChangeLogSet.Entry change, MarkupText text) { throw new RuntimeException(); } } @@ -41,7 +41,7 @@ public void annotate(AbstractBuild build, ChangeLogSet.Entry change, Markup @Extension public static final class ThrowErrorChangeLogAnnotator extends ChangeLogAnnotator { @Override - public void annotate(AbstractBuild build, ChangeLogSet.Entry change, MarkupText text ) { + public void annotate(AbstractBuild build, ChangeLogSet.Entry change, MarkupText text) { throw new Error(); } } diff --git a/test/src/test/java/hudson/scm/ScmTest.java b/test/src/test/java/hudson/scm/ScmTest.java index e95034c6c373f..9529af0ea1d8e 100644 --- a/test/src/test/java/hudson/scm/ScmTest.java +++ b/test/src/test/java/hudson/scm/ScmTest.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,9 +21,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.scm; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import hudson.FilePath; @@ -31,7 +31,6 @@ import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.BuildListener; -import hudson.model.FreeStyleBuild; import hudson.model.FreeStyleProject; import hudson.model.Node; import hudson.model.Result; @@ -69,7 +68,7 @@ private Object writeReplace() { // don't really care about save return new NullSCM(); } }); - p.scheduleBuild2(0).get(); + j.buildAndAssertSuccess(p); p.delete(); assertTrue(callback[0]); } @@ -92,7 +91,6 @@ private Object writeReplace() { // don't really care about save } }); - FreeStyleBuild build = p.scheduleBuild2(0).get(); - assertEquals(Result.ABORTED, build.getResult()); + j.buildAndAssertStatus(Result.ABORTED, p); } } diff --git a/test/src/test/java/hudson/search/SearchTest.java b/test/src/test/java/hudson/search/SearchTest.java index 5250cd4893138..26d8deefa5bce 100644 --- a/test/src/test/java/hudson/search/SearchTest.java +++ b/test/src/test/java/hudson/search/SearchTest.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.search; import static org.junit.Assert.assertEquals; @@ -59,9 +60,9 @@ * @author Kohsuke Kawaguchi */ public class SearchTest { - + @Rule public JenkinsRule j = new JenkinsRule(); - + /** * No exact match should result in a failure status code. */ @@ -87,17 +88,17 @@ public void testXSS() throws Exception { HtmlPage resultPage = wc.search(""); assertEquals(HttpURLConnection.HTTP_NOT_FOUND, resultPage.getWebResponse().getStatusCode()); } - + @Test public void testSearchByProjectName() throws Exception { final String projectName = "testSearchByProjectName"; - + j.createFreeStyleProject(projectName); - + Page result = j.search(projectName); assertNotNull(result); j.assertGoodStatus(result); - + // make sure we've fetched the testSearchByDisplayName project page String contents = result.getWebResponse().getContentAsString(); assertTrue(contents.contains(String.format("%s [Jenkins]", projectName))); @@ -109,7 +110,7 @@ public void testSearchByProjectNameBehindAFolder() throws Exception { FreeStyleProject myFreeStyleProject = j.createFreeStyleProject("testSearchByProjectName"); MockFolder myMockFolder = j.createFolder("my-folder-1"); - Page result = j.createWebClient().goTo(myMockFolder.getUrl() + "search?q="+ myFreeStyleProject.getName()); + Page result = j.createWebClient().goTo(myMockFolder.getUrl() + "search?q=" + myFreeStyleProject.getName()); assertNotNull(result); j.assertGoodStatus(result); @@ -137,19 +138,19 @@ public void testSearchByProjectNameInAFolder() throws Exception { @Test public void testSearchByDisplayName() throws Exception { final String displayName = "displayName9999999"; - + FreeStyleProject project = j.createFreeStyleProject("testSearchByDisplayName"); project.setDisplayName(displayName); - + Page result = j.search(displayName); assertNotNull(result); j.assertGoodStatus(result); - + // make sure we've fetched the testSearchByDisplayName project page String contents = result.getWebResponse().getContentAsString(); assertTrue(contents.contains(String.format("%s [Jenkins]", displayName))); } - + @Test public void testSearch2ProjectsWithSameDisplayName() throws Exception { // create 2 freestyle projects with the same display name @@ -158,7 +159,7 @@ public void testSearch2ProjectsWithSameDisplayName() throws Exception { final String projectName3 = "projectName3"; final String displayName = "displayNameFoo"; final String otherDisplayName = "otherDisplayName"; - + FreeStyleProject project1 = j.createFreeStyleProject(projectName1); project1.setDisplayName(displayName); FreeStyleProject project2 = j.createFreeStyleProject(projectName2); @@ -178,7 +179,7 @@ public void testSearch2ProjectsWithSameDisplayName() throws Exception { assertTrue(contents.contains(String.format("%s [Jenkins]", displayName))); assertFalse(contents.contains(otherDisplayName)); } - + @Test public void testProjectNamePrecedesDisplayName() throws Exception { final String project1Name = "foo"; @@ -187,11 +188,11 @@ public void testProjectNamePrecedesDisplayName() throws Exception { final String project2DisplayName = project1Name; final String project3Name = "project3Name"; final String project3DisplayName = "project3DisplayName"; - + // create 1 freestyle project with the name foo FreeStyleProject project1 = j.createFreeStyleProject(project1Name); project1.setDisplayName(project1DisplayName); - + // create another with the display name foo FreeStyleProject project2 = j.createFreeStyleProject(project2Name); project2.setDisplayName(project2DisplayName); @@ -199,12 +200,12 @@ public void testProjectNamePrecedesDisplayName() throws Exception { // create a third project and make sure it's not picked up by search FreeStyleProject project3 = j.createFreeStyleProject(project3Name); project3.setDisplayName(project3DisplayName); - + // search for foo Page result = j.search(project1Name); assertNotNull(result); j.assertGoodStatus(result); - + // make sure we get the project with the name foo String contents = result.getWebResponse().getContentAsString(); assertTrue(contents.contains(String.format("%s [Jenkins]", project1DisplayName))); @@ -213,7 +214,7 @@ public void testProjectNamePrecedesDisplayName() throws Exception { assertFalse(contents.contains(project3Name)); assertFalse(contents.contains(project3DisplayName)); } - + @Test public void testGetSuggestionsHasBothNamesAndDisplayNames() throws Exception { final String projectName = "project name"; @@ -221,31 +222,31 @@ public void testGetSuggestionsHasBothNamesAndDisplayNames() throws Exception { FreeStyleProject project1 = j.createFreeStyleProject(projectName); project1.setDisplayName(displayName); - + WebClient wc = j.createWebClient(); Page result = wc.goTo("search/suggest?query=name", "application/json"); assertNotNull(result); j.assertGoodStatus(result); - + String content = result.getWebResponse().getContentAsString(); System.out.println(content); - JSONObject jsonContent = (JSONObject)JSONSerializer.toJSON(content); + JSONObject jsonContent = (JSONObject) JSONSerializer.toJSON(content); assertNotNull(jsonContent); JSONArray jsonArray = jsonContent.getJSONArray("suggestions"); assertNotNull(jsonArray); - + assertEquals(2, jsonArray.size()); - + boolean foundProjectName = false; boolean foundDisplayName = false; - for(Object suggestion : jsonArray) { - JSONObject jsonSuggestion = (JSONObject)suggestion; - - String name = (String)jsonSuggestion.get("name"); - if(projectName.equals(name)) { + for (Object suggestion : jsonArray) { + JSONObject jsonSuggestion = (JSONObject) suggestion; + + String name = (String) jsonSuggestion.get("name"); + if (projectName.equals(name)) { foundProjectName = true; } - else if(displayName.equals(name)) { + else if (displayName.equals(name)) { foundDisplayName = true; } } @@ -277,7 +278,7 @@ public void testProjectNameBehindAFolderDisplayName() throws Exception { j.assertGoodStatus(result); String content = result.getWebResponse().getContentAsString(); - JSONObject jsonContent = (JSONObject)JSONSerializer.toJSON(content); + JSONObject jsonContent = (JSONObject) JSONSerializer.toJSON(content); assertNotNull(jsonContent); JSONArray jsonArray = jsonContent.getJSONArray("suggestions"); assertNotNull(jsonArray); @@ -285,11 +286,11 @@ public void testProjectNameBehindAFolderDisplayName() throws Exception { assertEquals(2, jsonArray.size()); boolean foundDisplayName = false; - for(Object suggestion : jsonArray) { - JSONObject jsonSuggestion = (JSONObject)suggestion; + for (Object suggestion : jsonArray) { + JSONObject jsonSuggestion = (JSONObject) suggestion; - String name = (String)jsonSuggestion.get("name"); - if(projectName1.equals(name)) { + String name = (String) jsonSuggestion.get("name"); + if (projectName1.equals(name)) { foundDisplayName = true; } } @@ -320,7 +321,7 @@ public void testProjectNameInAFolderDisplayName() throws Exception { j.assertGoodStatus(result); String content = result.getWebResponse().getContentAsString(); - JSONObject jsonContent = (JSONObject)JSONSerializer.toJSON(content); + JSONObject jsonContent = (JSONObject) JSONSerializer.toJSON(content); assertNotNull(jsonContent); JSONArray jsonArray = jsonContent.getJSONArray("suggestions"); assertNotNull(jsonArray); @@ -328,12 +329,12 @@ public void testProjectNameInAFolderDisplayName() throws Exception { assertEquals(1, jsonArray.size()); boolean foundDisplayName = false; - for(Object suggestion : jsonArray) { - JSONObject jsonSuggestion = (JSONObject)suggestion; + for (Object suggestion : jsonArray) { + JSONObject jsonSuggestion = (JSONObject) suggestion; - String name = (String)jsonSuggestion.get("name"); + String name = (String) jsonSuggestion.get("name"); - if(displayName2.equals(name)) { + if (displayName2.equals(name)) { foundDisplayName = true; } } @@ -361,8 +362,8 @@ public void testDisabledJobShouldBeSearchable() throws Exception { @Test public void testCompletionOutsideView() throws Exception { FreeStyleProject p = j.createFreeStyleProject("foo-bar"); - ListView v = new ListView("empty1",j.jenkins); - ListView w = new ListView("empty2",j.jenkins); + ListView v = new ListView("empty1", j.jenkins); + ListView w = new ListView("empty2", j.jenkins); j.jenkins.addView(v); j.jenkins.addView(w); j.jenkins.setPrimaryView(w); @@ -372,7 +373,7 @@ public void testCompletionOutsideView() throws Exception { assertFalse(w.contains(p)); assertFalse(j.jenkins.getPrimaryView().contains(p)); - assertTrue(suggest(j.jenkins.getSearchIndex(),"foo").contains(p)); + assertTrue(suggest(j.jenkins.getSearchIndex(), "foo").contains(p)); } @Issue("SECURITY-385") @@ -405,7 +406,7 @@ public void run() { } }); } - + @Test public void testSearchWithinFolders() throws Exception { MockFolder folder1 = j.createFolder("folder1"); @@ -426,7 +427,7 @@ public void adminOnlyLinksNotShownToRegularUser() { mas.grant(Jenkins.READ).onRoot().toEveryone(); j.jenkins.setAuthorizationStrategy(mas); - try(ACLContext acl = ACL.as(User.get("alice"))) { + try (ACLContext acl = ACL.as(User.get("alice"))) { List results = new ArrayList<>(); j.jenkins.getSearchIndex().find("config", results); j.jenkins.getSearchIndex().find("manage", results); @@ -464,7 +465,7 @@ public void testProjectNameInAListView() throws Exception { j.assertGoodStatus(result); String content = result.getWebResponse().getContentAsString(); - JSONObject jsonContent = (JSONObject)JSONSerializer.toJSON(content); + JSONObject jsonContent = (JSONObject) JSONSerializer.toJSON(content); assertNotNull(jsonContent); JSONArray jsonArray = jsonContent.getJSONArray("suggestions"); assertNotNull(jsonArray); diff --git a/test/src/test/java/hudson/security/AccessDeniedException3Test.java b/test/src/test/java/hudson/security/AccessDeniedException3Test.java index 6a766bbb69126..479ca8e3d59c2 100644 --- a/test/src/test/java/hudson/security/AccessDeniedException3Test.java +++ b/test/src/test/java/hudson/security/AccessDeniedException3Test.java @@ -97,15 +97,18 @@ public void captureException() throws Exception { assertEquals("should send a 403 from AccessDeniedException2", HttpURLConnection.HTTP_FORBIDDEN, x.getStatusCode()); assertEquals("should report X-You-Are-Authenticated-As from AccessDeniedException2", "user", x.getResponse().getResponseHeaderValue("X-You-Are-Authenticated-As")); } + @TestExtension("captureException") public static final class Fails extends InvisibleAction implements RootAction { @Override public String getUrlName() { return "fails"; } + public HttpResponse doAccessDeniedException3() { throw new AccessDeniedException3(Jenkins.getAuthentication2(), Item.READ); } + @SuppressWarnings("deprecation") public HttpResponse doAccessDeniedException2() { throw new AccessDeniedException2(Jenkins.getAuthentication(), Item.READ); diff --git a/test/src/test/java/hudson/security/ExtendedReadPermissionTest.java b/test/src/test/java/hudson/security/ExtendedReadPermissionTest.java index 5a3b154a7f39d..31085c8c23034 100644 --- a/test/src/test/java/hudson/security/ExtendedReadPermissionTest.java +++ b/test/src/test/java/hudson/security/ExtendedReadPermissionTest.java @@ -58,7 +58,7 @@ private void setPermissionEnabled(boolean enabled) { HtmlPage page = wc.goTo("job/a/configure"); HtmlForm form = page.getFormByName("config"); - HtmlButton saveButton = r.getButtonByCaption(form,"Save"); + HtmlButton saveButton = r.getButtonByCaption(form, "Save"); assertNull(saveButton); } @@ -68,7 +68,7 @@ private void setPermissionEnabled(boolean enabled) { + " MockAuthorizationStrategy does not implement this check.") @Test public void readOnlyConfigAccessWithPermissionDisabled() throws Exception { setPermissionEnabled(false); - + JenkinsRule.WebClient wc = r.createWebClient(); wc.withBasicCredentials("charlie"); diff --git a/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java b/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java index 4ba76a0dedb8e..c66a40d26d000 100644 --- a/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java +++ b/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java @@ -98,7 +98,7 @@ public void setup() throws Exception { public void fullNameCollisionPassword() throws Exception { HudsonPrivateSecurityRealm securityRealm = new HudsonPrivateSecurityRealm(false, false, null); j.jenkins.setSecurityRealm(securityRealm); - + User u1 = securityRealm.createAccount("user1", "password1"); u1.setFullName("User One"); u1.save(); @@ -113,17 +113,17 @@ public void fullNameCollisionPassword() throws Exception { WebClient wc2 = j.createWebClient(); wc2.login("user2", "password2"); - + // Check both users can use their token XmlPage w1 = (XmlPage) wc1.goTo("whoAmI/api/xml", "application/xml"); assertThat(w1, hasXPath("//name", is("user1"))); - + XmlPage w2 = (XmlPage) wc2.goTo("whoAmI/api/xml", "application/xml"); assertThat(w2, hasXPath("//name", is("user2"))); u1.setFullName("user2"); u1.save(); - + // check the tokens still work wc1 = j.createWebClient(); wc1.login("user1", "password1"); @@ -135,7 +135,7 @@ public void fullNameCollisionPassword() throws Exception { // belt and braces in case the failed login no longer throws exceptions. w1 = (XmlPage) wc1.goTo("whoAmI/api/xml", "application/xml"); assertThat(w1, hasXPath("//name", is("user1"))); - + w2 = (XmlPage) wc2.goTo("whoAmI/api/xml", "application/xml"); assertThat(w2, hasXPath("//name", is("user2"))); } @@ -144,10 +144,10 @@ public void fullNameCollisionPassword() throws Exception { @Test public void fullNameCollisionToken() throws Exception { ApiTokenTestHelper.enableLegacyBehavior(); - + HudsonPrivateSecurityRealm securityRealm = new HudsonPrivateSecurityRealm(false, false, null); j.jenkins.setSecurityRealm(securityRealm); - + User u1 = securityRealm.createAccount("user1", "password1"); u1.setFullName("User One"); u1.save(); @@ -165,11 +165,11 @@ public void fullNameCollisionToken() throws Exception { WebClient wc2 = j.createWebClient(); wc2.addRequestHeader("Authorization", basicHeader("user2", u2Token)); //wc2.setCredentialsProvider(new FixedCredentialsProvider("user2", u1Token)); - + // Check both users can use their token XmlPage w1 = (XmlPage) wc1.goTo("whoAmI/api/xml", "application/xml"); assertThat(w1, hasXPath("//name", is("user1"))); - + XmlPage w2 = (XmlPage) wc2.goTo("whoAmI/api/xml", "application/xml"); assertThat(w2, hasXPath("//name", is("user2"))); @@ -179,14 +179,14 @@ public void fullNameCollisionToken() throws Exception { // check the tokens still work w1 = (XmlPage) wc1.goTo("whoAmI/api/xml", "application/xml"); assertThat(w1, hasXPath("//name", is("user1"))); - + w2 = (XmlPage) wc2.goTo("whoAmI/api/xml", "application/xml"); assertThat(w2, hasXPath("//name", is("user2"))); } private static String basicHeader(String user, String pass) { - String str = user +':' + pass; + String str = user + ':' + pass; String auth = Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8)); return "Basic " + auth; } @@ -239,7 +239,7 @@ public void systemCantSignup() throws Exception { signup.enterEmail("noone@nowhere.com"); signup = new SignupPage(signup.submit(j)); signup.assertErrorContains("prohibited as a username"); - assertNull(User.get("system",false, Collections.emptyMap())); + assertNull(User.get("system", false, Collections.emptyMap())); } /** @@ -258,7 +258,7 @@ public void fullNameOfUnknownCantSignup() throws Exception { signup.enterEmail("noone@nowhere.com"); signup = new SignupPage(signup.submit(j)); signup.assertErrorContains("prohibited as a full name"); - assertNull(User.get("unknown2",false, Collections.emptyMap())); + assertNull(User.get("unknown2", false, Collections.emptyMap())); } @Issue("JENKINS-48383") @@ -424,11 +424,11 @@ protected void loggedIn(@NonNull String username) { public void controlCharacterAreNoMoreValid() throws Exception { HudsonPrivateSecurityRealm securityRealm = new HudsonPrivateSecurityRealm(true, false, null); j.jenkins.setSecurityRealm(securityRealm); - + String password = "testPwd"; String email = "test@test.com"; int i = 0; - + // regular case = only accepting a-zA-Z0-9 + "-_" checkUserCanBeCreatedWith(securityRealm, "test" + i, password, "Test" + i, email); assertNotNull(User.getById("test" + i, false)); @@ -436,7 +436,7 @@ public void controlCharacterAreNoMoreValid() throws Exception { checkUserCanBeCreatedWith(securityRealm, "te-st_123" + i, password, "Test" + i, email); assertNotNull(User.getById("te-st_123" + i, false)); i++; - {// user id that contains invalid characters + { // user id that contains invalid characters checkUserCannotBeCreatedWith(securityRealm, "test " + i, password, "Test" + i, email); i++; checkUserCannotBeCreatedWith(securityRealm, "te@st" + i, password, "Test" + i, email); @@ -454,23 +454,23 @@ public void controlCharacterAreNoMoreValid() throws Exception { checkUserCannotBeCreatedWith(securityRealm, "te\u0000st" + i, password, "Test" + i, email); } } - + @Issue("SECURITY-786") @Test public void controlCharacterAreNoMoreValid_CustomRegex() throws Exception { HudsonPrivateSecurityRealm securityRealm = new HudsonPrivateSecurityRealm(true, false, null); j.jenkins.setSecurityRealm(securityRealm); - + String currentRegex = "^[A-Z]+[0-9]*$"; - + Field field = HudsonPrivateSecurityRealm.class.getDeclaredField("ID_REGEX"); field.setAccessible(true); field.set(null, currentRegex); - + String password = "testPwd"; String email = "test@test.com"; int i = 0; - + // regular case = only accepting a-zA-Z0-9 + "-_" checkUserCanBeCreatedWith(securityRealm, "TEST" + i, password, "Test" + i, email); assertNotNull(User.getById("TEST" + i, false)); @@ -478,7 +478,7 @@ public void controlCharacterAreNoMoreValid_CustomRegex() throws Exception { checkUserCanBeCreatedWith(securityRealm, "TEST123" + i, password, "Test" + i, email); assertNotNull(User.getById("TEST123" + i, false)); i++; - {// user id that do not follow custom regex + { // user id that do not follow custom regex checkUserCannotBeCreatedWith_custom(securityRealm, "test " + i, password, "Test" + i, email, currentRegex); i++; checkUserCannotBeCreatedWith_custom(securityRealm, "@" + i, password, "Test" + i, email, currentRegex); @@ -489,7 +489,7 @@ public void controlCharacterAreNoMoreValid_CustomRegex() throws Exception { { // we can even change regex on the fly currentRegex = "^[0-9]*$"; field.set(null, currentRegex); - + checkUserCanBeCreatedWith(securityRealm, "125213" + i, password, "Test" + i, email); assertNotNull(User.getById("125213" + i, false)); i++; @@ -557,7 +557,7 @@ public void ensureHashingVersion_2x_isNotSupported() { public void ensureHashingVersion_2y_isNotSupported() { assertThrows(IllegalArgumentException.class, () -> BCrypt.checkpw("a", "$2y$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V.")); } - + private void checkUserCanBeCreatedWith(HudsonPrivateSecurityRealm securityRealm, String id, String password, String fullName, String email) throws Exception { JenkinsRule.WebClient wc = j.createWebClient(); SignupPage signup = new SignupPage(wc.goTo("signup")); @@ -568,7 +568,7 @@ private void checkUserCanBeCreatedWith(HudsonPrivateSecurityRealm securityRealm, HtmlPage success = signup.submit(j); assertThat(success.getElementById("main-panel").getTextContent(), containsString("Success")); } - + private void checkUserCannotBeCreatedWith(HudsonPrivateSecurityRealm securityRealm, String id, String password, String fullName, String email) throws Exception { JenkinsRule.WebClient wc = j.createWebClient(); SignupPage signup = new SignupPage(wc.goTo("signup")); @@ -580,7 +580,7 @@ private void checkUserCannotBeCreatedWith(HudsonPrivateSecurityRealm securityRea assertThat(success.getElementById("main-panel").getTextContent(), not(containsString("Success"))); assertThat(success.getElementById("main-panel").getTextContent(), containsString(Messages.HudsonPrivateSecurityRealm_CreateAccount_UserNameInvalidCharacters())); } - + private void checkUserCannotBeCreatedWith_custom(HudsonPrivateSecurityRealm securityRealm, String id, String password, String fullName, String email, String regex) throws Exception { JenkinsRule.WebClient wc = j.createWebClient(); SignupPage signup = new SignupPage(wc.goTo("signup")); diff --git a/test/src/test/java/hudson/security/LoginTest.java b/test/src/test/java/hudson/security/LoginTest.java index 85a6bb522e5e4..c6d59a672e029 100644 --- a/test/src/test/java/hudson/security/LoginTest.java +++ b/test/src/test/java/hudson/security/LoginTest.java @@ -7,7 +7,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import com.gargoylesoftware.htmlunit.html.HtmlCheckBoxInput; import com.gargoylesoftware.htmlunit.html.HtmlForm; import com.gargoylesoftware.htmlunit.html.HtmlFormUtil; import com.gargoylesoftware.htmlunit.html.HtmlPage; @@ -76,7 +75,7 @@ public void loginError() throws Exception { form.getInputByName("j_password").setValueAttribute("oops I forgot"); wc.setThrowExceptionOnFailingStatusCode(false); page = (HtmlPage) HtmlFormUtil.submit(form, null); - assertThat(page.asText(), containsString("Invalid username or password")); + assertThat(page.asNormalizedText(), containsString("Invalid username or password")); } private HtmlForm prepareLoginFormWithRememberMeChecked(WebClient wc) throws IOException, org.xml.sax.SAXException { @@ -86,7 +85,7 @@ private HtmlForm prepareLoginFormWithRememberMeChecked(WebClient wc) throws IOEx HtmlForm form = page.getFormByName("login"); form.getInputByName("j_username").setValueAttribute("alice"); form.getInputByName("j_password").setValueAttribute("alice"); - ((HtmlCheckBoxInput)form.getInputByName("remember_me")).setChecked(true); + form.getInputByName("remember_me").setChecked(true); return form; } diff --git a/test/src/test/java/hudson/security/PermissionGroupTest.java b/test/src/test/java/hudson/security/PermissionGroupTest.java index 70d87fa57827b..7fbd6b20ad22d 100644 --- a/test/src/test/java/hudson/security/PermissionGroupTest.java +++ b/test/src/test/java/hudson/security/PermissionGroupTest.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import static org.junit.Assert.assertSame; diff --git a/test/src/test/java/hudson/security/SecurityRealmSecurity2371Test.java b/test/src/test/java/hudson/security/SecurityRealmSecurity2371Test.java index a9d475b6924cf..eee1f3099ceda 100644 --- a/test/src/test/java/hudson/security/SecurityRealmSecurity2371Test.java +++ b/test/src/test/java/hudson/security/SecurityRealmSecurity2371Test.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import static org.junit.Assert.assertThrows; diff --git a/test/src/test/java/hudson/security/SecurityRealmTest.java b/test/src/test/java/hudson/security/SecurityRealmTest.java index 55448bc3c8a50..7535e118decf0 100644 --- a/test/src/test/java/hudson/security/SecurityRealmTest.java +++ b/test/src/test/java/hudson/security/SecurityRealmTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.security; import static org.hamcrest.CoreMatchers.is; @@ -89,7 +90,7 @@ public void generateImage(String id, OutputStream ios) { } static void addSessionCookie(CookieManager manager, String domain, String path, Date date) { - manager.addCookie(new Cookie(domain, "JSESSIONID."+Integer.toHexString(new Random().nextInt()), + manager.addCookie(new Cookie(domain, "JSESSIONID." + Integer.toHexString(new Random().nextInt()), "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", path, date, @@ -158,18 +159,23 @@ public void getPostLogOutUrl() throws Exception { return null; }); } + @SuppressWarnings("deprecation") public static final class OldSecurityRealm extends SecurityRealm { boolean special; + @DataBoundConstructor public OldSecurityRealm() {} + @Override public SecurityRealm.SecurityComponents createSecurityComponents() { return new SecurityComponents(); } + @Override protected String getPostLogOutUrl(StaplerRequest req, org.acegisecurity.Authentication auth) { return special ? req.getContextPath() + "/custom" : super.getPostLogOutUrl(req, auth); } + @TestExtension("getPostLogOutUrl") public static final class DescriptorImpl extends Descriptor {} } diff --git a/test/src/test/java/hudson/security/TokenBasedRememberMeServices2Test.java b/test/src/test/java/hudson/security/TokenBasedRememberMeServices2Test.java index 81066c9a36648..7481fecbf71d1 100644 --- a/test/src/test/java/hudson/security/TokenBasedRememberMeServices2Test.java +++ b/test/src/test/java/hudson/security/TokenBasedRememberMeServices2Test.java @@ -14,6 +14,7 @@ import com.gargoylesoftware.htmlunit.util.Cookie; import com.gargoylesoftware.htmlunit.xml.XmlPage; import hudson.model.User; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Base64; import java.util.Collections; @@ -336,7 +337,7 @@ private Cookie createRememberMeCookie(TokenBasedRememberMeServices2 tokenService HudsonPrivateSecurityRealm.Details details = user.getProperty(HudsonPrivateSecurityRealm.Details.class); String signatureValue = tokenService.makeTokenSignature(expiryTime, details.getUsername(), details.getPassword()); String tokenValue = user.getId() + ":" + expiryTime + ":" + signatureValue; - String tokenValueBase64 = Base64.getEncoder().encodeToString(tokenValue.getBytes()); + String tokenValueBase64 = Base64.getEncoder().encodeToString(tokenValue.getBytes(StandardCharsets.UTF_8)); return new Cookie(j.getURL().getHost(), tokenService.getCookieName(), tokenValueBase64); } diff --git a/test/src/test/java/hudson/security/WhoAmITest.java b/test/src/test/java/hudson/security/WhoAmITest.java index dae0f6940ac42..39c8517a41b0a 100644 --- a/test/src/test/java/hudson/security/WhoAmITest.java +++ b/test/src/test/java/hudson/security/WhoAmITest.java @@ -79,7 +79,7 @@ public void whoAmI_regular_doesNotProvideSensitiveInformation() throws Exception assertThat(sessionId, not(nullValue())); - // dangerous stuff in Regular Login mode: + // dangerous stuff in Regular Login mode: /* * Details: * org.acegisecurity.ui.WebAuthenticationDetails@12afc: RemoteIpAddress: 127.0.0.1; SessionId: node0gbmv9ly0f3h517eppoupykq6n0 @@ -120,7 +120,7 @@ public void whoAmI_regularApi_doesNotProvideSensitiveInformation() throws Except assertThat(sessionId, not(nullValue())); - // dangerous stuff in Regular Login mode with the api/json call: + // dangerous stuff in Regular Login mode with the api/json call: /* * { * "_class": "hudson.security.WhoAmI", @@ -156,7 +156,7 @@ public void whoAmI_basic_doesNotProvideSensitiveInformation() throws Exception { HtmlPage whoAmIPage = wc.goTo("whoAmI"); String content = whoAmIPage.getWebResponse().getContentAsString(); - // dangerous stuff in Basic mode: + // dangerous stuff in Basic mode: /* * toString: * org.acegisecurity.providers.UsernamePasswordAuthenticationToken@e8fd00a7: Username: [toString()=S3cr3t]; @@ -191,7 +191,7 @@ public void whoAmI_apiToken_doesNotProvideSensitiveInformation() throws Exceptio HtmlPage whoAmIPage = wc.goTo("whoAmI"); String content = whoAmIPage.getWebResponse().getContentAsString(); - // dangerous stuff in API Token mode: + // dangerous stuff in API Token mode: /* * Authorization * Basic dXNlcjoxMTRiNGRmMWNhZTVkNDQ2MjgxZTJkZWEzMDY1NTEyZDBi diff --git a/test/src/test/java/hudson/security/csrf/DefaultCrumbIssuerTest.java b/test/src/test/java/hudson/security/csrf/DefaultCrumbIssuerTest.java index f86ee94a288a5..a837fe0b4343a 100644 --- a/test/src/test/java/hudson/security/csrf/DefaultCrumbIssuerTest.java +++ b/test/src/test/java/hudson/security/csrf/DefaultCrumbIssuerTest.java @@ -42,7 +42,7 @@ * @author dty */ public class DefaultCrumbIssuerTest { - + @Rule public JenkinsRule r = new JenkinsRule(); @Before public void setIssuer() { @@ -74,7 +74,7 @@ public class DefaultCrumbIssuerTest { HtmlPage p = wc.goTo("configure"); wc.removeRequestHeader(HEADER_NAME); - + wc.setThrowExceptionOnFailingStatusCode(false); // The crumb should no longer match if we remove the proxy info Page page = r.submit(p.getFormByName("config")); @@ -144,7 +144,7 @@ public class DefaultCrumbIssuerTest { WebClient wc = r.createWebClient(); String json = wc.goTo("crumbIssuer/api/json", "application/json").getWebResponse().getContentAsString(); JSONObject jsonObject = JSONObject.fromObject(json); - assertEquals(r.jenkins.getCrumbIssuer().getCrumbRequestField(),jsonObject.getString("crumbRequestField")); + assertEquals(r.jenkins.getCrumbIssuer().getCrumbRequestField(), jsonObject.getString("crumbRequestField")); assertTrue(jsonObject.getString("crumb").matches("[0-9a-f]+")); wc.assertFails("crumbIssuer/api/json?jsonp=hack", HttpURLConnection.HTTP_FORBIDDEN); } @@ -156,7 +156,7 @@ public class DefaultCrumbIssuerTest { .withThrowExceptionOnFailingStatusCode(false); Page page = wc.goTo("quietDown"); - assertEquals("expect HTTP 405 method not allowed", + assertEquals("expect HTTP 405 method not allowed", HttpURLConnection.HTTP_BAD_METHOD, page.getWebResponse().getStatusCode()); diff --git a/test/src/test/java/hudson/slaves/AgentInboundUrlTest.java b/test/src/test/java/hudson/slaves/AgentInboundUrlTest.java index 3c60c4d84ac88..f4836b871f93a 100644 --- a/test/src/test/java/hudson/slaves/AgentInboundUrlTest.java +++ b/test/src/test/java/hudson/slaves/AgentInboundUrlTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.slaves; import static org.junit.Assert.assertEquals; diff --git a/test/src/test/java/hudson/slaves/EnvironmentVariableNodePropertyTest.java b/test/src/test/java/hudson/slaves/EnvironmentVariableNodePropertyTest.java index 6b2cc338b3e86..6acf60e2480b5 100644 --- a/test/src/test/java/hudson/slaves/EnvironmentVariableNodePropertyTest.java +++ b/test/src/test/java/hudson/slaves/EnvironmentVariableNodePropertyTest.java @@ -8,7 +8,6 @@ import hudson.model.FreeStyleProject; import hudson.model.Node; import hudson.model.ParametersDefinitionProperty; -import hudson.model.Result; import hudson.model.StringParameterDefinition; import java.io.IOException; import java.util.Collections; @@ -30,150 +29,147 @@ */ public class EnvironmentVariableNodePropertyTest { - @ClassRule - public static BuildWatcher buildWatcher = new BuildWatcher(); - - @Rule - public JenkinsRule j = new JenkinsRule(); - - private DumbSlave agent; - private FreeStyleProject project; - - /** - * Agent properties are available - */ - @Test - public void testAgentPropertyOnAgent() throws Exception { - setVariables(agent, new EnvironmentVariablesNodeProperty.Entry("KEY", "agentValue")); - Map envVars = executeBuild(agent); - assertEquals("agentValue", envVars.get("KEY")); - } - - /** - * Built-in node properties are available - */ - @Test - public void testControllerPropertyOnBuiltInNode() throws Exception { + @ClassRule + public static BuildWatcher buildWatcher = new BuildWatcher(); + + @Rule + public JenkinsRule j = new JenkinsRule(); + + private DumbSlave agent; + private FreeStyleProject project; + + /** + * Agent properties are available + */ + @Test + public void testAgentPropertyOnAgent() throws Exception { + setVariables(agent, new EnvironmentVariablesNodeProperty.Entry("KEY", "agentValue")); + Map envVars = executeBuild(agent); + assertEquals("agentValue", envVars.get("KEY")); + } + + /** + * Built-in node properties are available + */ + @Test + public void testControllerPropertyOnBuiltInNode() throws Exception { j.jenkins.getGlobalNodeProperties().replaceBy( Collections.singleton(new EnvironmentVariablesNodeProperty( new EnvironmentVariablesNodeProperty.Entry("KEY", "globalValue")))); - Map envVars = executeBuild(j.jenkins); + Map envVars = executeBuild(j.jenkins); - assertEquals("globalValue", envVars.get("KEY")); - } + assertEquals("globalValue", envVars.get("KEY")); + } - /** - * Both agent and controller properties are available, but agent properties have priority - */ - @Test - public void testAgentAndControllerPropertyOnAgent() throws Exception { + /** + * Both agent and controller properties are available, but agent properties have priority + */ + @Test + public void testAgentAndControllerPropertyOnAgent() throws Exception { j.jenkins.getGlobalNodeProperties().replaceBy( Collections.singleton(new EnvironmentVariablesNodeProperty( new EnvironmentVariablesNodeProperty.Entry("KEY", "globalValue")))); - setVariables(agent, new EnvironmentVariablesNodeProperty.Entry("KEY", "agentValue")); - - Map envVars = executeBuild(agent); - - assertEquals("agentValue", envVars.get("KEY")); - } - - /** - * Agent and controller properties and parameters are available. - * Priority: parameters > agent > controller - */ - @Test - // TODO(terminology) is this correct? This sets a built-in node property, not a global property - public void testAgentAndBuiltInNodePropertyAndParameterOnAgent() - throws Exception { - ParametersDefinitionProperty pdp = new ParametersDefinitionProperty( - new StringParameterDefinition("KEY", "parameterValue")); - project.addProperty(pdp); - - setVariables(j.jenkins, new EnvironmentVariablesNodeProperty.Entry("KEY", "builtInNodeValue")); - setVariables(agent, new EnvironmentVariablesNodeProperty.Entry("KEY", "agentValue")); - - Map envVars = executeBuild(agent); - - assertEquals("parameterValue", envVars.get("KEY")); - } - - @Test - public void testVariableResolving() throws Exception { + setVariables(agent, new EnvironmentVariablesNodeProperty.Entry("KEY", "agentValue")); + + Map envVars = executeBuild(agent); + + assertEquals("agentValue", envVars.get("KEY")); + } + + /** + * Agent and controller properties and parameters are available. + * Priority: parameters > agent > controller + */ + @Test + // TODO(terminology) is this correct? This sets a built-in node property, not a global property + public void testAgentAndBuiltInNodePropertyAndParameterOnAgent() + throws Exception { + ParametersDefinitionProperty pdp = new ParametersDefinitionProperty( + new StringParameterDefinition("KEY", "parameterValue")); + project.addProperty(pdp); + + setVariables(j.jenkins, new EnvironmentVariablesNodeProperty.Entry("KEY", "builtInNodeValue")); + setVariables(agent, new EnvironmentVariablesNodeProperty.Entry("KEY", "agentValue")); + + Map envVars = executeBuild(agent); + + assertEquals("parameterValue", envVars.get("KEY")); + } + + @Test + public void testVariableResolving() throws Exception { j.jenkins.getGlobalNodeProperties().replaceBy( Collections.singleton(new EnvironmentVariablesNodeProperty( new EnvironmentVariablesNodeProperty.Entry("KEY1", "value"), new EnvironmentVariablesNodeProperty.Entry("KEY2", "$KEY1")))); - Map envVars = executeBuild(j.jenkins); - assertEquals("value", envVars.get("KEY1")); - assertEquals("value", envVars.get("KEY2")); - } - - @Test - public void testFormRoundTripForController() throws Exception { + Map envVars = executeBuild(j.jenkins); + assertEquals("value", envVars.get("KEY1")); + assertEquals("value", envVars.get("KEY2")); + } + + @Test + public void testFormRoundTripForController() throws Exception { j.jenkins.getGlobalNodeProperties().replaceBy( Collections.singleton(new EnvironmentVariablesNodeProperty( new EnvironmentVariablesNodeProperty.Entry("KEY", "value")))); - - WebClient webClient = j.createWebClient(); - HtmlPage page = webClient.getPage(j.jenkins, "configure"); - HtmlForm form = page.getFormByName("config"); - j.submit(form); - - assertEquals(1, j.jenkins.getGlobalNodeProperties().toList().size()); - - EnvironmentVariablesNodeProperty prop = j.jenkins.getGlobalNodeProperties().get(EnvironmentVariablesNodeProperty.class); - assertEquals(1, prop.getEnvVars().size()); - assertEquals("value", prop.getEnvVars().get("KEY")); - } - - @Test - public void testFormRoundTripForAgent() throws Exception { - setVariables(agent, new EnvironmentVariablesNodeProperty.Entry("KEY", "value")); - - WebClient webClient = j.createWebClient(); - HtmlPage page = webClient.getPage(agent, "configure"); - HtmlForm form = page.getFormByName("config"); - j.submit(form); - - assertEquals(1, agent.getNodeProperties().toList().size()); - - EnvironmentVariablesNodeProperty prop = agent.getNodeProperties().get(EnvironmentVariablesNodeProperty.class); - assertEquals(1, prop.getEnvVars().size()); - assertEquals("value", prop.getEnvVars().get("KEY")); - } - - // //////////////////////// setup ////////////////////////////////////////// - - @Before - public void setUp() throws Exception { - agent = j.createSlave(); - project = j.createFreeStyleProject(); - } - - // ////////////////////// helper methods ///////////////////////////////// - - private void setVariables(Node node, EnvironmentVariablesNodeProperty.Entry... entries) throws IOException { - node.getNodeProperties().replaceBy( - Collections.singleton(new EnvironmentVariablesNodeProperty( - entries))); - - } - - /** - * Launches project on this node, waits for the result, and returns the environment that is used - */ - private Map executeBuild(Node node) throws Exception { - CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); - - project.getBuildersList().add(builder); - project.setAssignedLabel(node.getSelfLabel()); - - // use a timeout so we don't wait infinitely in case of failure - FreeStyleBuild build = project.scheduleBuild2(0).get(/*10, TimeUnit.SECONDS*/); - - assertEquals(Result.SUCCESS, build.getResult()); - - return builder.getEnvVars(); - } + + WebClient webClient = j.createWebClient(); + HtmlPage page = webClient.getPage(j.jenkins, "configure"); + HtmlForm form = page.getFormByName("config"); + j.submit(form); + + assertEquals(1, j.jenkins.getGlobalNodeProperties().toList().size()); + + EnvironmentVariablesNodeProperty prop = j.jenkins.getGlobalNodeProperties().get(EnvironmentVariablesNodeProperty.class); + assertEquals(1, prop.getEnvVars().size()); + assertEquals("value", prop.getEnvVars().get("KEY")); + } + + @Test + public void testFormRoundTripForAgent() throws Exception { + setVariables(agent, new EnvironmentVariablesNodeProperty.Entry("KEY", "value")); + + WebClient webClient = j.createWebClient(); + HtmlPage page = webClient.getPage(agent, "configure"); + HtmlForm form = page.getFormByName("config"); + j.submit(form); + + assertEquals(1, agent.getNodeProperties().toList().size()); + + EnvironmentVariablesNodeProperty prop = agent.getNodeProperties().get(EnvironmentVariablesNodeProperty.class); + assertEquals(1, prop.getEnvVars().size()); + assertEquals("value", prop.getEnvVars().get("KEY")); + } + + // //////////////////////// setup ////////////////////////////////////////// + + @Before + public void setUp() throws Exception { + agent = j.createSlave(); + project = j.createFreeStyleProject(); + } + + // ////////////////////// helper methods ///////////////////////////////// + + private void setVariables(Node node, EnvironmentVariablesNodeProperty.Entry... entries) throws IOException { + node.getNodeProperties().replaceBy( + Collections.singleton(new EnvironmentVariablesNodeProperty( + entries))); + + } + + /** + * Launches project on this node, waits for the result, and returns the environment that is used + */ + private Map executeBuild(Node node) throws Exception { + CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); + + project.getBuildersList().add(builder); + project.setAssignedLabel(node.getSelfLabel()); + + FreeStyleBuild build = j.buildAndAssertSuccess(project); + + return builder.getEnvVars(); + } } diff --git a/test/src/test/java/hudson/slaves/JNLPLauncherTest.java b/test/src/test/java/hudson/slaves/JNLPLauncherTest.java index 81ce8c714a77d..f10e320607244 100644 --- a/test/src/test/java/hudson/slaves/JNLPLauncherTest.java +++ b/test/src/test/java/hudson/slaves/JNLPLauncherTest.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.slaves; import static org.hamcrest.CoreMatchers.is; @@ -69,13 +70,13 @@ @Category(SmokeTest.class) public class JNLPLauncherTest { @Rule public JenkinsRule j = new JenkinsRule(); - + @Rule public TemporaryFolder tmpDir = new TemporaryFolder(); @Rule public LoggerRule logging = new LoggerRule().record(Slave.class, Level.FINE); /** - * Starts a JNLP agent and makes sure it successfully connects to Jenkins. + * Starts a JNLP agent and makes sure it successfully connects to Jenkins. */ @Test public void testLaunch() throws Exception { @@ -84,16 +85,16 @@ public void testLaunch() throws Exception { Computer c = addTestAgent(false); launchJnlpAndVerify(c, buildJnlpArgs(c)); } - + /** - * Starts a JNLP agent and makes sure it successfully connects to Jenkins. + * Starts a JNLP agent and makes sure it successfully connects to Jenkins. */ @Test @Issue("JENKINS-39370") public void testLaunchWithWorkDir() throws Exception { Assume.assumeFalse("Skipping JNLPLauncherTest.testLaunch because we are running headless", GraphicsEnvironment.isHeadless()); File workDir = tmpDir.newFolder("workDir"); - + Computer c = addTestAgent(false); launchJnlpAndVerify(c, buildJnlpArgs(c).add("-workDir", workDir.getAbsolutePath())); assertTrue("Remoting work dir should have been created", new File(workDir, "remoting").exists()); @@ -106,49 +107,49 @@ public void testLaunchWithWorkDir() throws Exception { @Test public void testHeadlessLaunch() throws Exception { Computer c = addTestAgent(false); - launchJnlpAndVerify(c, buildJnlpArgs(c).add("-arg","-headless")); + launchJnlpAndVerify(c, buildJnlpArgs(c).add("-arg", "-headless")); // make sure that onOffline gets called just the right number of times assertEquals(1, ComputerListener.all().get(ListenerImpl.class).offlined); } - + @Test @Issue("JENKINS-44112") public void testHeadlessLaunchWithWorkDir() throws Exception { Assume.assumeFalse("Skipping JNLPLauncherTest.testLaunch because we are running headless", GraphicsEnvironment.isHeadless()); - + Computer c = addTestAgent(true); - launchJnlpAndVerify(c, buildJnlpArgs(c).add("-arg","-headless")); + launchJnlpAndVerify(c, buildJnlpArgs(c).add("-arg", "-headless")); assertEquals(1, ComputerListener.all().get(ListenerImpl.class).offlined); } - + @Test @Issue("JENKINS-39370") public void testHeadlessLaunchWithCustomWorkDir() throws Exception { Assume.assumeFalse("Skipping JNLPLauncherTest.testLaunch because we are running headless", GraphicsEnvironment.isHeadless()); File workDir = tmpDir.newFolder("workDir"); - + Computer c = addTestAgent(false); - launchJnlpAndVerify(c, buildJnlpArgs(c).add("-arg","-headless", "-workDir", workDir.getAbsolutePath())); + launchJnlpAndVerify(c, buildJnlpArgs(c).add("-arg", "-headless", "-workDir", workDir.getAbsolutePath())); assertEquals(1, ComputerListener.all().get(ListenerImpl.class).offlined); } - + @Test @LocalData @Issue("JENKINS-44112") public void testNoWorkDirMigration() { Computer computer = j.jenkins.getComputer("Foo"); assertThat(computer, instanceOf(SlaveComputer.class)); - - SlaveComputer c = (SlaveComputer)computer; + + SlaveComputer c = (SlaveComputer) computer; ComputerLauncher launcher = c.getLauncher(); assertThat(launcher, instanceOf(JNLPLauncher.class)); - JNLPLauncher jnlpLauncher = (JNLPLauncher)launcher; - assertNotNull("Work Dir Settings should be defined", + JNLPLauncher jnlpLauncher = (JNLPLauncher) launcher; + assertNotNull("Work Dir Settings should be defined", jnlpLauncher.getWorkDirSettings()); - assertTrue("Work directory should be disabled for the migrated agent", + assertTrue("Work directory should be disabled for the migrated agent", jnlpLauncher.getWorkDirSettings().isDisabled()); } - + @Test @Issue("JENKINS-44112") @SuppressWarnings("deprecation") @@ -207,20 +208,20 @@ private static class ComputerLauncherFilterImpl extends ComputerLauncherFilter { private ArgumentListBuilder buildJnlpArgs(Computer c) throws Exception { ArgumentListBuilder args = new ArgumentListBuilder(); - args.add(new File(new File(System.getProperty("java.home")),"bin/java").getPath(),"-jar"); + args.add(new File(new File(System.getProperty("java.home")), "bin/java").getPath(), "-jar"); args.add(Which.jarFile(JNLPRuntime.class).getAbsolutePath()); - args.add("-headless","-basedir"); + args.add("-headless", "-basedir"); args.add(j.createTmpDir()); - args.add("-nosecurity","-jnlp", j.getURL() + "computer/"+c.getName()+"/jenkins-agent.jnlp"); - + args.add("-nosecurity", "-jnlp", j.getURL() + "computer/" + c.getName() + "/jenkins-agent.jnlp"); + if (c instanceof SlaveComputer) { - SlaveComputer sc = (SlaveComputer)c; + SlaveComputer sc = (SlaveComputer) c; ComputerLauncher launcher = sc.getLauncher(); if (launcher instanceof JNLPLauncher) { - args.add(((JNLPLauncher)launcher).getWorkDirSettings().toCommandLineArgs(sc)); + args.add(((JNLPLauncher) launcher).getWorkDirSettings().toCommandLineArgs(sc)); } } - + return args; } @@ -232,9 +233,9 @@ private void launchJnlpAndVerify(Computer c, ArgumentListBuilder args) throws Ex try { // verify that the connection is established, up to 20 secs - for( int i=0; i<200; i++ ) { + for (int i = 0; i < 200; i++) { Thread.sleep(100); - if(!c.isOffline()) + if (!c.isOffline()) break; } @@ -267,7 +268,7 @@ private Computer addTestAgent(boolean enableWorkDir) throws Exception { private Computer addTestAgent(ComputerLauncher launcher) throws Exception { List agents = new ArrayList<>(j.jenkins.getNodes()); File dir = Util.createTempDir(); - agents.add(new DumbSlave("test","dummy",dir.getAbsolutePath(),"1", Mode.NORMAL, "", + agents.add(new DumbSlave("test", "dummy", dir.getAbsolutePath(), "1", Mode.NORMAL, "", launcher, RetentionStrategy.INSTANCE, new ArrayList<>())); j.jenkins.setNodes(agents); Computer c = j.jenkins.getComputer("test"); @@ -275,7 +276,7 @@ private Computer addTestAgent(ComputerLauncher launcher) throws Exception { return c; } - private static class NoopTask extends SlaveToMasterCallable { + private static class NoopTask extends SlaveToMasterCallable { @Override public String call() { return "done"; @@ -294,7 +295,7 @@ public void testConfigRoundtrip() throws Exception { ((JNLPLauncher) s.getLauncher()).setWorkDirSettings(custom); HtmlPage p = j.createWebClient().getPage(s, "configure"); j.submit(p.getFormByName("config")); - j.assertEqualBeans(original,s.getLauncher(),"tunnel,vmargs"); + j.assertEqualBeans(original, s.getLauncher(), "tunnel,vmargs"); j.assertEqualDataBoundBeans(((JNLPLauncher) s.getLauncher()).getWorkDirSettings(), custom); } diff --git a/test/src/test/java/hudson/slaves/NodeCanTakeTaskTest.java b/test/src/test/java/hudson/slaves/NodeCanTakeTaskTest.java index c2dd0d109f2ef..4435ee664a8ea 100644 --- a/test/src/test/java/hudson/slaves/NodeCanTakeTaskTest.java +++ b/test/src/test/java/hudson/slaves/NodeCanTakeTaskTest.java @@ -37,7 +37,6 @@ import hudson.model.Slave; import hudson.model.queue.CauseOfBlockage; import java.util.List; -import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.Rule; @@ -60,8 +59,7 @@ public void takeBlockedByProperty() throws Exception { FreeStyleProject project = r.createFreeStyleProject(); // First, attempt to run our project before adding the property - Future build = project.scheduleBuild2(0); - r.assertBuildStatus(Result.SUCCESS, build.get(20, TimeUnit.SECONDS)); + r.buildAndAssertSuccess(project); // Add the build-blocker property and try again slave.getNodeProperties().add(new RejectAllTasksProperty()); @@ -96,13 +94,15 @@ public void becauseNodeIsBusy() throws Exception { project.setAssignedNode(slave); project.setConcurrentBuild(true); project.getBuildersList().add(new SleepBuilder(Long.MAX_VALUE)); - project.scheduleBuild2(0).waitForStart(); // consume the one executor + FreeStyleBuild build = project.scheduleBuild2(0).waitForStart(); // consume the one executor project.scheduleBuild2(0); // now try to reschedule Queue.Item item; while ((item = r.jenkins.getQueue().getItem(project)) == null || !item.isBuildable()) { Thread.sleep(100); } assertEquals(hudson.model.Messages.Queue_WaitingForNextAvailableExecutorOn(slave.getDisplayName()), item.getWhy()); + build.doStop(); + r.assertBuildStatus(Result.ABORTED, r.waitForCompletion(build)); } } diff --git a/test/src/test/java/hudson/slaves/NodeParallelTest.java b/test/src/test/java/hudson/slaves/NodeParallelTest.java index 0b74d5b106cb0..0a75ec220c90a 100644 --- a/test/src/test/java/hudson/slaves/NodeParallelTest.java +++ b/test/src/test/java/hudson/slaves/NodeParallelTest.java @@ -37,7 +37,7 @@ public void createNodesWithParallelThreads() throws InterruptedException, Execut LOGGER.log(Level.INFO, "Creating slave " + i); // JenkinsRule sync on Jenkins singleton, so this doesn't work // r.createSlave(); - DumbSlave agent = new DumbSlave("agent-"+i, "/tmp", new JNLPLauncher(true)); + DumbSlave agent = new DumbSlave("agent-" + i, "/tmp", new JNLPLauncher(true)); r.jenkins.addNode(agent); agent.setNodeProperties(Collections.singletonList(new EnvironmentVariablesNodeProperty(new EnvironmentVariablesNodeProperty.Entry("foo", "" + i)))); return null; diff --git a/test/src/test/java/hudson/slaves/NodePropertyTest.java b/test/src/test/java/hudson/slaves/NodePropertyTest.java index 913757f44fb26..aa9e30d3e6618 100644 --- a/test/src/test/java/hudson/slaves/NodePropertyTest.java +++ b/test/src/test/java/hudson/slaves/NodePropertyTest.java @@ -41,10 +41,10 @@ public void invisibleProperty() throws Exception { assertFalse(before.reconfigured); DumbSlave s2 = j.configRoundtrip(s); - assertNotSame(s,s2); + assertNotSame(s, s2); InvisibleProperty after = s2.getNodeProperties().get(InvisibleProperty.class); - assertSame(before,after); + assertSame(before, after); assertTrue(after.reconfigured); } @@ -65,16 +65,16 @@ public static class DescriptorImpl extends NodePropertyDescriptor {} public void basicConfigRoundtrip() throws Exception { DumbSlave s = j.createSlave(); HtmlForm f = j.createWebClient().goTo("computer/" + s.getNodeName() + "/configure").getFormByName("config"); - ((HtmlLabel)DomNodeUtil.selectSingleNode(f, ".//LABEL[text()='PropertyImpl']")).click(); + ((HtmlLabel) DomNodeUtil.selectSingleNode(f, ".//LABEL[text()='PropertyImpl']")).click(); j.submit(f); PropertyImpl p = j.jenkins.getNode(s.getNodeName()).getNodeProperties().get(PropertyImpl.class); - assertEquals("Duke",p.name); + assertEquals("Duke", p.name); p.name = "Kohsuke"; j.configRoundtrip(s); PropertyImpl p2 = j.jenkins.getNode(s.getNodeName()).getNodeProperties().get(PropertyImpl.class); - assertNotSame(p,p2); + assertNotSame(p, p2); j.assertEqualDataBoundBeans(p, p2); } diff --git a/test/src/test/java/hudson/slaves/NodeProvisionerTest.java b/test/src/test/java/hudson/slaves/NodeProvisionerTest.java index 5e3b900451fa3..b1be8dfaa50e0 100644 --- a/test/src/test/java/hudson/slaves/NodeProvisionerTest.java +++ b/test/src/test/java/hudson/slaves/NodeProvisionerTest.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,30 +21,40 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.slaves; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assume.assumeFalse; import hudson.BulkChange; +import hudson.Functions; import hudson.Launcher; import hudson.model.AbstractBuild; import hudson.model.BuildListener; +import hudson.model.Computer; +import hudson.model.Descriptor; import hudson.model.FreeStyleBuild; import hudson.model.FreeStyleProject; import hudson.model.Label; +import hudson.model.Node; import hudson.model.Result; +import hudson.model.queue.QueueTaskFuture; import hudson.tasks.Builder; import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.Rule; import org.junit.Test; +import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.SleepBuilder; @@ -62,7 +72,7 @@ public class NodeProvisionerTest { */ static class Latch { /** Initial value */ - public final CountDownLatch counter; + public final transient CountDownLatch counter; private final int init; Latch(int n) { @@ -104,7 +114,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen f.get(30, TimeUnit.SECONDS); // if it's taking too long, abort. // since there's only one job, we expect there to be just one slave - assertEquals(1,cloud.numProvisioned); + assertEquals(1, cloud.numProvisioned); } } @@ -113,6 +123,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen */ // TODO fragile @Test public void loadSpike() throws Exception { + assumeFalse("TODO: Windows container agents do not have enough resources to run this test", Functions.isWindows() && System.getenv("CI") != null); try (BulkChange bc = new BulkChange(r.jenkins)) { DummyCloudImpl cloud = initHudson(0); @@ -120,7 +131,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen // the time it takes to complete a job is eternally long compared to the time it takes to launch // a new slave, so in this scenario we end up allocating 5 slaves for 5 jobs. - assertEquals(5,cloud.numProvisioned); + assertEquals(5, cloud.numProvisioned); } } @@ -129,6 +140,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen */ // TODO fragile @Test public void baselineSlaveUsage() throws Exception { + assumeFalse("TODO: Windows container agents do not have enough resources to run this test", Functions.isWindows() && System.getenv("CI") != null); try (BulkChange bc = new BulkChange(r.jenkins)) { DummyCloudImpl cloud = initHudson(0); // add agents statically upfront @@ -138,7 +150,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen verifySuccessfulCompletion(buildAll(create5SlowJobs(new Latch(5)))); // we should have used two static slaves, thus only 3 slaves should have been provisioned - assertEquals(3,cloud.numProvisioned); + assertEquals(3, cloud.numProvisioned); } } @@ -147,6 +159,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen */ // TODO fragile @Test public void labels() throws Exception { + assumeFalse("TODO: Windows container agents do not have enough resources to run this test", Functions.isWindows() && System.getenv("CI") != null); try (BulkChange bc = new BulkChange(r.jenkins)) { DummyCloudImpl cloud = initHudson(0); Label blue = r.jenkins.getLabel("blue"); @@ -168,7 +181,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen verifySuccessfulCompletion(buildAll(redJobs)); // cloud should only give us 5 nodes for 5 red jobs - assertEquals(5,cloud.numProvisioned); + assertEquals(5, cloud.numProvisioned); // and all blue jobs should be still stuck in the queue for (Future bb : blueBuilds) @@ -176,6 +189,84 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen } } + @Issue("JENKINS-67635") + @Test + public void testJobWithCloudLabelExpressionProvisionsOnlyOneAgent() throws Exception { + DummyCloudImpl3 cloud1 = new DummyCloudImpl3(r); + DummyCloudImpl3 cloud2 = new DummyCloudImpl3(r); + + cloud1.label = Label.get("cloud-1-label"); + cloud2.label = Label.get("cloud-2-label"); + + r.jenkins.clouds.add(cloud1); + r.jenkins.clouds.add(cloud2); + + FreeStyleProject p = r.createFreeStyleProject(); + p.setAssignedLabel(Label.parseExpression("cloud-1-label || cloud-2-label")); + + QueueTaskFuture futureBuild = p.scheduleBuild2(0); + futureBuild.waitForStart(); + r.assertBuildStatus(Result.SUCCESS, futureBuild); + + assertEquals(1, cloud1.numProvisioned); + assertEquals(0, cloud2.numProvisioned); + } + + private static class DummyCloudImpl3 extends Cloud { + private final transient JenkinsRule caller; + public int numProvisioned; + private Label label; + + DummyCloudImpl3() { + super("DummyCloudImpl3"); + this.caller = null; + } + + DummyCloudImpl3(JenkinsRule caller) { + super("DummyCloudImpl3"); + this.caller = caller; + } + + @Override + public Collection provision(Label label, int excessWorkload) { + List r = new ArrayList<>(); + if (! this.canProvision(label)) + return r; + + while (excessWorkload > 0) { + numProvisioned++; + Future f = Computer.threadPoolForRemoting.submit(new DummyCloudImpl3.Launcher()); + r.add(new NodeProvisioner.PlannedNode(name + " #" + numProvisioned, f, 1)); + excessWorkload -= 1; + } + return r; + } + + @Override + public boolean canProvision(Label label) { + return label.matches(this.label.listAtoms()); + } + + private final class Launcher implements Callable { + private volatile Computer computer; + + private Launcher() {} + + @Override + public Node call() throws Exception { + DumbSlave slave = caller.createSlave(label); + computer = slave.toComputer(); + computer.connect(false).get(); + return slave; + } + } + + @Override + public Descriptor getDescriptor() { + throw new UnsupportedOperationException(); + } + } + private FreeStyleProject createJob(Builder builder) throws IOException { FreeStyleProject p = r.createFreeStyleProject(); @@ -197,7 +288,7 @@ private DummyCloudImpl initHudson(int delay) throws IOException { private List create5SlowJobs(Latch l) throws IOException { List jobs = new ArrayList<>(); - for( int i=0; i create5SlowJobs(Latch l) throws IOException { * Builds all the given projects at once. */ private List> buildAll(List jobs) { - System.out.println("Scheduling builds for "+jobs.size()+" jobs"); + System.out.println("Scheduling builds for " + jobs.size() + " jobs"); List> builds = new ArrayList<>(); for (FreeStyleProject job : jobs) builds.add(job.scheduleBuild2(0)); diff --git a/test/src/test/java/hudson/slaves/PingThreadTest.java b/test/src/test/java/hudson/slaves/PingThreadTest.java index d283f15bca388..4c329e2c29182 100644 --- a/test/src/test/java/hudson/slaves/PingThreadTest.java +++ b/test/src/test/java/hudson/slaves/PingThreadTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.slaves; import static org.junit.Assert.assertEquals; @@ -61,7 +62,7 @@ public void failedPingThreadResetsComputerChannel() throws Exception { String pid = channel.call(new GetPid()); PingThread pingThread = null; - for (Thread it: Thread.getAllStackTraces().keySet()) { + for (Thread it : Thread.getAllStackTraces().keySet()) { if (it instanceof PingThread && it.getName().endsWith(channel.toString())) { pingThread = (PingThread) it; } diff --git a/test/src/test/java/hudson/slaves/SlaveComputerTest.java b/test/src/test/java/hudson/slaves/SlaveComputerTest.java index 1db74056ce1ed..301f408dc00a8 100644 --- a/test/src/test/java/hudson/slaves/SlaveComputerTest.java +++ b/test/src/test/java/hudson/slaves/SlaveComputerTest.java @@ -21,13 +21,16 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.slaves; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.containsString; +import static org.junit.Assume.assumeFalse; import com.gargoylesoftware.htmlunit.WebResponse; +import hudson.Functions; import hudson.model.Computer; import hudson.model.Node; import hudson.model.TaskListener; @@ -70,7 +73,7 @@ public void testGetAbsoluteRemotePath() throws Exception { j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); j.jenkins.setAuthorizationStrategy(authStrategy); - try(ACLContext context = ACL.as(User.getById(userAlice, true))) { + try (ACLContext context = ACL.as(User.getById(userAlice, true))) { path = nodeA.getComputer().getAbsoluteRemotePath(); Assert.assertNull(path); Assert.assertNull(getRemoteFS(nodeA, userAlice)); @@ -79,7 +82,7 @@ public void testGetAbsoluteRemotePath() throws Exception { //with auth String userBob = "bob"; authStrategy.grant(Computer.CONNECT, Jenkins.READ).everywhere().to(userBob); - try(ACLContext context = ACL.as(User.getById(userBob, true))) { + try (ACLContext context = ACL.as(User.getById(userBob, true))) { path = nodeA.getComputer().getAbsoluteRemotePath(); Assert.assertNotNull(path); Assert.assertNotNull(getRemoteFS(nodeA, userBob)); @@ -143,8 +146,8 @@ public void onOnline(Computer c, TaskListener listener) { @Test @Issue("JENKINS-57111") - public void startupShouldFailOnErrorOnlineListener() throws Exception { + assumeFalse("TODO: Windows container agents do not have enough resources to run this test", Functions.isWindows() && System.getenv("CI") != null); DumbSlave nodeA = j.createSlave(); Assert.assertTrue(nodeA.getComputer() instanceof SlaveComputer); int retries = 10; @@ -186,7 +189,7 @@ public void onOnline(Computer c, TaskListener listener) { */ private String getRemoteFS(Node node, String user) throws Exception { JenkinsRule.WebClient wc = j.createWebClient(); - if(user != null) { + if (user != null) { wc.login(user); } @@ -195,7 +198,7 @@ private String getRemoteFS(Node node, String user) throws Exception { JSONObject json = JSONObject.fromObject(response.getContentAsString()); Object pathObj = json.get("absoluteRemotePath"); - if(pathObj instanceof JSONNull) { + if (pathObj instanceof JSONNull) { return null; // the value is null in here } else { return pathObj.toString(); diff --git a/test/src/test/java/hudson/tasks/ArtifactArchiverTest.java b/test/src/test/java/hudson/tasks/ArtifactArchiverTest.java index 852f3a31c8eda..282efe49a70dd 100644 --- a/test/src/test/java/hudson/tasks/ArtifactArchiverTest.java +++ b/test/src/test/java/hudson/tasks/ArtifactArchiverTest.java @@ -24,7 +24,6 @@ package hudson.tasks; -import static hudson.tasks.LogRotatorTest.build; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.lessThan; import static org.junit.Assert.assertEquals; @@ -83,7 +82,7 @@ public void testNoneCompression() throws Exception { final FreeStyleProject project = j.createFreeStyleProject(); project.getBuildersList().add(new CreateArtifact()); project.getPublishersList().add(new ArtifactArchiver("f")); - assertEquals(Result.SUCCESS, build(project)); + j.buildAndAssertSuccess(project); assertTrue(project.getBuildByNumber(1).getHasArtifacts()); } finally { StandardArtifactManager.TAR_COMPRESSION = prevCompression; @@ -107,7 +106,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen return true; } })); - assertEquals(Result.SUCCESS, build(project)); // #1 + j.buildAndAssertSuccess(project); // #1 File artifacts = project.getBuildByNumber(1).getArtifactsDir(); File[] kids = artifacts.listFiles(); assertEquals(1, kids.length); @@ -128,7 +127,7 @@ public void testAllowEmptyArchive() throws Exception { assertFalse(aa.getAllowEmptyArchive()); aa.setAllowEmptyArchive(true); project.getPublishersList().replaceBy(Collections.singleton(aa)); - assertEquals("(no artifacts)", Result.SUCCESS, build(project)); + j.buildAndAssertSuccess(project); assertFalse(project.getBuildByNumber(1).getHasArtifacts()); } @@ -136,7 +135,7 @@ public void testAllowEmptyArchive() throws Exception { @Test public void symlinks() throws Exception { FreeStyleProject p = j.createFreeStyleProject(); p.getBuildersList().add(new TestBuilder() { - @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { + @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { FilePath ws = build.getWorkspace(); if (ws == null) { return false; @@ -151,7 +150,7 @@ public void testAllowEmptyArchive() throws Exception { ArtifactArchiver aa = new ArtifactArchiver("dir/lodge"); aa.setAllowEmptyArchive(true); p.getPublishersList().add(aa); - FreeStyleBuild b = j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + FreeStyleBuild b = j.buildAndAssertSuccess(p); FilePath ws = b.getWorkspace(); assertNotNull(ws); assumeTrue("May not be testable on Windows:\n" + JenkinsRule.getLog(b), ws.child("dir/lodge").exists()); @@ -169,7 +168,7 @@ public void testAllowEmptyArchive() throws Exception { @Test public void notFollowSymlinks() throws Exception { FreeStyleProject p = j.createFreeStyleProject(); p.getBuildersList().add(new TestBuilder() { - @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { + @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { FilePath ws = build.getWorkspace(); if (ws == null) { return false; @@ -186,7 +185,7 @@ public void testAllowEmptyArchive() throws Exception { aa.setFollowSymlinks(false); aa.setAllowEmptyArchive(true); p.getPublishersList().add(aa); - FreeStyleBuild b = j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + FreeStyleBuild b = j.buildAndAssertSuccess(p); FilePath ws = b.getWorkspace(); assertNotNull(ws); assumeTrue("May not be testable on Windows:\n" + JenkinsRule.getLog(b), ws.child("dir/lodge").exists()); @@ -200,7 +199,7 @@ public void testAllowEmptyArchive() throws Exception { FreeStyleProject p = j.jenkins.getItemByFullName(Functions.isWindows() ? "sample-windows" : "sample", FreeStyleProject.class); FreeStyleBuild b = p.scheduleBuild2(0).get(); - assumeTrue("May not be testable on Windows:\n" + JenkinsRule.getLog(b),b.getResult()==Result.SUCCESS); + assumeTrue("May not be testable on Windows:\n" + JenkinsRule.getLog(b), b.getResult() == Result.SUCCESS); FilePath ws = b.getWorkspace(); assertNotNull(ws); List artifacts = b.getArtifacts(); @@ -217,7 +216,7 @@ public void testAllowEmptyArchive() throws Exception { @Test public void outsideSymlinks() throws Exception { final FreeStyleProject p = j.createFreeStyleProject(); p.getBuildersList().add(new TestBuilder() { - @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { + @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { FilePath ws = build.getWorkspace(); if (ws == null) { return false; @@ -227,7 +226,7 @@ public void testAllowEmptyArchive() throws Exception { } }); p.getPublishersList().add(new ArtifactArchiver("hack", "", false, true)); - FreeStyleBuild b = j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + FreeStyleBuild b = j.buildAndAssertSuccess(p); List artifacts = b.getArtifacts(); assertEquals(1, artifacts.size()); FreeStyleBuild.Artifact artifact = artifacts.get(0); @@ -243,7 +242,7 @@ public void testAllowEmptyArchive() throws Exception { static class CreateArtifact extends TestBuilder { @Override - public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { build.getWorkspace().child("f").write("content", "UTF-8"); return true; } @@ -251,7 +250,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListene static class CreateArtifactAndFail extends TestBuilder { @Override - public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { build.getWorkspace().child("f").write("content", "UTF-8"); throw new AbortException("failing the build"); } @@ -264,10 +263,10 @@ public void testArchivingSkippedWhenOnlyIfSuccessfulChecked() throws Exception { ArtifactArchiver aa = new ArtifactArchiver("f"); project.getPublishersList().replaceBy(Collections.singleton(aa)); project.getBuildersList().replaceBy(Collections.singleton(new CreateArtifactAndFail())); - assertEquals(Result.FAILURE, build(project)); + j.buildAndAssertStatus(Result.FAILURE, project); assertTrue(project.getBuildByNumber(1).getHasArtifacts()); aa.setOnlyIfSuccessful(true); - assertEquals(Result.FAILURE, build(project)); + j.buildAndAssertStatus(Result.FAILURE, project); assertTrue(project.getBuildByNumber(1).getHasArtifacts()); assertFalse(project.getBuildByNumber(2).getHasArtifacts()); } @@ -291,7 +290,7 @@ public void configRoundTrip() throws Exception { static class CreateDefaultExcludesArtifact extends TestBuilder { @Override - public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { FilePath dir = build.getWorkspace().child("dir"); FilePath subSvnDir = dir.child(".svn"); subSvnDir.mkdirs(); @@ -315,7 +314,7 @@ public void testDefaultExcludesOn() throws Exception { project.getPublishersList().replaceBy(Collections.singleton(artifactArchiver)); project.getBuildersList().replaceBy(Collections.singleton(new CreateDefaultExcludesArtifact())); - assertEquals(Result.SUCCESS, build(project)); // #1 + j.buildAndAssertSuccess(project); // #1 VirtualFile artifacts = project.getBuildByNumber(1).getArtifactManager().root(); assertFalse(artifacts.child(".svn").child("file").exists()); assertFalse(artifacts.child("dir").child(".svn").child("file").exists()); @@ -332,7 +331,7 @@ public void testDefaultExcludesOff() throws Exception { project.getPublishersList().replaceBy(Collections.singleton(artifactArchiver)); project.getBuildersList().replaceBy(Collections.singleton(new CreateDefaultExcludesArtifact())); - assertEquals(Result.SUCCESS, build(project)); // #1 + j.buildAndAssertSuccess(project); // #1 VirtualFile artifacts = project.getBuildByNumber(1).getArtifactManager().root(); assertTrue(artifacts.child(".svn").child("file").exists()); assertTrue(artifacts.child("dir").child(".svn").child("file").exists()); @@ -387,9 +386,8 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen p.getPublishersList().add(new ArtifactArchiver(FILENAME)); p.setAssignedNode(slave); - FreeStyleBuild build = p.scheduleBuild2(0).get(); + FreeStyleBuild build = j.buildAndAssertStatus(Result.FAILURE, p); assumeFalse(FILENAME + " should not be readable by " + System.getProperty("user.name"), new File(build.getWorkspace().child(FILENAME).getRemote()).canRead()); - j.assertBuildStatus(Result.FAILURE, build); String expectedPath = build.getWorkspace().child(FILENAME).getRemote(); j.assertLogContains("ERROR: Step ‘Archive the artifacts’ failed: java.nio.file.AccessDeniedException: " + expectedPath, build); assertThat("No stacktrace shown", build.getLog(31), Matchers.iterableWithSize(lessThan(30))); @@ -400,7 +398,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen public void lengthOfArtifactIsCorrect_eventForInvalidSymlink() throws Exception { FreeStyleProject p = j.createFreeStyleProject(); p.getBuildersList().add(new TestBuilder() { - @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { + @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { FilePath ws = build.getWorkspace(); if (ws == null) { return false; @@ -416,7 +414,7 @@ public void lengthOfArtifactIsCorrect_eventForInvalidSymlink() throws Exception ArtifactArchiver aa = new ArtifactArchiver("dir/**"); aa.setAllowEmptyArchive(true); p.getPublishersList().add(aa); - FreeStyleBuild b = j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + FreeStyleBuild b = j.buildAndAssertSuccess(p); FilePath ws = b.getWorkspace(); assertNotNull(ws); List artifacts = b.getArtifacts(); diff --git a/test/src/test/java/hudson/tasks/BatchFileTest.java b/test/src/test/java/hudson/tasks/BatchFileTest.java index 08d5232c9799b..a6e9a80fd539d 100644 --- a/test/src/test/java/hudson/tasks/BatchFileTest.java +++ b/test/src/test/java/hudson/tasks/BatchFileTest.java @@ -67,14 +67,14 @@ private void nonZeroErrorlevelShouldMakeBuildUnstable(int exitCode) throws Excep FreeStyleProject p = rule.createFreeStyleProject(); p.getBuildersList().add(createNewBatchTask("", exitCode)); p.setAssignedNode(slave); - rule.assertBuildStatus(Result.UNSTABLE, p.scheduleBuild2(0).get()); + rule.buildAndAssertStatus(Result.UNSTABLE, p); } @Test @Issue("JENKINS-23786") public void windowsNonZeroErrorlevelsShouldMakeBuildUnstable() throws Exception { assumeTrue(Functions.isWindows()); - for( int exitCode: new int [] {Integer.MIN_VALUE, -1, 1, Integer.MAX_VALUE}) { + for (int exitCode : new int [] {Integer.MIN_VALUE, -1, 1, Integer.MAX_VALUE}) { nonZeroErrorlevelShouldMakeBuildUnstable(exitCode); } } @@ -87,19 +87,19 @@ private void nonZeroErrorlevelShouldBreakTheBuildByDefault(int exitCode) throws p = rule.createFreeStyleProject(); p.getBuildersList().add(createNewBatchTask("", null)); p.setAssignedNode(slave); - rule.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0).get()); + rule.buildAndAssertStatus(Result.FAILURE, p); p = rule.createFreeStyleProject(); p.getBuildersList().add(createNewBatchTask("", 0)); p.setAssignedNode(slave); - rule.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0).get()); + rule.buildAndAssertStatus(Result.FAILURE, p); } @Test @Issue("JENKINS-23786") public void windowsNonZeroErrorlevelsShouldBreakTheBuildByDefault() throws Exception { assumeTrue(Functions.isWindows()); - for( int exitCode: new int [] {Integer.MIN_VALUE, -1, 1, Integer.MAX_VALUE}) { + for (int exitCode : new int [] {Integer.MIN_VALUE, -1, 1, Integer.MAX_VALUE}) { nonZeroErrorlevelShouldBreakTheBuildByDefault(exitCode); } } @@ -112,14 +112,14 @@ private void nonZeroErrorlevelShouldBreakTheBuildIfNotMatching(int exitCode) thr FreeStyleProject p = rule.createFreeStyleProject(); p.getBuildersList().add(createNewBatchTask("", notMatchingExitCode)); p.setAssignedNode(slave); - rule.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0).get()); + rule.buildAndAssertStatus(Result.FAILURE, p); } @Test @Issue("JENKINS-23786") public void windowsErrorlevelsShouldBreakTheBuildIfNotMatching() throws Exception { assumeTrue(Functions.isWindows()); - for( int exitCode: new int [] {Integer.MIN_VALUE, -1, 1, Integer.MAX_VALUE}) { + for (int exitCode : new int [] {Integer.MIN_VALUE, -1, 1, Integer.MAX_VALUE}) { nonZeroErrorlevelShouldBreakTheBuildIfNotMatching(exitCode); } } @@ -130,11 +130,11 @@ public void windowsErrorlevel0ShouldNeverMakeTheBuildUnstable() throws Exception assumeTrue(Functions.isWindows()); PretendSlave slave = rule.createPretendSlave(new BatchFileTest.ReturnCodeFakeLauncher(0)); - for( Integer unstableReturn: new Integer [] {null, 0, 1}) { + for (Integer unstableReturn : new Integer [] {null, 0, 1}) { FreeStyleProject p = rule.createFreeStyleProject(); p.getBuildersList().add(createNewBatchTask("", unstableReturn)); p.setAssignedNode(slave); - rule.assertBuildStatus(Result.SUCCESS, p.scheduleBuild2(0).get()); + rule.buildAndAssertSuccess(p); } } @@ -144,7 +144,7 @@ public void windowsUnstableCodeZeroIsSameAsUnset() { assumeTrue(Functions.isWindows()); /* Creating unstable=0 produces unstable=null */ - assertNull( createNewBatchTask("",0).getUnstableReturn() ); + assertNull(createNewBatchTask("", 0).getUnstableReturn()); } @Issue("JENKINS-40894") diff --git a/test/src/test/java/hudson/tasks/BuildTriggerTest.java b/test/src/test/java/hudson/tasks/BuildTriggerTest.java index a7efe039ae7a4..85a320f74c5cd 100644 --- a/test/src/test/java/hudson/tasks/BuildTriggerTest.java +++ b/test/src/test/java/hudson/tasks/BuildTriggerTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.tasks; import static org.junit.Assert.assertEquals; @@ -103,26 +104,24 @@ private void doTriggerTest(boolean evenWhenUnstable, Result triggerResult, j.jenkins.rebuildDependencyGraph(); // First build should not trigger downstream job - FreeStyleBuild b = p.scheduleBuild2(0).get(); + FreeStyleBuild b = j.buildAndAssertStatus(dontTriggerResult, p); assertNoDownstreamBuild(dp, b); - j.assertBuildStatus(dontTriggerResult, b); // Next build should trigger downstream job p.getBuildersList().replace(new MockBuilder(triggerResult)); - b = p.scheduleBuild2(0).get(); - j.assertBuildStatus(triggerResult, b); + b = j.buildAndAssertStatus(triggerResult, p); j.assertBuildStatusSuccess(j.waitForCompletion(assertDownstreamBuild(dp, b))); } - private void assertNoDownstreamBuild(FreeStyleProject dp, Run b) throws Exception { + private void assertNoDownstreamBuild(FreeStyleProject dp, Run b) throws Exception { for (int i = 0; i < 3; i++) { Thread.sleep(200); assertTrue("downstream build should not run! upstream log: " + b.getLog(), - !dp.isInQueue() && !dp.isBuilding() && dp.getLastBuild()==null); + !dp.isInQueue() && !dp.isBuilding() && dp.getLastBuild() == null); } } - private FreeStyleBuild assertDownstreamBuild(FreeStyleProject dp, Run b) throws Exception { + private FreeStyleBuild assertDownstreamBuild(FreeStyleProject dp, Run b) throws Exception { // Wait for downstream build FreeStyleBuild result = null; for (int i = 0; (result = dp.getLastBuild()) == null && i < 25; i++) { @@ -151,10 +150,10 @@ public void downstreamProjectSecurity() throws Exception { auth.add(Computer.BUILD, "alice"); auth.add(Computer.BUILD, "anonymous"); j.jenkins.setAuthorizationStrategy(auth); - final FreeStyleProject upstream =j. createFreeStyleProject("upstream"); + final FreeStyleProject upstream = j. createFreeStyleProject("upstream"); org.acegisecurity.Authentication alice = User.getOrCreateByIdOrFullName("alice").impersonate(); QueueItemAuthenticatorConfiguration.get().getAuthenticators().add(new MockQueueItemAuthenticator(Collections.singletonMap("upstream", alice))); - Map> perms = new HashMap<>(); + Map> perms = new HashMap<>(); perms.put(Item.READ, Collections.singleton("alice")); perms.put(Item.CONFIGURE, Collections.singleton("alice")); upstream.addProperty(new AuthorizationMatrixProperty(perms)); @@ -182,7 +181,7 @@ public void downstreamProjectSecurity() throws Exception { j.waitUntilNoActivity(); assertNull(downstream.getLastBuild()); // If we can see them, but not build them, that is a warning (but this is in cleanUp so the build is still considered a success): - Map> grantedPermissions = new HashMap<>(); + Map> grantedPermissions = new HashMap<>(); grantedPermissions.put(Item.READ, Collections.singleton("alice")); AuthorizationMatrixProperty amp = new AuthorizationMatrixProperty(grantedPermissions); downstream.addProperty(amp); @@ -243,6 +242,7 @@ public void downstreamProjectSecurity() throws Exception { assertEquals(3, downstream.getLastBuild().number); j.buildAndAssertSuccess(simple); } + private void assertDoCheck(org.acegisecurity.Authentication auth, @CheckForNull String expectedError, AbstractProject project, String value) { FormValidation result; try (ACLContext c = ACL.as(auth)) { @@ -308,6 +308,7 @@ private static final class SlowTrigger extends BuildTrigger { private static final class Dep extends Dependency { private static boolean block = false; + private Dep(AbstractProject upstream, AbstractProject downstream) { super(upstream, downstream); } @@ -333,7 +334,7 @@ public boolean shouldTriggerBuild(AbstractBuild build, TaskListener listener, Li @Override @SuppressWarnings("rawtypes") public void buildDependencyGraph(AbstractProject owner, DependencyGraph graph) { - for (AbstractProject ch: getChildProjects(owner)) { + for (AbstractProject ch : getChildProjects(owner)) { graph.addDependency(new Dep(owner, ch)); } } diff --git a/test/src/test/java/hudson/tasks/CommandInterpreterTest.java b/test/src/test/java/hudson/tasks/CommandInterpreterTest.java index 72263544a7467..d1696f2b484ec 100644 --- a/test/src/test/java/hudson/tasks/CommandInterpreterTest.java +++ b/test/src/test/java/hudson/tasks/CommandInterpreterTest.java @@ -30,7 +30,7 @@ public void ensurePluginCommandInterpretersCanBeLoaded() { Assert.fail("getConfiguredLocalRules must not return null"); } try { - ((TestCommandInterpreter)builder).buildEnvVarsFilterRules(); + ((TestCommandInterpreter) builder).buildEnvVarsFilterRules(); } catch (NullPointerException ex) { Assert.fail("buildEnvVarsFilterRules must not throw"); } diff --git a/test/src/test/java/hudson/tasks/EnvVarsInConfigTasksTest.java b/test/src/test/java/hudson/tasks/EnvVarsInConfigTasksTest.java index a2b94beae7d71..809c7cd1c143e 100644 --- a/test/src/test/java/hudson/tasks/EnvVarsInConfigTasksTest.java +++ b/test/src/test/java/hudson/tasks/EnvVarsInConfigTasksTest.java @@ -20,102 +20,94 @@ import org.jvnet.hudson.test.ToolInstallations; public class EnvVarsInConfigTasksTest { - public static final String DUMMY_LOCATION_VARNAME = "TOOLS_DUMMY_LOCATION"; - - private DumbSlave agentEnv = null; - private DumbSlave agentRegular = null; - - @ClassRule - public static BuildWatcher buildWatcher = new BuildWatcher(); - - @Rule - public JenkinsRule j = new JenkinsRule(); - - @Rule - public TemporaryFolder tmp = new TemporaryFolder(); - - @Before - public void setUp() throws Exception { - JDK defaultJDK = j.jenkins.getJDK(null); - JDK varJDK = new JDK("varJDK", withVariable(defaultJDK.getHome())); - j.jenkins.getJDKs().add(varJDK); - - // Maven with a variable in its path - ToolInstallations.configureDefaultMaven(); - MavenInstallation defaultMaven = j.jenkins.getDescriptorByType(Maven.DescriptorImpl.class).getInstallations()[0]; - MavenInstallation varMaven = new MavenInstallation("varMaven", - withVariable(defaultMaven.getHome()), JenkinsRule.NO_PROPERTIES); - j.jenkins.getDescriptorByType(Maven.DescriptorImpl.class).setInstallations(varMaven); - - // create agents - EnvVars additionalEnv = new EnvVars(DUMMY_LOCATION_VARNAME, ""); - agentEnv = j.createSlave(new LabelAtom("agentEnv"), additionalEnv); - agentRegular = j.createSlave(new LabelAtom("agentRegular")); - } - - private String withVariable(String s) { - return s + "${" + DUMMY_LOCATION_VARNAME + "}"; - } - - @Test - public void testFreeStyleShellOnAgent() throws Exception { - FreeStyleProject project = j.createFreeStyleProject(); - if (Functions.isWindows()) { - project.getBuildersList().add(new BatchFile("echo %JAVA_HOME%")); - } else { - project.getBuildersList().add(new Shell("echo \"$JAVA_HOME\"")); - } - project.setJDK(j.jenkins.getJDK("varJDK")); - - // set appropriate SCM to get the necessary build files - project.setScm(new ExtractResourceSCM(getClass().getResource( - "/simple-projects.zip"))); - - // test the regular agent - variable not expanded - project.setAssignedLabel(agentRegular.getSelfLabel()); - FreeStyleBuild build = project.scheduleBuild2(0).get(); - - j.assertBuildStatusSuccess(build); - - j.assertLogContains(DUMMY_LOCATION_VARNAME, build); - - // test the agent with prepared environment - project.setAssignedLabel(agentEnv.getSelfLabel()); - build = project.scheduleBuild2(0).get(); - - j.assertBuildStatusSuccess(build); - - // Check variable was expanded - j.assertLogNotContains(DUMMY_LOCATION_VARNAME, build); - } - - @Test - public void testFreeStyleMavenOnAgent() throws Exception { - FreeStyleProject project = j.createFreeStyleProject(); - project.setJDK(j.jenkins.getJDK("varJDK")); - project.setScm(new ExtractResourceSCM(getClass().getResource( - "/simple-projects.zip"))); - - project.getBuildersList().add( - new Maven("test", "varMaven", "pom.xml${" - + DUMMY_LOCATION_VARNAME + "}", "", "", - false)); - - // test the regular agent - variable not expanded - project.setAssignedLabel(agentRegular.getSelfLabel()); - FreeStyleBuild build = project.scheduleBuild2(0).get(); - - j.assertBuildStatus(Result.FAILURE, build); - - j.assertLogContains(DUMMY_LOCATION_VARNAME, build); - - // test the agent with prepared environment - project.setAssignedLabel(agentEnv.getSelfLabel()); - build = project.scheduleBuild2(0).get(); - - j.assertBuildStatusSuccess(build); - - // Check variable was expanded - j.assertLogNotContains(DUMMY_LOCATION_VARNAME, build); - } + public static final String DUMMY_LOCATION_VARNAME = "TOOLS_DUMMY_LOCATION"; + + private DumbSlave agentEnv = null; + private DumbSlave agentRegular = null; + + @ClassRule + public static BuildWatcher buildWatcher = new BuildWatcher(); + + @Rule + public JenkinsRule j = new JenkinsRule(); + + @Rule + public TemporaryFolder tmp = new TemporaryFolder(); + + @Before + public void setUp() throws Exception { + JDK defaultJDK = j.jenkins.getJDK(null); + JDK varJDK = new JDK("varJDK", withVariable(defaultJDK.getHome())); + j.jenkins.getJDKs().add(varJDK); + + // Maven with a variable in its path + ToolInstallations.configureDefaultMaven(); + MavenInstallation defaultMaven = j.jenkins.getDescriptorByType(Maven.DescriptorImpl.class).getInstallations()[0]; + MavenInstallation varMaven = new MavenInstallation("varMaven", + withVariable(defaultMaven.getHome()), JenkinsRule.NO_PROPERTIES); + j.jenkins.getDescriptorByType(Maven.DescriptorImpl.class).setInstallations(varMaven); + + // create agents + EnvVars additionalEnv = new EnvVars(DUMMY_LOCATION_VARNAME, ""); + agentEnv = j.createSlave(new LabelAtom("agentEnv"), additionalEnv); + agentRegular = j.createSlave(new LabelAtom("agentRegular")); + } + + private String withVariable(String s) { + return s + "${" + DUMMY_LOCATION_VARNAME + "}"; + } + + @Test + public void testFreeStyleShellOnAgent() throws Exception { + FreeStyleProject project = j.createFreeStyleProject(); + if (Functions.isWindows()) { + project.getBuildersList().add(new BatchFile("echo %JAVA_HOME%")); + } else { + project.getBuildersList().add(new Shell("echo \"$JAVA_HOME\"")); + } + project.setJDK(j.jenkins.getJDK("varJDK")); + + // set appropriate SCM to get the necessary build files + project.setScm(new ExtractResourceSCM(getClass().getResource( + "/simple-projects.zip"))); + + // test the regular agent - variable not expanded + project.setAssignedLabel(agentRegular.getSelfLabel()); + FreeStyleBuild build = j.buildAndAssertSuccess(project); + + j.assertLogContains(DUMMY_LOCATION_VARNAME, build); + + // test the agent with prepared environment + project.setAssignedLabel(agentEnv.getSelfLabel()); + build = j.buildAndAssertSuccess(project); + + // Check variable was expanded + j.assertLogNotContains(DUMMY_LOCATION_VARNAME, build); + } + + @Test + public void testFreeStyleMavenOnAgent() throws Exception { + FreeStyleProject project = j.createFreeStyleProject(); + project.setJDK(j.jenkins.getJDK("varJDK")); + project.setScm(new ExtractResourceSCM(getClass().getResource( + "/simple-projects.zip"))); + + project.getBuildersList().add( + new Maven("test", "varMaven", "pom.xml${" + + DUMMY_LOCATION_VARNAME + "}", "", "", + false)); + + // test the regular agent - variable not expanded + project.setAssignedLabel(agentRegular.getSelfLabel()); + FreeStyleBuild build = j.buildAndAssertStatus(Result.FAILURE, project); + + j.assertLogContains(DUMMY_LOCATION_VARNAME, build); + + // test the agent with prepared environment + project.setAssignedLabel(agentEnv.getSelfLabel()); + build = j.buildAndAssertSuccess(project); + + // Check variable was expanded + j.assertLogNotContains(DUMMY_LOCATION_VARNAME, build); + } } diff --git a/test/src/test/java/hudson/tasks/FingerprinterTest.java b/test/src/test/java/hudson/tasks/FingerprinterTest.java index ffa5a087326f2..4e99be1af0630 100644 --- a/test/src/test/java/hudson/tasks/FingerprinterTest.java +++ b/test/src/test/java/hudson/tasks/FingerprinterTest.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright 2011 Yahoo!, Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -90,7 +90,7 @@ public class FingerprinterTest { "test.txt", "test2.txt", }; - + private static final String renamedProject1 = "renamed project 1"; private static final String renamedProject2 = "renamed project 2"; @@ -100,13 +100,13 @@ public class FingerprinterTest { public static void setUp() { Fingerprinter.enableFingerprintsInDependencyGraph = true; } - + @Test public void fingerprintDependencies() throws Exception { FreeStyleProject upstream = createFreeStyleProjectWithFingerprints(singleContents, singleFiles); FreeStyleProject downstream = createFreeStyleProjectWithFingerprints(singleContents, singleFiles); - j.assertBuildStatusSuccess(upstream.scheduleBuild2(0).get()); - j.assertBuildStatusSuccess(downstream.scheduleBuild2(0).get()); + j.buildAndAssertSuccess(upstream); + j.buildAndAssertSuccess(downstream); j.jenkins.rebuildDependencyGraph(); @@ -144,9 +144,9 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen FreeStyleProject upstream2 = createFreeStyleProjectWithFingerprints(singleContents2, singleFiles2); FreeStyleProject downstream = createFreeStyleProjectWithFingerprints(doubleContents, doubleFiles); - j.assertBuildStatusSuccess(upstream.scheduleBuild2(0).get()); - j.assertBuildStatusSuccess(upstream2.scheduleBuild2(0).get()); - j.assertBuildStatusSuccess(downstream.scheduleBuild2(0).get()); + j.buildAndAssertSuccess(upstream); + j.buildAndAssertSuccess(upstream2); + j.buildAndAssertSuccess(downstream); j.jenkins.rebuildDependencyGraph(); @@ -167,9 +167,9 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen FreeStyleProject downstream = createFreeStyleProjectWithFingerprints(singleContents, singleFiles); FreeStyleProject downstream2 = createFreeStyleProjectWithFingerprints(singleContents2, singleFiles2); - j.assertBuildStatusSuccess(upstream.scheduleBuild2(0).get()); - j.assertBuildStatusSuccess(downstream.scheduleBuild2(0).get()); - j.assertBuildStatusSuccess(downstream2.scheduleBuild2(0).get()); + j.buildAndAssertSuccess(upstream); + j.buildAndAssertSuccess(downstream); + j.buildAndAssertSuccess(downstream2); j.jenkins.rebuildDependencyGraph(); @@ -190,8 +190,8 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen FreeStyleProject upstream = createFreeStyleProjectWithFingerprints(singleContents, singleFiles); FreeStyleProject downstream = createFreeStyleProjectWithFingerprints(singleContents, singleFiles); - FreeStyleBuild upstreamBuild = j.assertBuildStatusSuccess(upstream.scheduleBuild2(0).get()); - j.assertBuildStatusSuccess(downstream.scheduleBuild2(0).get()); + FreeStyleBuild upstreamBuild = j.buildAndAssertSuccess(upstream); + j.buildAndAssertSuccess(downstream); upstreamBuild.delete(); @@ -206,19 +206,19 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen @Test public void circularDependency() throws Exception { FreeStyleProject p = createFreeStyleProjectWithFingerprints(singleContents, singleFiles); - - j.assertBuildStatusSuccess(p.scheduleBuild2(0).get()); - j.assertBuildStatusSuccess(p.scheduleBuild2(0).get()); - + + j.buildAndAssertSuccess(p); + j.buildAndAssertSuccess(p); + Jenkins.get().rebuildDependencyGraph(); List upstreamProjects = p.getUpstreamProjects(); List downstreamProjects = p.getDownstreamProjects(); - + assertEquals(0, upstreamProjects.size()); assertEquals(0, downstreamProjects.size()); } - + @Test public void matrixDependency() throws Exception { MatrixProject matrixProject = j.jenkins.createProject(MatrixProject.class, "p"); matrixProject.setAxes(new AxisList(new Axis("foo", "a", "b"))); @@ -238,7 +238,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen FreeStyleBuild build = builds.iterator().next(); assertEquals(Result.SUCCESS, build.getResult()); List downstream = j.jenkins.getDependencyGraph().getDownstream(matrixProject); - assertTrue(downstream.contains(freestyleProject)); + assertTrue(downstream.contains(freestyleProject)); List upstream = j.jenkins.getDependencyGraph().getUpstream(freestyleProject); assertTrue(upstream.contains(matrixProject)); } @@ -247,33 +247,33 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen FreeStyleProject upstream = createFreeStyleProjectWithFingerprints(singleContents, singleFiles); FreeStyleProject downstream = createFreeStyleProjectWithFingerprints(singleContents, singleFiles); - FreeStyleBuild upstreamBuild = j.assertBuildStatusSuccess(upstream.scheduleBuild2(0).get()); - FreeStyleBuild downstreamBuild = j.assertBuildStatusSuccess(downstream.scheduleBuild2(0).get()); + FreeStyleBuild upstreamBuild = j.buildAndAssertSuccess(upstream); + FreeStyleBuild downstreamBuild = j.buildAndAssertSuccess(downstream); String oldUpstreamName = upstream.getName(); String oldDownstreamName = downstream.getName(); - + // Verify that owner entry in fingerprint record is changed // after source project is renamed upstream.renameTo(renamedProject1); Fingerprinter.FingerprintAction action = upstreamBuild.getAction(Fingerprinter.FingerprintAction.class); assertNotNull(action); Collection fingerprints = action.getFingerprints().values(); - for (Fingerprint f: fingerprints) { + for (Fingerprint f : fingerprints) { assertTrue(f.getOriginal().is(upstream)); assertEquals(renamedProject1, f.getOriginal().getName()); assertNotEquals(f.getOriginal().getName(), oldUpstreamName); } - + action = downstreamBuild.getAction(Fingerprinter.FingerprintAction.class); assertNotNull(action); fingerprints = action.getFingerprints().values(); - for (Fingerprint f: fingerprints) { + for (Fingerprint f : fingerprints) { assertTrue(f.getOriginal().is(upstream)); assertEquals(renamedProject1, f.getOriginal().getName()); assertNotEquals(f.getOriginal().getName(), oldUpstreamName); } - + // Verify that usage entry in fingerprint record is changed after // sink project is renamed downstream.renameTo(renamedProject2); @@ -281,9 +281,9 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen action = upstreamBuild.getAction(Fingerprinter.FingerprintAction.class); assertNotNull(action); fingerprints = action.getFingerprints().values(); - for (Fingerprint f: fingerprints) { + for (Fingerprint f : fingerprints) { List jobs = f.getJobs(); - + assertTrue(jobs.contains(renamedProject2)); assertFalse(jobs.contains(oldDownstreamName)); } @@ -291,9 +291,9 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen action = downstreamBuild.getAction(Fingerprinter.FingerprintAction.class); assertNotNull(action); fingerprints = action.getFingerprints().values(); - for (Fingerprint f: fingerprints) { + for (Fingerprint f : fingerprints) { List jobs = f.getJobs(); - + assertTrue(jobs.contains(renamedProject2)); assertFalse(jobs.contains(oldDownstreamName)); } @@ -314,7 +314,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen } else { assertEquals("{a=2d5fac981a2e865baf0e15db655c7d63}", action.getRecords().toString()); } - j.assertBuildStatusSuccess(job.scheduleBuild2(0)); + j.buildAndAssertSuccess(job); job._getRuns().purgeCache(); // force build records to be reloaded build = job.getBuildByNumber(3); assertNotNull(build); @@ -339,19 +339,19 @@ public void fingerprintCleanup() throws Exception { FreeStyleProject p2 = createFreeStyleProjectWithFingerprints(singleContents, singleFiles2); FreeStyleProject p3 = createFreeStyleProjectWithFingerprints(singleContents, singleFiles); - j.assertBuildStatusSuccess(p1.scheduleBuild2(0)); - j.assertBuildStatusSuccess(p2.scheduleBuild2(0)); - j.assertBuildStatusSuccess(p3.scheduleBuild2(0)); + j.buildAndAssertSuccess(p1); + j.buildAndAssertSuccess(p2); + j.buildAndAssertSuccess(p3); - Fingerprint f = j.jenkins._getFingerprint(Util.getDigestOf(singleContents[0]+System.lineSeparator())); + Fingerprint f = j.jenkins._getFingerprint(Util.getDigestOf(singleContents[0] + System.lineSeparator())); assertNotNull(f); - assertEquals(3,f.getUsages().size()); + assertEquals(3, f.getUsages().size()); j.jenkins.rebuildDependencyGraph(); assertEquals(Collections.singletonList(p1), p2.getUpstreamProjects()); assertEquals(Collections.singletonList(p1), p3.getUpstreamProjects()); - assertEquals(new HashSet(Arrays.asList(p2,p3)), new HashSet(p1.getDownstreamProjects())); + assertEquals(new HashSet(Arrays.asList(p2, p3)), new HashSet(p1.getDownstreamProjects())); // discard the p3 records p3.delete(); @@ -360,7 +360,7 @@ public void fingerprintCleanup() throws Exception { j.jenkins.rebuildDependencyGraph(); // records for p3 should have been deleted now - assertEquals(2,f.getUsages().size()); + assertEquals(2, f.getUsages().size()); assertEquals(Collections.singletonList(p1), p2.getUpstreamProjects()); assertEquals(Collections.singletonList(p2), p1.getDownstreamProjects()); @@ -368,40 +368,40 @@ public void fingerprintCleanup() throws Exception { // do a new build in p2 #2 that points to a separate fingerprints p2.getBuildersList().clear(); p2.getPublishersList().clear(); - addFingerprinterToProject(p2,singleContents2,singleFiles2); - j.assertBuildStatusSuccess(p2.scheduleBuild2(0)); + addFingerprinterToProject(p2, singleContents2, singleFiles2); + j.buildAndAssertSuccess(p2); // another garbage collection that gets rid of p2 records from the fingerprint p2.getBuildByNumber(1).delete(); new FingerprintCleanupThread().execute(StreamTaskListener.fromStdout()); - assertEquals(1,f.getUsages().size()); + assertEquals(1, f.getUsages().size()); } - + private FreeStyleProject createFreeStyleProjectWithFingerprints(String[] contents, String[] files) throws Exception { FreeStyleProject project = j.createFreeStyleProject(); addFingerprinterToProject(project, contents, files); - + return project; } - + private void addFingerprinterToProject(AbstractProject project, String[] contents, String[] files) { StringBuilder targets = new StringBuilder(); for (int i = 0; i < contents.length; i++) { if (project instanceof MatrixProject) { - ((MatrixProject)project).getBuildersList().add( + ((MatrixProject) project).getBuildersList().add( Functions.isWindows() ? new BatchFile("echo " + contents[i] + "> " + files[i]) : new Shell("echo " + contents[i] + " > " + files[i])); } else { - ((FreeStyleProject)project).getBuildersList().add( + ((FreeStyleProject) project).getBuildersList().add( Functions.isWindows() ? new BatchFile("echo " + contents[i] + "> " + files[i]) : new Shell("echo " + contents[i] + " > " + files[i])); } - + targets.append(files[i]).append(','); } diff --git a/test/src/test/java/hudson/tasks/LogRotatorTest.java b/test/src/test/java/hudson/tasks/LogRotatorTest.java index 0b967cde4e622..da5da0f15211e 100644 --- a/test/src/test/java/hudson/tasks/LogRotatorTest.java +++ b/test/src/test/java/hudson/tasks/LogRotatorTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.tasks; import static org.hamcrest.MatcherAssert.assertThat; @@ -67,13 +68,13 @@ public class LogRotatorTest { public void successVsFailure() throws Exception { FreeStyleProject project = j.createFreeStyleProject(); project.setLogRotator(new LogRotator(-1, 2, -1, -1)); - assertEquals(Result.SUCCESS, build(project)); // #1 + j.buildAndAssertSuccess(project); // #1 project.getBuildersList().replaceBy(Collections.singleton(new FailureBuilder())); - assertEquals(Result.FAILURE, build(project)); // #2 - assertEquals(Result.FAILURE, build(project)); // #3 + j.buildAndAssertStatus(Result.FAILURE, project); // #2 + j.buildAndAssertStatus(Result.FAILURE, project); // #3 assertEquals(1, numberOf(project.getLastSuccessfulBuild())); project.getBuildersList().replaceBy(Collections.emptySet()); - assertEquals(Result.SUCCESS, build(project)); // #4 + j.buildAndAssertSuccess(project); // #4 assertEquals(4, numberOf(project.getLastSuccessfulBuild())); assertNull(project.getBuildByNumber(1)); assertNull(project.getBuildByNumber(2)); @@ -85,13 +86,13 @@ public void successVsFailure() throws Exception { public void stableVsUnstable() throws Exception { FreeStyleProject project = j.createFreeStyleProject(); project.setLogRotator(new LogRotator(-1, 2, -1, -1)); - assertEquals(Result.SUCCESS, build(project)); // #1 + j.buildAndAssertSuccess(project); // #1 project.getPublishersList().replaceBy(Collections.singleton(new TestsFail())); - assertEquals(Result.UNSTABLE, build(project)); // #2 - assertEquals(Result.UNSTABLE, build(project)); // #3 + j.buildAndAssertStatus(Result.UNSTABLE, project); // #2 + j.buildAndAssertStatus(Result.UNSTABLE, project); // #3 assertEquals(1, numberOf(project.getLastStableBuild())); project.getPublishersList().replaceBy(Collections.emptySet()); - assertEquals(Result.SUCCESS, build(project)); // #4 + j.buildAndAssertSuccess(project); // #4 assertNull(project.getBuildByNumber(1)); assertNull(project.getBuildByNumber(2)); } @@ -102,32 +103,32 @@ public void artifactDelete() throws Exception { FreeStyleProject project = j.createFreeStyleProject(); project.setLogRotator(new LogRotator(-1, 6, -1, 2)); project.getPublishersList().replaceBy(Collections.singleton(new ArtifactArchiver("f", "", true, false))); - assertEquals("(no artifacts)", Result.FAILURE, build(project)); // #1 + j.buildAndAssertStatus(Result.FAILURE, project); // #1 assertFalse(project.getBuildByNumber(1).getHasArtifacts()); project.getBuildersList().replaceBy(Collections.singleton(new CreateArtifact())); - assertEquals(Result.SUCCESS, build(project)); // #2 + j.buildAndAssertSuccess(project); // #2 assertTrue(project.getBuildByNumber(2).getHasArtifacts()); project.getBuildersList().replaceBy(Arrays.asList(new CreateArtifact(), new FailureBuilder())); - assertEquals(Result.FAILURE, build(project)); // #3 + j.buildAndAssertStatus(Result.FAILURE, project); // #3 assertTrue(project.getBuildByNumber(2).getHasArtifacts()); assertTrue(project.getBuildByNumber(3).getHasArtifacts()); - assertEquals(Result.FAILURE, build(project)); // #4 + j.buildAndAssertStatus(Result.FAILURE, project); // #4 assertTrue(project.getBuildByNumber(2).getHasArtifacts()); assertTrue(project.getBuildByNumber(3).getHasArtifacts()); assertTrue(project.getBuildByNumber(4).getHasArtifacts()); - assertEquals(Result.FAILURE, build(project)); // #5 + j.buildAndAssertStatus(Result.FAILURE, project); // #5 assertTrue(project.getBuildByNumber(2).getHasArtifacts()); assertFalse("no better than #4", project.getBuildByNumber(3).getHasArtifacts()); assertTrue(project.getBuildByNumber(4).getHasArtifacts()); assertTrue(project.getBuildByNumber(5).getHasArtifacts()); project.getBuildersList().replaceBy(Collections.singleton(new CreateArtifact())); - assertEquals(Result.SUCCESS, build(project)); // #6 + j.buildAndAssertSuccess(project); // #6 assertFalse("#2 is still lastSuccessful until #6 is complete", project.getBuildByNumber(2).getHasArtifacts()); assertFalse(project.getBuildByNumber(3).getHasArtifacts()); assertFalse(project.getBuildByNumber(4).getHasArtifacts()); assertTrue(project.getBuildByNumber(5).getHasArtifacts()); assertTrue(project.getBuildByNumber(6).getHasArtifacts()); - assertEquals(Result.SUCCESS, build(project)); // #7 + j.buildAndAssertSuccess(project); // #7 assertNull(project.getBuildByNumber(1)); assertNotNull(project.getBuildByNumber(2)); assertFalse("lastSuccessful was #6 for ArtifactArchiver", project.getBuildByNumber(2).getHasArtifacts()); @@ -136,7 +137,7 @@ public void artifactDelete() throws Exception { assertFalse(project.getBuildByNumber(5).getHasArtifacts()); assertTrue(project.getBuildByNumber(6).getHasArtifacts()); assertTrue(project.getBuildByNumber(7).getHasArtifacts()); - assertEquals(Result.SUCCESS, build(project)); // #8 + j.buildAndAssertSuccess(project); // #8 assertNull(project.getBuildByNumber(2)); assertNotNull(project.getBuildByNumber(3)); assertFalse(project.getBuildByNumber(3).getHasArtifacts()); @@ -146,7 +147,7 @@ public void artifactDelete() throws Exception { assertTrue(project.getBuildByNumber(7).getHasArtifacts()); assertTrue(project.getBuildByNumber(8).getHasArtifacts()); } - + @Test @Issue("JENKINS-27836") public void artifactsRetainedWhileBuilding() throws Exception { @@ -179,7 +180,7 @@ public void artifactsRetainedWhileBuilding() throws Exception { assertThat("run1 is last stable build", p.getLastStableBuild(), is(run1)); assertThat("run1 is last successful build", p.getLastSuccessfulBuild(), is(run1)); assertThat("we have artifacts in run1", run1.getHasArtifacts(), is(true)); - assertThat("CRITICAL ASSERTION: we have artifacts in run2", run2.getHasArtifacts(), is(true)); + assertThat("CRITICAL ASSERTION: we have artifacts in run2", run2.getHasArtifacts(), is(true)); assertThat("we have artifacts in run3", run3.getHasArtifacts(), is(true)); sync.release(run2.getNumber()); futureRun2.get(); @@ -200,17 +201,13 @@ public void artifactsRetainedWhileBuilding() throws Exception { assertThat("we have artifacts in run3", run3.getHasArtifacts(), is(true)); } - static Result build(FreeStyleProject project) throws Exception { - return project.scheduleBuild2(0).get().getResult(); - } - - private static int numberOf(Run run) { + private static int numberOf(Run run) { return run != null ? run.getNumber() : -1; } static class TestsFail extends Publisher { @Override - public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) { + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) { build.setResult(Result.UNSTABLE); return true; } @@ -225,21 +222,21 @@ public Descriptor getDescriptor() { return new Descriptor(TestsFail.class) {}; } } - + public static class StallBuilder extends TestBuilder { - + private int syncBuildNumber; - + private final Object syncLock = new Object(); - + private int waitBuildNumber; - + private final Object waitLock = new Object(); - + private final ArtifactArchiver archiver = new ArtifactArchiver("f"); @Override - public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { archiver.perform(build, launcher, listener); Logger.getAnonymousLogger().log(Level.INFO, "Building #{0}", build.getNumber()); @@ -263,7 +260,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListene Logger.getAnonymousLogger().log(Level.INFO, "Done #{0}", build.getNumber()); return true; } - + public void release(int upToBuildNumber) { synchronized (syncLock) { if (syncBuildNumber < upToBuildNumber) { @@ -273,7 +270,7 @@ public void release(int upToBuildNumber) { } } } - + public void waitFor(int buildNumber, long timeout, TimeUnit units) throws TimeoutException, InterruptedException { long giveUp = System.nanoTime() + units.toNanos(timeout); @@ -283,7 +280,7 @@ public void waitFor(int buildNumber, long timeout, TimeUnit units) throws Timeou if (remaining < 0) { throw new TimeoutException(); } - waitLock.wait(remaining/1000000L, (int)(remaining%1000000L)); + waitLock.wait(remaining / 1000000L, (int) (remaining % 1000000L)); } } } diff --git a/test/src/test/java/hudson/tasks/MavenTest.java b/test/src/test/java/hudson/tasks/MavenTest.java index c6395bf72b711..700372cfb6c34 100644 --- a/test/src/test/java/hudson/tasks/MavenTest.java +++ b/test/src/test/java/hudson/tasks/MavenTest.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, Yahoo! Inc. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.tasks; import static org.junit.Assert.assertEquals; @@ -34,7 +35,6 @@ import com.gargoylesoftware.htmlunit.html.HtmlForm; import com.gargoylesoftware.htmlunit.html.HtmlPage; import hudson.EnvVars; -import hudson.model.Build; import hudson.model.Cause.LegacyCodeCause; import hudson.model.FreeStyleBuild; import hudson.model.FreeStyleProject; @@ -42,7 +42,6 @@ import hudson.model.ParametersAction; import hudson.model.ParametersDefinitionProperty; import hudson.model.PasswordParameterDefinition; -import hudson.model.Result; import hudson.model.StringParameterDefinition; import hudson.model.StringParameterValue; import hudson.slaves.EnvironmentVariablesNodeProperty; @@ -97,7 +96,7 @@ public class MavenTest { assertEquals("b.pom", m.pom); assertEquals("c=d", m.properties); assertEquals("-e", m.jvmOptions); - assertTrue(m.usesPrivateRepository()); + assertTrue(m.usesPrivateRepository()); } @Test public void withNodeProperty() throws Exception { @@ -123,10 +122,7 @@ public class MavenTest { project.getBuildersList().add(new Maven("--help", varMaven.getName())); project.setJDK(varJDK); - Build build = project.scheduleBuild2(0).get(); - - assertEquals(Result.SUCCESS, build.getResult()); - + j.buildAndAssertSuccess(project); } @Test public void withParameter() throws Exception { @@ -134,7 +130,7 @@ public class MavenTest { String mavenHome = maven.getHome(); String mavenHomeVar = "${VAR_MAVEN}" + mavenHome.substring(3); String mavenVar = mavenHome.substring(0, 3); - MavenInstallation varMaven = new MavenInstallation("varMaven",mavenHomeVar, JenkinsRule.NO_PROPERTIES); + MavenInstallation varMaven = new MavenInstallation("varMaven", mavenHomeVar, JenkinsRule.NO_PROPERTIES); j.jenkins.getDescriptorByType(Maven.DescriptorImpl.class).setInstallations(maven, varMaven); JDK jdk = j.jenkins.getJDK("default"); @@ -168,8 +164,8 @@ public class MavenTest { HtmlForm f = p.getFormByName("config"); HtmlButton b = j.getButtonByCaption(f, "Add Maven"); b.click(); - j.findPreviousInputElement(b,"name").setValueAttribute("myMaven"); - j.findPreviousInputElement(b,"home").setValueAttribute("/tmp/foo"); + j.findPreviousInputElement(b, "name").setValueAttribute("myMaven"); + j.findPreviousInputElement(b, "home").setValueAttribute("/tmp/foo"); j.submit(f); verify(); @@ -182,14 +178,14 @@ public class MavenTest { private void verify() throws Exception { MavenInstallation[] l = j.get(MavenInstallation.DescriptorImpl.class).getInstallations(); - assertEquals(1,l.length); - j.assertEqualBeans(l[0],new MavenInstallation("myMaven","/tmp/foo", JenkinsRule.NO_PROPERTIES),"name,home"); + assertEquals(1, l.length); + j.assertEqualBeans(l[0], new MavenInstallation("myMaven", "/tmp/foo", JenkinsRule.NO_PROPERTIES), "name,home"); // by default we should get the auto installer - DescribableList,ToolPropertyDescriptor> props = l[0].getProperties(); - assertEquals(1,props.size()); + DescribableList, ToolPropertyDescriptor> props = l[0].getProperties(); + assertEquals(1, props.size()); InstallSourceProperty isp = props.get(InstallSourceProperty.class); - assertEquals(1,isp.installers.size()); + assertEquals(1, isp.installers.size()); assertNotNull(isp.installers.get(MavenInstaller.class)); } @@ -202,16 +198,12 @@ private void verify() throws Exception { ); project.addProperty(pdb); project.setScm(new ExtractResourceSCM(getClass().getResource("maven-empty.zip"))); - project.getBuildersList().add(new Maven("clean package",null)); - - FreeStyleBuild build = project.scheduleBuild2(0).get(); - @SuppressWarnings("deprecation") - String buildLog = build.getLog(); - assertNotNull(buildLog); - System.out.println(buildLog); - assertFalse(buildLog.contains("-Dpassword=12345")); + project.getBuildersList().add(new Maven("clean package", null)); + + FreeStyleBuild build = j.waitForCompletion(project.scheduleBuild2(0).waitForStart()); + j.assertLogNotContains("-Dpassword=12345", build); } - + @Test public void parametersReferencedFromPropertiesShouldRetainBackslashes() throws Exception { final String properties = "global.path=$GLOBAL_PATH\nmy.path=$PATH\\\\Dir"; @@ -227,45 +219,35 @@ public void parametersReferencedFromPropertiesShouldRetainBackslashes() throws E new EnvironmentVariablesNodeProperty(envVar) )); - FreeStyleBuild build = project.scheduleBuild2(0).get(); - @SuppressWarnings("deprecation") - String buildLog = build.getLog(); - - assertNotNull(buildLog); - assertTrue( - "Parameter my.path should preserve backslashes in:\n" + buildLog, - buildLog.contains("-Dmy.path=C:\\Windows\\Dir") - ); - assertTrue( - "Parameter global.path should preserve backslashes in:\n" + buildLog, - buildLog.contains("-Dglobal.path=D:\\Jenkins") - ); + FreeStyleBuild build = j.waitForCompletion(project.scheduleBuild2(0).waitForStart()); + j.assertLogContains("-Dmy.path=C:\\Windows\\Dir", build); + j.assertLogContains("-Dglobal.path=D:\\Jenkins", build); } @Test public void defaultSettingsProvider() throws Exception { { FreeStyleProject p = j.createFreeStyleProject(); p.getBuildersList().add(new Maven("a", null, "a.pom", "c=d", "-e", true)); - + Maven m = p.getBuildersList().get(Maven.class); assertNotNull(m); assertEquals(DefaultSettingsProvider.class, m.getSettings().getClass()); assertEquals(DefaultGlobalSettingsProvider.class, m.getGlobalSettings().getClass()); } - + { GlobalMavenConfig globalMavenConfig = GlobalMavenConfig.get(); assertNotNull("No global Maven Config available", globalMavenConfig); globalMavenConfig.setSettingsProvider(new FilePathSettingsProvider("/tmp/settings.xml")); globalMavenConfig.setGlobalSettingsProvider(new FilePathGlobalSettingsProvider("/tmp/global-settings.xml")); - + FreeStyleProject p = j.createFreeStyleProject(); p.getBuildersList().add(new Maven("b", null, "b.pom", "c=d", "-e", true)); - + Maven m = p.getBuildersList().get(Maven.class); assertEquals(FilePathSettingsProvider.class, m.getSettings().getClass()); - assertEquals("/tmp/settings.xml", ((FilePathSettingsProvider)m.getSettings()).getPath()); - assertEquals("/tmp/global-settings.xml", ((FilePathGlobalSettingsProvider)m.getGlobalSettings()).getPath()); + assertEquals("/tmp/settings.xml", ((FilePathSettingsProvider) m.getSettings()).getPath()); + assertEquals("/tmp/global-settings.xml", ((FilePathGlobalSettingsProvider) m.getGlobalSettings()).getPath()); } } @@ -319,21 +301,21 @@ public void parametersReferencedFromPropertiesShouldRetainBackslashes() throws E FreeStyleProject p = j.createFreeStyleProject(); p.updateByXml((Source) new StreamSource(getClass().getResourceAsStream("MavenTest/doPassBuildVariablesOptionally.xml"))); - String log = j.buildAndAssertSuccess(p).getLog(); + FreeStyleBuild build = j.buildAndAssertSuccess(p); assertTrue("Build variables injection should be enabled by default when loading from XML", p.getBuildersList().get(Maven.class).isInjectBuildVariables()); - assertTrue("Build variables should be injected by default when loading from XML", log.contains("-DNAME=VALUE")); + j.assertLogContains("-DNAME=VALUE", build); p.getBuildersList().clear(); p.getBuildersList().add(new Maven("--help", maven.getName(), null, null, null, false, null, null, false/*do not inject*/)); - log = j.buildAndAssertSuccess(p).getLog(); - assertFalse("Build variables should not be injected", log.contains("-DNAME=VALUE")); + build = j.buildAndAssertSuccess(p); + j.assertLogNotContains("-DNAME=VALUE", build); p.getBuildersList().clear(); p.getBuildersList().add(new Maven("--help", maven.getName(), null, null, null, false, null, null, true/*do inject*/)); - log = j.buildAndAssertSuccess(p).getLog(); - assertTrue("Build variables should be injected", log.contains("-DNAME=VALUE")); + build = j.buildAndAssertSuccess(p); + j.assertLogContains("-DNAME=VALUE", build); assertFalse("Build variables injection should be disabled by default", new Maven("", "").isInjectBuildVariables()); } @@ -346,16 +328,16 @@ public void parametersReferencedFromPropertiesShouldRetainBackslashes() throws E p.getBuildersList().add(new Maven("--help", maven.getName(), null, properties, null, false, null, null, false/*do not inject build variables*/)); - String log = j.buildAndAssertSuccess(p).getLog(); - assertTrue("Properties should always be injected, even when build variables injection is disabled", - log.contains("-DTEST_PROP1=VAL1") && log.contains("-DTEST_PROP2=VAL2")); + FreeStyleBuild build = j.buildAndAssertSuccess(p); + j.assertLogContains("-DTEST_PROP1=VAL1", build); + j.assertLogContains("-DTEST_PROP2=VAL2", build); p.getBuildersList().clear(); p.getBuildersList().add(new Maven("--help", maven.getName(), null, properties, null, false, null, null, true/*do inject build variables*/)); - log = j.buildAndAssertSuccess(p).getLog(); - assertTrue("Properties should always be injected, even when build variables injection is enabled", - log.contains("-DTEST_PROP1=VAL1") && log.contains("-DTEST_PROP2=VAL2")); + build = j.buildAndAssertSuccess(p); + j.assertLogContains("-DTEST_PROP1=VAL1", build); + j.assertLogContains("-DTEST_PROP2=VAL2", build); } @Issue("JENKINS-34138") diff --git a/test/src/test/java/hudson/tasks/ShellTest.java b/test/src/test/java/hudson/tasks/ShellTest.java index de058c61075f0..a54534b532a3e 100644 --- a/test/src/test/java/hudson/tasks/ShellTest.java +++ b/test/src/test/java/hudson/tasks/ShellTest.java @@ -57,8 +57,8 @@ public void testBasic() throws Exception { public Proc onLaunch(ProcStarter p) { // test the command line argument. List cmds = p.cmds(); - rule.assertStringContains("/bin/sh",cmds.get(0)); - rule.assertStringContains("-xe",cmds.get(1)); + rule.assertStringContains("/bin/sh", cmds.get(0)); + rule.assertStringContains("-xe", cmds.get(1)); assertTrue(new File(cmds.get(2)).exists()); // fake the execution @@ -73,9 +73,9 @@ public Proc onLaunch(ProcStarter p) { p.getBuildersList().add(new Shell("echo abc")); p.setAssignedNode(s); - FreeStyleBuild b = rule.assertBuildStatusSuccess(p.scheduleBuild2(0).get()); + FreeStyleBuild b = rule.buildAndAssertSuccess(p); - assertEquals(1,s.numLaunch); + assertEquals(1, s.numLaunch); assertTrue(IOUtils.toString(b.getLogInputStream(), StandardCharsets.UTF_8).contains("Hudson was here")); } @@ -106,14 +106,14 @@ private void nonZeroExitCodeShouldMakeBuildUnstable(int exitCode) throws Excepti FreeStyleProject p = rule.createFreeStyleProject(); p.getBuildersList().add(createNewShell("", exitCode)); p.setAssignedNode(slave); - rule.assertBuildStatus(Result.UNSTABLE, p.scheduleBuild2(0).get()); + rule.buildAndAssertStatus(Result.UNSTABLE, p); } @Test @Issue("JENKINS-23786") public void unixExitCodes1To255ShouldMakeBuildUnstable() throws Exception { assumeFalse(Functions.isWindows()); - for( int exitCode: new int [] {1, 2, 255}) { + for (int exitCode : new int [] {1, 2, 255}) { nonZeroExitCodeShouldMakeBuildUnstable(exitCode); } } @@ -126,12 +126,12 @@ private void nonZeroExitCodeShouldBreakTheBuildByDefault(int exitCode) throws Ex p = rule.createFreeStyleProject(); p.getBuildersList().add(createNewShell("", null)); p.setAssignedNode(slave); - rule.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0).get()); + rule.buildAndAssertStatus(Result.FAILURE, p); p = rule.createFreeStyleProject(); p.getBuildersList().add(createNewShell("", 0)); p.setAssignedNode(slave); - rule.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0).get()); + rule.buildAndAssertStatus(Result.FAILURE, p); } @Test @@ -139,7 +139,7 @@ private void nonZeroExitCodeShouldBreakTheBuildByDefault(int exitCode) throws Ex public void unixExitCodes1To255ShouldBreakTheBuildByDefault() throws Exception { assumeFalse(Functions.isWindows()); - for( int exitCode: new int [] {1, 2, 255}) { + for (int exitCode : new int [] {1, 2, 255}) { nonZeroExitCodeShouldBreakTheBuildByDefault(exitCode); } } @@ -152,14 +152,14 @@ private void nonZeroExitCodeShouldBreakTheBuildIfNotMatching(int exitCode) throw FreeStyleProject p = rule.createFreeStyleProject(); p.getBuildersList().add(createNewShell("", notMatchingExitCode)); p.setAssignedNode(slave); - rule.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0).get()); + rule.buildAndAssertStatus(Result.FAILURE, p); } @Test @Issue("JENKINS-23786") public void unixExitCodes1To255ShouldBreakTheBuildIfNotMatching() throws Exception { assumeFalse(Functions.isWindows()); - for( int exitCode: new int [] {1, 2, 255}) { + for (int exitCode : new int [] {1, 2, 255}) { nonZeroExitCodeShouldBreakTheBuildIfNotMatching(exitCode); } } @@ -170,11 +170,11 @@ public void unixExitCodes0ShouldNeverMakeTheBuildUnstable() throws Exception { assumeFalse(Functions.isWindows()); PretendSlave slave = rule.createPretendSlave(new ReturnCodeFakeLauncher(0)); - for( Integer unstableReturn: new Integer [] {null, 0, 1}) { + for (Integer unstableReturn : new Integer [] {null, 0, 1}) { FreeStyleProject p = rule.createFreeStyleProject(); p.getBuildersList().add(createNewShell("", unstableReturn)); p.setAssignedNode(slave); - rule.assertBuildStatus(Result.SUCCESS, p.scheduleBuild2(0).get()); + rule.buildAndAssertSuccess(p); } } @@ -184,7 +184,7 @@ public void unixUnstableCodeZeroIsSameAsUnset() { assumeFalse(Functions.isWindows()); /* Creating unstable=0 produces unstable=null */ - assertNull( createNewShell("",0).getUnstableReturn() ); + assertNull(createNewShell("", 0).getUnstableReturn()); } @Issue("JENKINS-40894") diff --git a/test/src/test/java/hudson/tasks/UserAvatarResolverTest.java b/test/src/test/java/hudson/tasks/UserAvatarResolverTest.java index bb123e3c5e403..142ece4b34bc1 100644 --- a/test/src/test/java/hudson/tasks/UserAvatarResolverTest.java +++ b/test/src/test/java/hudson/tasks/UserAvatarResolverTest.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2011, Erik Ramfelt - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.tasks; import static org.hamcrest.MatcherAssert.assertThat; @@ -46,7 +47,7 @@ public class UserAvatarResolverTest { @Test public void defaultImageIsReturnedIfRegexFails() { String avatar = UserAvatarResolver.resolve(User.getOrCreateByIdOrFullName("USER"), "meh"); - assertThat(avatar, endsWith("/images/svgs/person.svg")); + assertThat(avatar, endsWith("symbol-person-circle")); } @Test @@ -59,7 +60,7 @@ public void resolverIsUsed() { @Test public void noResolverCanFindAvatar() { String avatar = UserAvatarResolver.resolve(User.getOrCreateByIdOrFullName("USER"), "20x20"); - assertThat(avatar, endsWith("/images/svgs/person.svg")); + assertThat(avatar, endsWith("symbol-person-circle")); } @Test diff --git a/test/src/test/java/hudson/tools/ToolLocationNodePropertyTest.java b/test/src/test/java/hudson/tools/ToolLocationNodePropertyTest.java index 358c00bff6480..8972a768c4861 100644 --- a/test/src/test/java/hudson/tools/ToolLocationNodePropertyTest.java +++ b/test/src/test/java/hudson/tools/ToolLocationNodePropertyTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.tools; import static org.junit.Assert.assertEquals; @@ -101,7 +102,7 @@ public void formRoundTrip() throws Exception { } private void configureDumpEnvBuilder() { - if(Functions.isWindows()) + if (Functions.isWindows()) project.getBuildersList().add(new BatchFile("set")); else project.getBuildersList().add(new Shell("export")); diff --git a/test/src/test/java/hudson/tools/ZipExtractionInstallerTest.java b/test/src/test/java/hudson/tools/ZipExtractionInstallerTest.java index 8bb0643b8bf38..8d16c789b8a32 100644 --- a/test/src/test/java/hudson/tools/ZipExtractionInstallerTest.java +++ b/test/src/test/java/hudson/tools/ZipExtractionInstallerTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.tools; import static org.hamcrest.MatcherAssert.assertThat; @@ -59,93 +60,93 @@ import org.jvnet.hudson.test.MockAuthorizationStrategy; public class ZipExtractionInstallerTest { - + @Rule public JenkinsRule j = new JenkinsRule(); - + @Rule public TemporaryFolder tmp = new TemporaryFolder(); - + @Test @Issue("SECURITY-794") public void onlyAdminCanReachTheDoCheck() throws Exception { final String ADMIN = "admin"; final String USER = "user"; - + j.jenkins.setCrumbIssuer(null); j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); j.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy() .grant(Jenkins.ADMINISTER).everywhere().to(ADMIN) .grant(Jenkins.READ).everywhere().to(USER) ); - + User.getById(ADMIN, true); User.getById(USER, true); - + WebRequest request = new WebRequest(new URL(j.getURL() + "descriptorByName/hudson.tools.ZipExtractionInstaller/checkUrl"), HttpMethod.POST); request.setRequestBody(URLEncoder.encode("value=https://www.google.com", StandardCharsets.UTF_8.name())); - + JenkinsRule.WebClient adminWc = j.createWebClient(); adminWc.login(ADMIN); assertEquals(HttpURLConnection.HTTP_OK, adminWc.getPage(request).getWebResponse().getStatusCode()); - + JenkinsRule.WebClient userWc = j.createWebClient() .withThrowExceptionOnFailingStatusCode(false); userWc.login(USER); assertEquals(HttpURLConnection.HTTP_FORBIDDEN, userWc.getPage(request).getWebResponse().getStatusCode()); } - + @Test @Issue("SECURITY-794") public void roundtrip() throws Exception { final String VALID_URL = "https://www.google.com"; final String INVALID_URL = "only-crappy-letters"; - + ZipExtractionInstaller installer = new ZipExtractionInstaller("", VALID_URL, ""); - + j.jenkins.getJDKs().add(new JDK("test", tmp.getRoot().getAbsolutePath(), Collections.singletonList( new InstallSourceProperty(Collections.singletonList(installer))))); - + JenkinsRule.WebClient wc = j.createWebClient(); - + SpyingJavaScriptEngine jsEngine = new SpyingJavaScriptEngine(wc, "ZipExtractionInstaller/checkUrl", HttpMethod.POST); wc.setJavaScriptEngine(jsEngine); - + HtmlPage page = wc.goTo("configureTools"); - + XMLHttpRequest lastRequest = jsEngine.getLastRequest(); String body = URLDecoder.decode(getPrivateWebRequestField(lastRequest).getRequestBody(), "UTF-8"); assertThat(body, containsString(VALID_URL)); assertEquals(FormValidation.ok().renderHtml(), lastRequest.getResponseText()); - + HtmlTextInput urlInput = page.getDocumentElement().getOneHtmlElementByAttribute("input", "value", VALID_URL); urlInput.setAttribute("value", INVALID_URL); j.submit(page.getFormByName("config")); - + JDK jdk = j.jenkins.getJDK("test"); InstallSourceProperty isp = jdk.getProperties().get(InstallSourceProperty.class); assertEquals(1, isp.installers.size()); assertEquals(INVALID_URL, isp.installers.get(ZipExtractionInstaller.class).getUrl()); - + wc.goTo("configureTools"); - + lastRequest = jsEngine.getLastRequest(); body = URLDecoder.decode(getPrivateWebRequestField(lastRequest).getRequestBody(), "UTF-8"); assertThat(body, containsString(INVALID_URL)); assertThat(lastRequest.getResponseText(), containsString(Messages.ZipExtractionInstaller_malformed_url())); } - + private static class SpyingJavaScriptEngine extends JavaScriptEngine { private List storedRequests = new ArrayList<>(); private String urlToMatch; private HttpMethod method; - + SpyingJavaScriptEngine(JenkinsRule.WebClient wc, @Nullable String urlToMatch, @Nullable HttpMethod method) { super(wc); this.urlToMatch = urlToMatch; this.method = method; } - + @Override public Object callFunction(HtmlPage page, Function function, Scriptable scope, Scriptable thisObject, Object[] args) { if (thisObject instanceof XMLHttpRequest) { @@ -164,7 +165,7 @@ public Object callFunction(HtmlPage page, Function function, Scriptable scope, S } return super.callFunction(page, function, scope, thisObject, args); } - + @NonNull public XMLHttpRequest getLastRequest() { if (storedRequests.isEmpty()) { @@ -173,7 +174,7 @@ public XMLHttpRequest getLastRequest() { return storedRequests.get(storedRequests.size() - 1); } } - + private static WebRequest getPrivateWebRequestField(XMLHttpRequest xmlHttpRequest) throws NoSuchFieldException, IllegalAccessException { Field webRequest_Field = XMLHttpRequest.class.getDeclaredField("webRequest_"); webRequest_Field.setAccessible(true); diff --git a/test/src/test/java/hudson/triggers/SCMTriggerTest.java b/test/src/test/java/hudson/triggers/SCMTriggerTest.java index faa14acfe940f..bd98b4dd4a6f9 100644 --- a/test/src/test/java/hudson/triggers/SCMTriggerTest.java +++ b/test/src/test/java/hudson/triggers/SCMTriggerTest.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.triggers; import static org.junit.Assert.assertEquals; @@ -82,6 +83,7 @@ public void simultaneousPollAndBuild() throws Exception { p.setScm(new TestSCM(checkoutStarted)); Future build = p.scheduleBuild2(0, new Cause.UserCause()); + assertNotNull(build); checkoutStarted.block(); assertFalse("SCM-poll after build has started should wait until that build finishes SCM-update", p.pollSCMChanges(StreamTaskListener.fromStdout())); build.get(); // let mock build finish @@ -123,7 +125,7 @@ public synchronized boolean pollChanges(AbstractProject project, Launcher launch } @Override - public boolean checkout(AbstractBuild build, Launcher launcher, FilePath remoteDir, BuildListener listener, File changeLogFile) throws IOException, InterruptedException { + public boolean checkout(AbstractBuild build, Launcher launcher, FilePath remoteDir, BuildListener listener, File changeLogFile) throws IOException, InterruptedException { checkoutStarted.signal(); Thread.sleep(400); // processing time for mock update synchronized (this) { if (myRev < 2) myRev = 2; } @@ -151,19 +153,19 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen }); SCMTrigger t = new SCMTrigger("@daily"); - t.start(p,true); + t.start(p, true); p.addTrigger(t); // Start one build to block others - assertTrue(p.scheduleBuild(new Cause.UserCause())); + p.scheduleBuild2(0, new Cause.UserCause()).waitForStart(); buildStarted.block(); // wait for the build to really start // Schedule a new build, and trigger it many ways while it sits in queue Future fb = p.scheduleBuild2(0, new Cause.UserCause()); assertNotNull(fb); - assertTrue(p.scheduleBuild(new SCMTriggerCause("First poll"))); - assertTrue(p.scheduleBuild(new SCMTriggerCause("Second poll"))); - assertTrue(p.scheduleBuild(new SCMTriggerCause("Third poll"))); + assertNotNull(p.scheduleBuild2(0, new SCMTriggerCause("First poll"))); + assertNotNull(p.scheduleBuild2(0, new SCMTriggerCause("Second poll"))); + assertNotNull(p.scheduleBuild2(0, new SCMTriggerCause("Third poll"))); // Wait for 2nd build to finish buildShouldComplete.signal(); diff --git a/test/src/test/java/hudson/triggers/TriggerStartTest.java b/test/src/test/java/hudson/triggers/TriggerStartTest.java index 5762e64ff5f0e..e3aa8fdc474d0 100644 --- a/test/src/test/java/hudson/triggers/TriggerStartTest.java +++ b/test/src/test/java/hudson/triggers/TriggerStartTest.java @@ -34,6 +34,7 @@ import java.io.ByteArrayInputStream; import java.io.ObjectStreamException; import java.io.StringReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import javax.xml.transform.Source; @@ -66,7 +67,7 @@ public class TriggerStartTest { MockTrigger t = new MockTrigger(); p.addTrigger(t); p.save(); - p = (FreeStyleProject)j.configRoundtrip((Item)p); + p = (FreeStyleProject) j.configRoundtrip((Item) p); t = p.getTrigger(MockTrigger.class); assertNotNull(t); assertEquals("[true]", t.calls.toString()); @@ -84,14 +85,16 @@ public class TriggerStartTest { } @Test public void createProjectFromXmlCallsStartTrue() throws Exception { - FreeStyleProject p = (FreeStyleProject) j.jenkins.createProjectFromXML("whatever", new ByteArrayInputStream(("\n \n \n \n" + triggersSection() + "").getBytes())); + FreeStyleProject p = (FreeStyleProject) j.jenkins.createProjectFromXML( + "whatever", + new ByteArrayInputStream(("\n \n \n \n" + triggersSection() + "").getBytes(StandardCharsets.UTF_8))); MockTrigger t = p.getTrigger(MockTrigger.class); assertNotNull(t); assertEquals("[true]", t.calls.toString()); } @Test public void copyCallsStartTrue() throws Exception { - AbstractProject p = j.createFreeStyleProject(); + AbstractProject p = j.createFreeStyleProject(); MockTrigger t = new MockTrigger(); p.addTrigger(t); p.save(); diff --git a/test/src/test/java/hudson/triggers/TriggerTest.java b/test/src/test/java/hudson/triggers/TriggerTest.java index d39d56285bd3c..6638a96d23ab1 100644 --- a/test/src/test/java/hudson/triggers/TriggerTest.java +++ b/test/src/test/java/hudson/triggers/TriggerTest.java @@ -28,6 +28,7 @@ import hudson.Extension; import hudson.model.Item; import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; import java.util.Calendar; import java.util.GregorianCalendar; import org.junit.Rule; @@ -44,7 +45,7 @@ public class TriggerTest { @Issue("JENKINS-36748") @Test public void testNoNPE() throws Exception { - jenkinsRule.getInstance().createProjectFromXML("whatever", new ByteArrayInputStream(("\n \n \n \n" + triggersSection() + "").getBytes())); + jenkinsRule.getInstance().createProjectFromXML("whatever", new ByteArrayInputStream(("\n \n \n \n" + triggersSection() + "").getBytes(StandardCharsets.UTF_8))); final Calendar cal = new GregorianCalendar(); Trigger.checkTriggers(cal); } diff --git a/test/src/test/java/hudson/util/AlternativeUiTextProviderTest.java b/test/src/test/java/hudson/util/AlternativeUiTextProviderTest.java index ffb98641ce652..fc59cbd9b2d98 100644 --- a/test/src/test/java/hudson/util/AlternativeUiTextProviderTest.java +++ b/test/src/test/java/hudson/util/AlternativeUiTextProviderTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.util; import static org.hamcrest.MatcherAssert.assertThat; @@ -45,6 +46,7 @@ public class AlternativeUiTextProviderTest { @TestExtension public static class Impl extends AlternativeUiTextProvider { static boolean oldschool; + @SuppressWarnings("deprecation") @Override public String getText(Message text, T context) { if (oldschool && text == ParameterizedJobMixIn.BUILD_NOW_TEXT) { @@ -64,10 +66,10 @@ public static class Impl extends AlternativeUiTextProvider { public void basics() throws Exception { Impl.oldschool = false; FreeStyleProject p = j.createFreeStyleProject("aaa"); - assertThat(j.createWebClient().getPage(p).asText(), containsString("newschool:aaa")); + assertThat(j.createWebClient().getPage(p).asNormalizedText(), containsString("newschool:aaa")); Impl.oldschool = true; - assertThat(j.createWebClient().getPage(p).asText(), containsString("oldschool:aaa")); + assertThat(j.createWebClient().getPage(p).asNormalizedText(), containsString("oldschool:aaa")); } /** @@ -79,11 +81,11 @@ public void basicsWithParameter() throws Exception { Impl.oldschool = false; FreeStyleProject p = j.createFreeStyleProject("aaa"); p.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("FOO", null))); - String pageText = j.createWebClient().getPage(p).asText(); + String pageText = j.createWebClient().getPage(p).asNormalizedText(); assertThat(pageText, containsString("newschool:aaa")); Impl.oldschool = true; - pageText = j.createWebClient().getPage(p).asText(); + pageText = j.createWebClient().getPage(p).asNormalizedText(); assertThat(pageText, containsString("oldschool:aaa")); } } diff --git a/test/src/test/java/hudson/util/ArgumentListBuilder2Test.java b/test/src/test/java/hudson/util/ArgumentListBuilder2Test.java index 8aef1d53c9f71..897fa0947c88d 100644 --- a/test/src/test/java/hudson/util/ArgumentListBuilder2Test.java +++ b/test/src/test/java/hudson/util/ArgumentListBuilder2Test.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.util; import static org.hamcrest.MatcherAssert.assertThat; @@ -38,6 +39,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.StringWriter; +import java.nio.charset.Charset; import java.util.logging.Level; import jenkins.util.SystemProperties; import org.apache.tools.ant.util.JavaEnvUtils; @@ -74,7 +76,7 @@ public void slaveMask() throws Exception { j.showAgentLogs(s, logging); StringWriter out = new StringWriter(); - assertEquals(0,s.createLauncher(new StreamTaskListener(out)).launch().cmds(args).join()); + assertEquals(0, s.createLauncher(new StreamTaskListener(out)).launch().cmds(args).join()); assertThat(out.toString(), containsString("$ java ********")); } @@ -134,7 +136,7 @@ public String echoArgs(String... arguments) throws Exception { .toWindowsCommand(); ByteArrayOutputStream out = new ByteArrayOutputStream(); - final StreamTaskListener listener = new StreamTaskListener(out); + final StreamTaskListener listener = new StreamTaskListener(out, Charset.defaultCharset()); Proc p = new LocalLauncher(listener) .launch() .stderr(System.err) @@ -146,6 +148,6 @@ public String echoArgs(String... arguments) throws Exception { listener.close(); assumeThat("Failed to run " + args, code, equalTo(0)); - return out.toString(); + return out.toString(Charset.defaultCharset().name()); } } diff --git a/test/src/test/java/hudson/util/BootFailureTest.java b/test/src/test/java/hudson/util/BootFailureTest.java index 22b9b39a19558..adbe0b06081c1 100644 --- a/test/src/test/java/hudson/util/BootFailureTest.java +++ b/test/src/test/java/hudson/util/BootFailureTest.java @@ -30,7 +30,6 @@ import org.jvnet.hudson.test.TestEnvironment; import org.jvnet.hudson.test.TestExtension; import org.kohsuke.stapler.WebApp; -import org.springframework.util.Assert; /** * @@ -71,11 +70,11 @@ public WebAppMain.FileAndDescription getHomeDir(ServletContextEvent event) { ServletContext ws = createWebServer((context, server) -> { NoListenerConfiguration noListenerConfiguration = context.getBean(NoListenerConfiguration.class); // future-proof - Assert.notNull(noListenerConfiguration, "Value must not be null"); + assertNotNull(noListenerConfiguration); if (noListenerConfiguration != null) { context.removeBean(noListenerConfiguration); context.addBean(new AbstractLifeCycle() { - @Override + @Override protected void doStart() { // default behavior of noListenerConfiguration context.setEventListeners(null); @@ -94,6 +93,7 @@ protected void doStart() { return null; // didn't boot } } + @Rule public CustomRule j = new CustomRule(); @@ -164,6 +164,7 @@ public void interruptedStartup() throws Exception { j.newHudson(); assertEquals(Collections.singletonList("1"), runRecord); } + @TestExtension("interruptedStartup") public static class PauseBoot extends ItemListener { @Override diff --git a/test/src/test/java/hudson/util/FormFieldValidatorTest.java b/test/src/test/java/hudson/util/FormFieldValidatorTest.java index 6f3f5824569c9..77bdff51fd192 100644 --- a/test/src/test/java/hudson/util/FormFieldValidatorTest.java +++ b/test/src/test/java/hudson/util/FormFieldValidatorTest.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * 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: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.util; diff --git a/test/src/test/java/hudson/util/FormValidationSecurity1893Test.java b/test/src/test/java/hudson/util/FormValidationSecurity1893Test.java index bd5fa5ec04629..bc4413288aaa2 100644 --- a/test/src/test/java/hudson/util/FormValidationSecurity1893Test.java +++ b/test/src/test/java/hudson/util/FormValidationSecurity1893Test.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.util; import static org.hamcrest.MatcherAssert.assertThat; diff --git a/test/src/test/java/hudson/util/LogTaskListenerTest.java b/test/src/test/java/hudson/util/LogTaskListenerTest.java index 4ac7e7f9d68d3..f1dad026f5d62 100644 --- a/test/src/test/java/hudson/util/LogTaskListenerTest.java +++ b/test/src/test/java/hudson/util/LogTaskListenerTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.util; import static org.junit.Assert.assertEquals; @@ -29,6 +30,7 @@ import hudson.model.TaskListener; import java.util.logging.Level; import java.util.logging.Logger; +import jenkins.security.MasterToSlaveCallable; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; @@ -55,4 +57,28 @@ public void annotations() throws Exception { assertEquals("[plain line, from annotate, from hyperlink, there from encoded]", logging.getMessages().toString()); } + @Test + public void serialization() throws Exception { + TaskListener l = new LogTaskListener(Logger.getLogger("LogTaskListenerTest"), Level.INFO); + r.createOnlineSlave().getChannel().call(new Log(l)); + assertEquals("[from agent]", logging.getMessages().toString()); + } + + private static final class Log extends MasterToSlaveCallable { + + private final TaskListener l; + + Log(TaskListener l) { + this.l = l; + } + + @Override + public Void call() throws RuntimeException { + l.getLogger().println("from agent"); + l.getLogger().flush(); + return null; + } + + } + } diff --git a/test/src/test/java/hudson/util/ProcessTreeTest.java b/test/src/test/java/hudson/util/ProcessTreeTest.java index aa187bb451814..7e0a6e668bb95 100644 --- a/test/src/test/java/hudson/util/ProcessTreeTest.java +++ b/test/src/test/java/hudson/util/ProcessTreeTest.java @@ -83,7 +83,7 @@ public void processProperlyKilledUnix() throws Exception { sleepProject.getBuildersList().add(new Shell("nohup sleep 100000 &")); - j.assertBuildStatusSuccess(sleepProject.scheduleBuild2(0).get()); + j.buildAndAssertSuccess(sleepProject); processJob.getBuildersList().add(new Shell("ps -ef | grep sleep")); diff --git a/test/src/test/java/hudson/util/RingBufferLogHandlerTest.java b/test/src/test/java/hudson/util/RingBufferLogHandlerTest.java index 7c01e12672448..de8a58e01d829 100644 --- a/test/src/test/java/hudson/util/RingBufferLogHandlerTest.java +++ b/test/src/test/java/hudson/util/RingBufferLogHandlerTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.util; import org.junit.Test; @@ -33,7 +34,7 @@ public class RingBufferLogHandlerTest { public void tooMuchRecordsShouldNotCrashHandler() { final RingBufferLogHandler handler = new RingBufferLogHandler(); - for (long i = 0; i < (long)Integer.MAX_VALUE + 300; i++) { + for (long i = 0; i < (long) Integer.MAX_VALUE + 300; i++) { // throws ArrayIndexOutOfBoundsException after int-overflow handler.publish(null); } diff --git a/test/src/test/java/hudson/util/RobustReflectionConverterTest.java b/test/src/test/java/hudson/util/RobustReflectionConverterTest.java index b3e03bd0ad474..eeffdf6a08715 100644 --- a/test/src/test/java/hudson/util/RobustReflectionConverterTest.java +++ b/test/src/test/java/hudson/util/RobustReflectionConverterTest.java @@ -47,6 +47,7 @@ import java.io.ByteArrayInputStream; import java.net.HttpURLConnection; import java.net.URL; +import java.nio.charset.Charset; import java.util.Collections; import java.util.Map; import jenkins.model.Jenkins; @@ -72,12 +73,12 @@ public class RobustReflectionConverterTest { assertNotNull(p); assertTrue("There should be no triggers", p.getTriggers().isEmpty()); OldDataMonitor odm = (OldDataMonitor) r.jenkins.getAdministrativeMonitor("OldData"); - Map data = odm.getData(); + Map data = odm.getData(); assertEquals(Collections.singleton(p), data.keySet()); String text = data.values().iterator().next().extra; assertTrue(text, text.contains("hudson.triggers.TimerTrigger.readResolve")); } - + // Testing describable object to demonstrate what is expected with RobustReflectionConverter#addCriticalField // This should be configured with a specific keyword, // and should reject configurations with other keywords. @@ -87,20 +88,20 @@ public class RobustReflectionConverterTest { public static class AcceptOnlySpecificKeyword extends AbstractDescribableImpl { public static final String ACCEPT_KEYWORD = "accept"; private final String keyword; - + @DataBoundConstructor public AcceptOnlySpecificKeyword(String keyword) { this.keyword = keyword; } - + public String getKeyword() { return keyword; } - + public boolean isAcceptable() { return ACCEPT_KEYWORD.equals(keyword); } - + private Object readResolve() throws Exception { if (!ACL.SYSTEM2.equals(Jenkins.getAuthentication2())) { // called via REST / CLI with authentication @@ -111,14 +112,14 @@ private Object readResolve() throws Exception { } return this; } - + @TestExtension public static class DescriptorImpl extends Descriptor { @Override public String getDisplayName() { return "AcceptOnlySpecificKeyword"; } - + @Override public AcceptOnlySpecificKeyword newInstance(StaplerRequest req, JSONObject formData) throws FormException { @@ -130,31 +131,31 @@ public AcceptOnlySpecificKeyword newInstance(StaplerRequest req, JSONObject form } } } - - public static class KeywordProperty extends JobProperty> { + + public static class KeywordProperty extends JobProperty> { private final AcceptOnlySpecificKeyword nonCriticalField; private final AcceptOnlySpecificKeyword criticalField; - + public KeywordProperty(AcceptOnlySpecificKeyword nonCriticalField, AcceptOnlySpecificKeyword criticalField) { this.nonCriticalField = nonCriticalField; this.criticalField = criticalField; } - + public AcceptOnlySpecificKeyword getNonCriticalField() { return nonCriticalField; } - + public AcceptOnlySpecificKeyword getCriticalField() { return criticalField; } - + @TestExtension public static class DescriptorImpl extends JobPropertyDescriptor { @Override public String getDisplayName() { return "KeywordProperty"; } - + @Override public JobProperty newInstance(StaplerRequest req, JSONObject formData) throws FormException { @@ -169,7 +170,7 @@ public JobProperty newInstance(StaplerRequest req, JSONObject formData) } } } - + private static final String CONFIGURATION_TEMPLATE = "" + "" @@ -184,7 +185,7 @@ public JobProperty newInstance(StaplerRequest req, JSONObject formData) + "" + "" + ""; - + @Test public void testRestInterfaceFailure() throws Exception { Items.XSTREAM2.addCriticalField(KeywordProperty.class, "criticalField"); @@ -197,7 +198,7 @@ public void testRestInterfaceFailure() throws Exception { new AcceptOnlySpecificKeyword(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD) )); p.save(); - + // Configure a bad keyword via REST. r.jenkins.setSecurityRealm(r.createDummySecurityRealm()); WebClient wc = r.createWebClient(); @@ -206,19 +207,19 @@ public void testRestInterfaceFailure() throws Exception { req.setEncodingType(null); req.setRequestBody(String.format(CONFIGURATION_TEMPLATE, "badvalue", AcceptOnlySpecificKeyword.ACCEPT_KEYWORD)); wc.getPage(req); - + // AcceptOnlySpecificKeyword with bad value is not instantiated for rejected with readResolve, assertNull(p.getProperty(KeywordProperty.class).getNonCriticalField()); assertEquals(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD, p.getProperty(KeywordProperty.class).getCriticalField().getKeyword()); - + // but save to the disk. r.jenkins.reload(); - + p = r.jenkins.getItemByFullName(p.getFullName(), FreeStyleProject.class); assertEquals("badvalue", p.getProperty(KeywordProperty.class).getNonCriticalField().getKeyword()); assertEquals(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD, p.getProperty(KeywordProperty.class).getCriticalField().getKeyword()); } - + // with addCriticalField. This is not accepted. { FreeStyleProject p = r.createFreeStyleProject(); @@ -227,7 +228,7 @@ public void testRestInterfaceFailure() throws Exception { new AcceptOnlySpecificKeyword(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD) )); p.save(); - + // Configure a bad keyword via REST. r.jenkins.setSecurityRealm(r.createDummySecurityRealm()); WebClient wc = r.createWebClient() @@ -236,27 +237,27 @@ public void testRestInterfaceFailure() throws Exception { WebRequest req = new WebRequest(new URL(wc.getContextPath() + String.format("%s/config.xml", p.getUrl())), HttpMethod.POST); req.setEncodingType(null); req.setRequestBody(String.format(CONFIGURATION_TEMPLATE, AcceptOnlySpecificKeyword.ACCEPT_KEYWORD, "badvalue")); - + Page page = wc.getPage(req); - assertEquals("Submitting unacceptable configuration via REST should fail.", + assertEquals("Submitting unacceptable configuration via REST should fail.", HttpURLConnection.HTTP_INTERNAL_ERROR, page.getWebResponse().getStatusCode()); - + // Configuration should not be updated for a failure of the critical field, assertNotEquals("badvalue", p.getProperty(KeywordProperty.class).getCriticalField().getKeyword()); - + r.jenkins.reload(); - + // rejected configuration is not saved p = r.jenkins.getItemByFullName(p.getFullName(), FreeStyleProject.class); assertNotEquals("badvalue", p.getProperty(KeywordProperty.class).getCriticalField().getKeyword()); } } - + @Test public void testCliFailure() throws Exception { Items.XSTREAM2.addCriticalField(KeywordProperty.class, "criticalField"); - + // without addCriticalField. This is accepted. { FreeStyleProject p = r.createFreeStyleProject(); @@ -265,31 +266,31 @@ public void testCliFailure() throws Exception { new AcceptOnlySpecificKeyword(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD) )); p.save(); - + // Configure a bad keyword via CLI. r.jenkins.setSecurityRealm(r.createDummySecurityRealm()); - + CLICommandInvoker.Result ret = new CLICommandInvoker(r, "update-job") .asUser("test") - .withStdin(new ByteArrayInputStream(String.format(CONFIGURATION_TEMPLATE, "badvalue", AcceptOnlySpecificKeyword.ACCEPT_KEYWORD).getBytes())) + .withStdin(new ByteArrayInputStream(String.format(CONFIGURATION_TEMPLATE, "badvalue", AcceptOnlySpecificKeyword.ACCEPT_KEYWORD).getBytes(Charset.defaultCharset()))) .withArgs( p.getFullName() ) .invoke(); - + assertEquals(0, ret.returnCode()); - + // AcceptOnlySpecificKeyword with bad value is not instantiated for rejected with readResolve, assertNull(p.getProperty(KeywordProperty.class).getNonCriticalField()); assertEquals(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD, p.getProperty(KeywordProperty.class).getCriticalField().getKeyword()); - + // but save to the disk. r.jenkins.reload(); - + p = r.jenkins.getItemByFullName(p.getFullName(), FreeStyleProject.class); assertEquals("badvalue", p.getProperty(KeywordProperty.class).getNonCriticalField().getKeyword()); } - + // with addCriticalField. This is not accepted. { FreeStyleProject p = r.createFreeStyleProject(); @@ -298,23 +299,23 @@ public void testCliFailure() throws Exception { new AcceptOnlySpecificKeyword(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD) )); p.save(); - + // Configure a bad keyword via CLI. r.jenkins.setSecurityRealm(r.createDummySecurityRealm()); CLICommandInvoker.Result ret = new CLICommandInvoker(r, "update-job") .asUser("test") - .withStdin(new ByteArrayInputStream(String.format(CONFIGURATION_TEMPLATE, AcceptOnlySpecificKeyword.ACCEPT_KEYWORD, "badvalue").getBytes())) + .withStdin(new ByteArrayInputStream(String.format(CONFIGURATION_TEMPLATE, AcceptOnlySpecificKeyword.ACCEPT_KEYWORD, "badvalue").getBytes(Charset.defaultCharset()))) .withArgs( p.getFullName() ) .invoke(); assertNotEquals(0, ret.returnCode()); - + // Configuration should not be updated for a failure of the critical field, assertNotEquals("badvalue", p.getProperty(KeywordProperty.class).getCriticalField().getKeyword()); - + r.jenkins.reload(); - + // rejected configuration is not saved p = r.jenkins.getItemByFullName(p.getFullName(), FreeStyleProject.class); assertNotEquals("badvalue", p.getProperty(KeywordProperty.class).getCriticalField().getKeyword()); diff --git a/test/src/test/java/hudson/util/SecretCompatTest.java b/test/src/test/java/hudson/util/SecretCompatTest.java index 38d0e6b0144f1..d9f5b53726823 100644 --- a/test/src/test/java/hudson/util/SecretCompatTest.java +++ b/test/src/test/java/hudson/util/SecretCompatTest.java @@ -22,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.util; import static org.hamcrest.MatcherAssert.assertThat; diff --git a/test/src/test/java/hudson/util/XStream2AnnotationTest.java b/test/src/test/java/hudson/util/XStream2AnnotationTest.java index 3fd3420250088..6a85ad78a05b3 100644 --- a/test/src/test/java/hudson/util/XStream2AnnotationTest.java +++ b/test/src/test/java/hudson/util/XStream2AnnotationTest.java @@ -77,11 +77,14 @@ public static class AnnotatedProcessed extends GlobalConfiguration { static AnnotatedProcessed get() { return ExtensionList.lookupSingleton(AnnotatedProcessed.class); } + int x; + public AnnotatedProcessed() { getConfigFile().getXStream().processAnnotations(AnnotatedProcessed.class); load(); } + String xml() throws IOException { return getConfigFile().asString().replaceAll("\n *", "").replaceAll("<[?].+?[?]>", ""); } @@ -93,13 +96,17 @@ public static class AnnotatedUnprocessed extends GlobalConfiguration { static AnnotatedUnprocessed get() { return ExtensionList.lookupSingleton(AnnotatedUnprocessed.class); } + int x; + public AnnotatedUnprocessed() { load(); } + String xml() throws IOException { return getConfigFile().asString().replaceAll("\n *", "").replaceAll("<[?].+?[?]>", ""); } + void writeXml(String xml) throws IOException { FileUtils.write(getConfigFile().getFile(), xml, StandardCharsets.UTF_8); } @@ -110,11 +117,14 @@ public static class Programmatic extends GlobalConfiguration { static Programmatic get() { return ExtensionList.lookupSingleton(Programmatic.class); } + int x; + public Programmatic() { getConfigFile().getXStream().alias("myconf-programmatic", Programmatic.class); load(); } + String xml() throws IOException { return getConfigFile().asString().replaceAll("\n *", "").replaceAll("<[?].+?[?]>", ""); } diff --git a/test/src/test/java/hudson/util/XStream2Security383Test.java b/test/src/test/java/hudson/util/XStream2Security383Test.java index 873587c348bbb..84d5fc0b7a521 100644 --- a/test/src/test/java/hudson/util/XStream2Security383Test.java +++ b/test/src/test/java/hudson/util/XStream2Security383Test.java @@ -123,22 +123,27 @@ private static class Stream extends ServletInputStream { public int read() throws IOException { return inner.read(); } + @Override public int read(byte[] b) throws IOException { return inner.read(b); } + @Override public int read(byte[] b, int off, int len) throws IOException { return inner.read(b, off, len); } + @Override public boolean isFinished() { throw new UnsupportedOperationException(); } + @Override public boolean isReady() { throw new UnsupportedOperationException(); } + @Override public void setReadListener(ReadListener readListener) { throw new UnsupportedOperationException(); diff --git a/test/src/test/java/hudson/views/GlobalDefaultViewConfigurationTest.java b/test/src/test/java/hudson/views/GlobalDefaultViewConfigurationTest.java index 8a55ce6122816..ca0a67e4fe426 100644 --- a/test/src/test/java/hudson/views/GlobalDefaultViewConfigurationTest.java +++ b/test/src/test/java/hudson/views/GlobalDefaultViewConfigurationTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package hudson.views; import static org.hamcrest.MatcherAssert.assertThat; @@ -41,27 +42,27 @@ * @author Oleg Nenashev */ public class GlobalDefaultViewConfigurationTest { - + @Rule public JenkinsRule j = new JenkinsRule(); - + @Test @Issue("JENKINS-42717") public void shouldNotFailIfTheDefaultViewIsMissing() { String viewName = "NonExistentView"; GlobalDefaultViewConfiguration c = new GlobalDefaultViewConfiguration(); - + StaplerRequest create = new MockStaplerRequestBuilder(j, "/configure").build(); JSONObject params = new JSONObject(); params.accumulate("primaryView", viewName); try { c.configure(create, params); - } catch(Descriptor.FormException ex) { - assertThat("Wrong exception message for the form failure", + } catch (Descriptor.FormException ex) { + assertThat("Wrong exception message for the form failure", ex.getMessage(), containsString(Messages.GlobalDefaultViewConfiguration_ViewDoesNotExist(viewName))); return; } Assert.fail("Expected FormException"); } - + } diff --git a/test/src/test/java/hudson/widgets/HistoryWidgetTest.java b/test/src/test/java/hudson/widgets/HistoryWidgetTest.java index fd28e63f19304..e1658c96949ac 100644 --- a/test/src/test/java/hudson/widgets/HistoryWidgetTest.java +++ b/test/src/test/java/hudson/widgets/HistoryWidgetTest.java @@ -16,7 +16,7 @@ public class HistoryWidgetTest { public void moreLink() throws Exception { FreeStyleProject p = j.createFreeStyleProject(); for (int x = 0; x < 3; x++) { - j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + j.buildAndAssertSuccess(p); } JenkinsRule.WebClient wc = j.createWebClient(); diff --git a/test/src/test/java/jenkins/AgentProtocolTest.java b/test/src/test/java/jenkins/AgentProtocolTest.java index 3f0bac4e22654..a82b449496f63 100644 --- a/test/src/test/java/jenkins/AgentProtocolTest.java +++ b/test/src/test/java/jenkins/AgentProtocolTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins; import static org.junit.Assert.fail; @@ -38,11 +39,11 @@ /** * Tests for {@link AgentProtocol}. - * + * * @author Oleg Nenashev */ public class AgentProtocolTest { - + @Rule public JenkinsRule j = new JenkinsRule(); @@ -54,19 +55,19 @@ public void testShouldNotOverrideUserConfiguration() throws Exception { assertDisabled("JNLP2-connect", "JNLP4-connect"); assertProtocols(true, "System protocols should be always enabled", "Ping"); } - + private void assertEnabled(String ... protocolNames) { - assertProtocols(true, null, protocolNames); + assertProtocols(true, null, protocolNames); } - + private void assertDisabled(String ... protocolNames) { - assertProtocols(false, null, protocolNames); + assertProtocols(false, null, protocolNames); } - + private void assertProtocols(boolean shouldBeEnabled, @CheckForNull String why, String ... protocolNames) { assertProtocols(j.jenkins, shouldBeEnabled, why, protocolNames); } - + public static void assertProtocols(Jenkins jenkins, boolean shouldBeEnabled, @CheckForNull String why, String ... protocolNames) { Set agentProtocols = jenkins.getAgentProtocols(); List failedChecks = new ArrayList<>(); @@ -78,7 +79,7 @@ public static void assertProtocols(Jenkins jenkins, boolean shouldBeEnabled, @Ch failedChecks.add(protocol); } } - + if (!failedChecks.isEmpty()) { String message = String.format("Protocol(s) are not %s: %s. %sEnabled protocols: %s", shouldBeEnabled ? "enabled" : "disabled", @@ -88,5 +89,5 @@ public static void assertProtocols(Jenkins jenkins, boolean shouldBeEnabled, @Ch fail(message); } } - + } diff --git a/test/src/test/java/jenkins/CoreJellyTest.java b/test/src/test/java/jenkins/CoreJellyTest.java index b0d3ea6a500c3..ca00e4b30e0fa 100644 --- a/test/src/test/java/jenkins/CoreJellyTest.java +++ b/test/src/test/java/jenkins/CoreJellyTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins; import hudson.remoting.Which; @@ -36,6 +37,6 @@ */ public class CoreJellyTest extends TestCase { public static Test suite() throws Exception { - return JellyTestSuiteBuilder.build(Which.jarFile(Jenkins.class),true); + return JellyTestSuiteBuilder.build(Which.jarFile(Jenkins.class), true); } } diff --git a/test/src/test/java/jenkins/CorePropertiesTest.java b/test/src/test/java/jenkins/CorePropertiesTest.java index 7aab2c2ac32c3..fe4524d7b2573 100644 --- a/test/src/test/java/jenkins/CorePropertiesTest.java +++ b/test/src/test/java/jenkins/CorePropertiesTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins; import hudson.remoting.Which; diff --git a/test/src/test/java/jenkins/I18nTest.java b/test/src/test/java/jenkins/I18nTest.java index 3574be339bae0..b9bf1f957a612 100644 --- a/test/src/test/java/jenkins/I18nTest.java +++ b/test/src/test/java/jenkins/I18nTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins; import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; diff --git a/test/src/test/java/jenkins/TestJnlpSlaveAgentProtocol.java b/test/src/test/java/jenkins/TestJnlpSlaveAgentProtocol.java index b228e111c2f23..2dfc884ecdf57 100644 --- a/test/src/test/java/jenkins/TestJnlpSlaveAgentProtocol.java +++ b/test/src/test/java/jenkins/TestJnlpSlaveAgentProtocol.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins; import hudson.Extension; diff --git a/test/src/test/java/jenkins/TestJnlpSlaveAgentProtocol2.java b/test/src/test/java/jenkins/TestJnlpSlaveAgentProtocol2.java index a7818f99a53b8..1cb630b33f552 100644 --- a/test/src/test/java/jenkins/TestJnlpSlaveAgentProtocol2.java +++ b/test/src/test/java/jenkins/TestJnlpSlaveAgentProtocol2.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins; import hudson.Extension; diff --git a/test/src/test/java/jenkins/TestJnlpSlaveAgentProtocol3.java b/test/src/test/java/jenkins/TestJnlpSlaveAgentProtocol3.java index dcc38a2bed5ac..e3a80c11e57dc 100644 --- a/test/src/test/java/jenkins/TestJnlpSlaveAgentProtocol3.java +++ b/test/src/test/java/jenkins/TestJnlpSlaveAgentProtocol3.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins; import hudson.Extension; diff --git a/test/src/test/java/jenkins/agents/WebSocketAgentsTest.java b/test/src/test/java/jenkins/agents/WebSocketAgentsTest.java index 3b82cd784e620..d26883f5a28ad 100644 --- a/test/src/test/java/jenkins/agents/WebSocketAgentsTest.java +++ b/test/src/test/java/jenkins/agents/WebSocketAgentsTest.java @@ -38,6 +38,7 @@ import hudson.tasks.BatchFile; import hudson.tasks.Shell; import java.io.File; +import java.nio.charset.StandardCharsets; import java.util.Random; import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; @@ -136,7 +137,7 @@ private FatTask() { @Override public String call() { - return new String(payload); + return new String(payload, StandardCharsets.UTF_8); } } diff --git a/test/src/test/java/jenkins/bugs/Jenkins19124Test.java b/test/src/test/java/jenkins/bugs/Jenkins19124Test.java index b288a060ce2f3..cf11cf90b9e1a 100644 --- a/test/src/test/java/jenkins/bugs/Jenkins19124Test.java +++ b/test/src/test/java/jenkins/bugs/Jenkins19124Test.java @@ -62,6 +62,7 @@ public static class Foo extends Builder { public String getAlpha() { return "alpha"; } + public String getBravo() { return "2"; } diff --git a/test/src/test/java/jenkins/bugs/Jenkins41511Test.java b/test/src/test/java/jenkins/bugs/Jenkins41511Test.java index 91fcd92a4cb57..25666fc73493b 100644 --- a/test/src/test/java/jenkins/bugs/Jenkins41511Test.java +++ b/test/src/test/java/jenkins/bugs/Jenkins41511Test.java @@ -11,8 +11,8 @@ public class Jenkins41511Test { @BeforeClass public static void setUpClass() { - System.setProperty(Jenkins.class.getName()+".slaveAgentPort", "10000"); - System.setProperty(Jenkins.class.getName()+".slaveAgentPortEnforce", "true"); + System.setProperty(Jenkins.class.getName() + ".slaveAgentPort", "10000"); + System.setProperty(Jenkins.class.getName() + ".slaveAgentPortEnforce", "true"); } @Rule diff --git a/test/src/test/java/jenkins/bugs/Jenkins64991Test.java b/test/src/test/java/jenkins/bugs/Jenkins64991Test.java index 36b4163fff65d..e9e010842bc1c 100644 --- a/test/src/test/java/jenkins/bugs/Jenkins64991Test.java +++ b/test/src/test/java/jenkins/bugs/Jenkins64991Test.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.bugs; import static org.hamcrest.CoreMatchers.containsStringIgnoringCase; @@ -80,8 +81,8 @@ public void test403Redirect() throws Exception { assertTrue(loginPage.isHtmlPage()); assertThat(loginPage.getUrl().toExternalForm(), containsStringIgnoringCase("%2Fmanage")); - ((HtmlTextInput)loginPage.getElementByName("j_username")).setText("alice"); - ((HtmlPasswordInput)loginPage.getElementByName("j_password")).setText("alice"); + ((HtmlTextInput) loginPage.getElementByName("j_username")).setText("alice"); + ((HtmlPasswordInput) loginPage.getElementByName("j_password")).setText("alice"); final Page redirectedPage = HtmlFormUtil.submit(loginPage.getFormByName("login")); assertTrue(redirectedPage.isHtmlPage()); @@ -104,8 +105,8 @@ public void testRedirect() throws Exception { assertThat(loginPage.getUrl().toExternalForm(), endsWithIgnoringCase("%2F")); HtmlPage loginHtmlPage = (HtmlPage) loginPage; - ((HtmlTextInput)loginHtmlPage.getElementByName("j_username")).setText("alice"); - ((HtmlPasswordInput)loginHtmlPage.getElementByName("j_password")).setText("alice"); + ((HtmlTextInput) loginHtmlPage.getElementByName("j_username")).setText("alice"); + ((HtmlPasswordInput) loginHtmlPage.getElementByName("j_password")).setText("alice"); final Page redirectedPage = HtmlFormUtil.submit(loginHtmlPage.getFormByName("login")); assertTrue(redirectedPage.isHtmlPage()); @@ -119,8 +120,8 @@ public void withoutFrom() throws Exception { assertTrue(loginPage.isHtmlPage()); - ((HtmlTextInput)loginPage.getElementByName("j_username")).setText("alice"); - ((HtmlPasswordInput)loginPage.getElementByName("j_password")).setText("alice"); + ((HtmlTextInput) loginPage.getElementByName("j_username")).setText("alice"); + ((HtmlPasswordInput) loginPage.getElementByName("j_password")).setText("alice"); final Page redirectedPage = HtmlFormUtil.submit(loginPage.getFormByName("login")); assertTrue(redirectedPage.isHtmlPage()); @@ -134,8 +135,8 @@ public void emptyFrom() throws Exception { assertTrue(loginPage.isHtmlPage()); - ((HtmlTextInput)loginPage.getElementByName("j_username")).setText("alice"); - ((HtmlPasswordInput)loginPage.getElementByName("j_password")).setText("alice"); + ((HtmlTextInput) loginPage.getElementByName("j_username")).setText("alice"); + ((HtmlPasswordInput) loginPage.getElementByName("j_password")).setText("alice"); final Page redirectedPage = HtmlFormUtil.submit(loginPage.getFormByName("login")); assertTrue(redirectedPage.isHtmlPage()); @@ -159,8 +160,8 @@ public void testRedirectToProject() throws Exception { assertThat(loginPage.getUrl().toExternalForm(), endsWithIgnoringCase("%2Fjob%2Ffoo%2520bar%2F")); HtmlPage loginHtmlPage = (HtmlPage) loginPage; - ((HtmlTextInput)loginHtmlPage.getElementByName("j_username")).setText("alice"); - ((HtmlPasswordInput)loginHtmlPage.getElementByName("j_password")).setText("alice"); + ((HtmlTextInput) loginHtmlPage.getElementByName("j_username")).setText("alice"); + ((HtmlPasswordInput) loginHtmlPage.getElementByName("j_password")).setText("alice"); final Page redirectedPage = HtmlFormUtil.submit(loginHtmlPage.getFormByName("login")); assertTrue(redirectedPage.isHtmlPage()); @@ -195,8 +196,8 @@ private void assertNoOpenRedirect(String loginUrl) throws IOException, SAXExcept final HtmlPage loginPage = webClient.goTo(loginUrl); assertTrue(loginPage.isHtmlPage()); - ((HtmlTextInput)loginPage.getElementById("j_username")).setText("alice"); - ((HtmlPasswordInput)loginPage.getElementByName("j_password")).setText("alice"); + ((HtmlTextInput) loginPage.getElementById("j_username")).setText("alice"); + ((HtmlPasswordInput) loginPage.getElementByName("j_password")).setText("alice"); final Page redirectedPage = HtmlFormUtil.submit(loginPage.getFormByName("login")); assertTrue(redirectedPage.isHtmlPage()); diff --git a/test/src/test/java/jenkins/cli/StopBuildsCommandTest.java b/test/src/test/java/jenkins/cli/StopBuildsCommandTest.java index 7de846f7bd3fd..77c139038aa88 100644 --- a/test/src/test/java/jenkins/cli/StopBuildsCommandTest.java +++ b/test/src/test/java/jenkins/cli/StopBuildsCommandTest.java @@ -21,29 +21,29 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.cli; import static java.util.Arrays.asList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsEqual.equalTo; -import hudson.Functions; import hudson.cli.CLICommand; import hudson.cli.CLICommandInvoker; import hudson.model.FreeStyleBuild; import hudson.model.FreeStyleProject; import hudson.model.Item; -import hudson.tasks.BatchFile; -import hudson.tasks.Builder; -import hudson.tasks.Shell; +import hudson.model.Result; import java.io.IOException; import java.util.Collections; import java.util.List; +import java.util.concurrent.TimeUnit; import jenkins.model.Jenkins; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.MockAuthorizationStrategy; +import org.jvnet.hudson.test.SleepBuilder; public class StopBuildsCommandTest { @@ -57,20 +57,20 @@ public class StopBuildsCommandTest { @Test public void shouldStopLastBuild() throws Exception { final FreeStyleProject project = createLongRunningProject(TEST_JOB_NAME); - project.scheduleBuild2(0).waitForStart(); + FreeStyleBuild build = project.scheduleBuild2(0).waitForStart(); + j.waitForMessage("Sleeping", build); final String stdout = runWith(Collections.singletonList(TEST_JOB_NAME)).stdout(); assertThat(stdout, equalTo("Build '#1' stopped for job 'jobName'" + LN)); - waitForLastBuildToStop(project); + j.assertBuildStatus(Result.ABORTED, j.waitForCompletion(build)); } @Test public void shouldNotStopEndedBuild() throws Exception { final FreeStyleProject project = j.createFreeStyleProject(TEST_JOB_NAME); - project.getBuildersList().add(createScriptBuilder("echo 1")); - project.scheduleBuild2(0).waitForStart(); - waitForLastBuildToStop(project); + project.getBuildersList().add(new SleepBuilder(TimeUnit.SECONDS.toMillis(1))); + j.buildAndAssertSuccess(project); final String out = runWith(Collections.singletonList(TEST_JOB_NAME)).stdout(); @@ -82,14 +82,17 @@ public void shouldStopSeveralWorkingBuilds() throws Exception { final FreeStyleProject project = createLongRunningProject(TEST_JOB_NAME); project.setConcurrentBuild(true); - project.scheduleBuild2(0).waitForStart(); - project.scheduleBuild2(0).waitForStart(); + FreeStyleBuild b1 = project.scheduleBuild2(0).waitForStart(); + j.waitForMessage("Sleeping", b1); + FreeStyleBuild b2 = project.scheduleBuild2(0).waitForStart(); + j.waitForMessage("Sleeping", b2); final String stdout = runWith(Collections.singletonList(TEST_JOB_NAME)).stdout(); assertThat(stdout, equalTo("Build '#2' stopped for job 'jobName'" + LN + "Build '#1' stopped for job 'jobName'" + LN)); - waitForLastBuildToStop(project); + j.assertBuildStatus(Result.ABORTED, j.waitForCompletion(b1)); + j.assertBuildStatus(Result.ABORTED, j.waitForCompletion(b2)); } @Test @@ -131,6 +134,7 @@ public void shouldReportBuildStopError() throws Exception { grant(Item.READ).onItems(project).toEveryone(). grant(Item.CANCEL).onItems(project).toAuthenticated()); FreeStyleBuild build = project.scheduleBuild2(0).waitForStart(); + j.waitForMessage("Sleeping", build); final String stdout = runWith(Collections.singletonList(TEST_JOB_NAME)).stdout(); @@ -140,7 +144,7 @@ public void shouldReportBuildStopError() throws Exception { "No builds stopped" + LN)); build.doStop(); - j.waitForCompletion(build); + j.assertBuildStatus(Result.ABORTED, j.waitForCompletion(build)); } @Test @@ -157,7 +161,9 @@ public void shouldStopSecondJobEvenIfFirstStopFailed() throws Exception { grant(Item.CANCEL).onItems(project).toEveryone()); FreeStyleBuild b1 = restrictedProject.scheduleBuild2(0).waitForStart(); + j.waitForMessage("Sleeping", b1); FreeStyleBuild b2 = project.scheduleBuild2(0).waitForStart(); + j.waitForMessage("Sleeping", b2); final String stdout = runWith(asList(TEST_JOB_NAME, TEST_JOB_NAME_2)).stdout(); @@ -168,8 +174,8 @@ public void shouldStopSecondJobEvenIfFirstStopFailed() throws Exception { b1.doStop(); b2.doStop(); - j.waitForCompletion(b1); - j.waitForCompletion(b2); + j.assertBuildStatus(Result.ABORTED, j.waitForCompletion(b1)); + j.assertBuildStatus(Result.ABORTED, j.waitForCompletion(b2)); } private CLICommandInvoker.Result runWith(final List jobNames) throws Exception { @@ -182,32 +188,23 @@ private void setupAndAssertTwoBuildsStop(final List inputNames) throws E final FreeStyleProject project = createLongRunningProject(TEST_JOB_NAME); final FreeStyleProject project2 = createLongRunningProject(TEST_JOB_NAME_2); - project.scheduleBuild2(0).waitForStart(); - project2.scheduleBuild2(0).waitForStart(); + FreeStyleBuild b1 = project.scheduleBuild2(0).waitForStart(); + j.waitForMessage("Sleeping", b1); + FreeStyleBuild b2 = project2.scheduleBuild2(0).waitForStart(); + j.waitForMessage("Sleeping", b2); final String stdout = runWith(inputNames).stdout(); assertThat(stdout, equalTo("Build '#1' stopped for job 'jobName'" + LN + "Build '#1' stopped for job 'jobName2'" + LN)); - waitForLastBuildToStop(project); - waitForLastBuildToStop(project2); + j.assertBuildStatus(Result.ABORTED, j.waitForCompletion(b1)); + j.assertBuildStatus(Result.ABORTED, j.waitForCompletion(b2)); } private FreeStyleProject createLongRunningProject(final String jobName) throws IOException { final FreeStyleProject project = j.createFreeStyleProject(jobName); - project.getBuildersList().add(createScriptBuilder("sleep 50000")); + project.getBuildersList().add(new SleepBuilder(Long.MAX_VALUE)); return project; } - - private Builder createScriptBuilder(String script) { - return Functions.isWindows() ? new BatchFile(script) : new Shell(script); - } - - private void waitForLastBuildToStop(final FreeStyleProject project) throws InterruptedException { - while (project.getLastBuild().isBuilding()) { - Thread.sleep(500); - } - assertThat(project.getLastBuild().isBuilding(), equalTo(false)); - } } diff --git a/test/src/test/java/jenkins/diagnostics/ControllerExecutorsAgentsTest.java b/test/src/test/java/jenkins/diagnostics/ControllerExecutorsAgentsTest.java index 27cdedca00d10..7ff072b3c9c7b 100644 --- a/test/src/test/java/jenkins/diagnostics/ControllerExecutorsAgentsTest.java +++ b/test/src/test/java/jenkins/diagnostics/ControllerExecutorsAgentsTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.diagnostics; import static org.junit.Assert.assertFalse; @@ -34,10 +35,10 @@ import org.jvnet.hudson.test.JenkinsRule; public class ControllerExecutorsAgentsTest { - + @Rule public JenkinsRule j = new JenkinsRule(); - + @Test public void testInitial() { ControllerExecutorsAgents monitor = j.jenkins.getExtensionList(AdministrativeMonitor.class).get(ControllerExecutorsAgents.class); diff --git a/test/src/test/java/jenkins/diagnostics/ControllerExecutorsNoAgentsTest.java b/test/src/test/java/jenkins/diagnostics/ControllerExecutorsNoAgentsTest.java index 4ef6291820904..a0d7485da5875 100644 --- a/test/src/test/java/jenkins/diagnostics/ControllerExecutorsNoAgentsTest.java +++ b/test/src/test/java/jenkins/diagnostics/ControllerExecutorsNoAgentsTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.diagnostics; import static org.junit.Assert.assertFalse; @@ -35,10 +36,10 @@ import org.jvnet.hudson.test.JenkinsRule; public class ControllerExecutorsNoAgentsTest { - + @Rule public JenkinsRule j = new JenkinsRule(); - + @Test public void testInitial() { ControllerExecutorsNoAgents monitor = j.jenkins.getExtensionList(AdministrativeMonitor.class).get(ControllerExecutorsNoAgents.class); diff --git a/test/src/test/java/jenkins/diagnostics/RootUrlNotSetMonitorTest.java b/test/src/test/java/jenkins/diagnostics/RootUrlNotSetMonitorTest.java index 47defcd3b229a..decee0412bea5 100644 --- a/test/src/test/java/jenkins/diagnostics/RootUrlNotSetMonitorTest.java +++ b/test/src/test/java/jenkins/diagnostics/RootUrlNotSetMonitorTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.diagnostics; import static org.junit.Assert.assertFalse; @@ -35,30 +36,30 @@ import org.jvnet.hudson.test.JenkinsRule; public class RootUrlNotSetMonitorTest { - + @Rule public JenkinsRule j = new JenkinsRule(); - + @Test @Issue("JENKINS-31661") public void testWithRootUrl_configured() { // test relies on the default JTH behavior JenkinsLocationConfiguration config = JenkinsLocationConfiguration.get(); assertTrue(StringUtils.isNotBlank(config.getUrl())); - + RootUrlNotSetMonitor monitor = j.jenkins.getExtensionList(AdministrativeMonitor.class).get(RootUrlNotSetMonitor.class); assertFalse("Monitor must not be activated", monitor.isActivated()); - + config.setUrl(null); - + assertTrue("Monitor must be activated", monitor.isActivated()); - + config.setUrl("ftp://localhost:8080/jenkins"); - + assertTrue("Monitor must be activated", monitor.isActivated()); - + config.setUrl("http://localhost:8080/jenkins"); - + assertFalse("Monitor must be activated", monitor.isActivated()); } } diff --git a/test/src/test/java/jenkins/fingerprints/FingerprintStorageTest.java b/test/src/test/java/jenkins/fingerprints/FingerprintStorageTest.java index 8f1405b433a1b..42ac0ac9db097 100644 --- a/test/src/test/java/jenkins/fingerprints/FingerprintStorageTest.java +++ b/test/src/test/java/jenkins/fingerprints/FingerprintStorageTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.fingerprints; import static org.hamcrest.MatcherAssert.assertThat; diff --git a/test/src/test/java/jenkins/install/InstallStateTest.java b/test/src/test/java/jenkins/install/InstallStateTest.java index 17e76721ceddc..1b129f30a8000 100644 --- a/test/src/test/java/jenkins/install/InstallStateTest.java +++ b/test/src/test/java/jenkins/install/InstallStateTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.install; import static org.hamcrest.CoreMatchers.equalTo; @@ -45,23 +46,23 @@ */ @Category(SmokeTest.class) public class InstallStateTest { - + @Rule public JenkinsRule j = new JenkinsRule(); - + @Test public void shouldPerformCorrectConversionForAllNames() { ExtensionList states = InstallState.all(); for (InstallState state : states) { InstallState afterRoundtrip = forName(state.name()); // It also prevents occasional name duplications - assertThat("State after the roundtrip must be equal to the original state", + assertThat("State after the roundtrip must be equal to the original state", afterRoundtrip, equalTo(state)); - assertSame("State " + state + " should return the extension point instance after deserialization", + assertSame("State " + state + " should return the extension point instance after deserialization", afterRoundtrip, state); } } - + @Test @Issue("JENKINS-35206") public void shouldNotFailOnNullXMLField() { @@ -71,21 +72,21 @@ public void shouldNotFailOnNullXMLField() { final InstallState state = forXml(xml); assertThat(state, equalTo(InstallState.UNKNOWN)); } - + @Test @Issue("JENKINS-35206") public void shouldNotFailOnEmptyName() { final InstallState state = forName(""); assertThat(state, equalTo(InstallState.UNKNOWN)); } - + @Test @Issue("JENKINS-35206") public void shouldReturnUnknownStateForUnknownName() { final InstallState state = forName("NonExistentStateName"); assertThat(state, equalTo(InstallState.UNKNOWN)); } - + private static InstallState forName(String name) { String xml = "\n" + " true\n" + @@ -93,7 +94,7 @@ private static InstallState forName(String name) { ""; return forXml(xml); } - + private static InstallState forXml(String xml) { Object read = Jenkins.XSTREAM2.fromXML(xml); assertThat(read, instanceOf(InstallState.class)); diff --git a/test/src/test/java/jenkins/install/InstallUtilTest.java b/test/src/test/java/jenkins/install/InstallUtilTest.java index 40cb8809eecda..c018b6e406648 100644 --- a/test/src/test/java/jenkins/install/InstallUtilTest.java +++ b/test/src/test/java/jenkins/install/InstallUtilTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.install; import hudson.Main; @@ -86,7 +87,7 @@ public void tearDown() { public void test_typeTransitions() throws IOException, ServletException { InstallUtil.getLastExecVersionFile().delete(); InstallUtil.getConfigFile().delete(); - + // A new test instance sets up security first Assert.assertEquals(InstallState.INITIAL_SECURITY_SETUP, InstallUtil.getNextInstallState(InstallState.UNKNOWN)); @@ -148,62 +149,59 @@ private void setStoredVersion(String version) throws Exception { public void testSaveAndRestoreInstallingPlugins() throws Exception { final List updates = new ArrayList<>(); - final Map nameMap = new HashMap<>(); + final Map nameMap = new HashMap<>(); new UpdateCenter() { // inner classes... - { - new UpdateSite("foo", "http://omg.org") { - { - for(String name : Arrays.asList("pending-plug:Pending", "installing-plug:Installing", "failure-plug:Failure", "success-plug:Success")) { - String statusType = name.split(":")[1]; - name = name.split(":")[0]; - - InstallationStatus status; - if("Success".equals(statusType)) { - status = Mockito.mock(Success.class, Mockito.CALLS_REAL_METHODS); - } - else if("Failure".equals(statusType)) { - status = Mockito.mock(Failure.class, Mockito.CALLS_REAL_METHODS); - } - else if("Installing".equals(statusType)) { - status = Mockito.mock(Installing.class, Mockito.CALLS_REAL_METHODS); - } - else { - status = Mockito.mock(Pending.class, Mockito.CALLS_REAL_METHODS); - } - - nameMap.put(statusType, status.getClass().getSimpleName()); - - JSONObject json = new JSONObject(); - json.put("name", name); - json.put("version", "1.1"); - json.put("url", "http://google.com"); - json.put("dependencies", new JSONArray()); - Plugin p = new Plugin(getId(), json); - - InstallationJob job = new InstallationJob(p, null, (Authentication) null, false); - job.status = status; - job.setCorrelationId(UUID.randomUUID()); // this indicates the plugin was 'directly selected' - updates.add(job); - } - } - }; - } + { + new UpdateSite("foo", "http://omg.org") { + { + for (String name : Arrays.asList("pending-plug:Pending", "installing-plug:Installing", "failure-plug:Failure", "success-plug:Success")) { + String statusType = name.split(":")[1]; + name = name.split(":")[0]; + + InstallationStatus status; + if ("Success".equals(statusType)) { + status = Mockito.mock(Success.class, Mockito.CALLS_REAL_METHODS); + } else if ("Failure".equals(statusType)) { + status = Mockito.mock(Failure.class, Mockito.CALLS_REAL_METHODS); + } else if ("Installing".equals(statusType)) { + status = Mockito.mock(Installing.class, Mockito.CALLS_REAL_METHODS); + } else { + status = Mockito.mock(Pending.class, Mockito.CALLS_REAL_METHODS); + } + + nameMap.put(statusType, status.getClass().getSimpleName()); + + JSONObject json = new JSONObject(); + json.put("name", name); + json.put("version", "1.1"); + json.put("url", "http://google.com"); + json.put("dependencies", new JSONArray()); + Plugin p = new Plugin(getId(), json); + + InstallationJob job = new InstallationJob(p, null, (Authentication) null, false); + job.status = status; + job.setCorrelationId(UUID.randomUUID()); // this indicates the plugin was 'directly selected' + updates.add(job); + } + } + }; + } }; InstallUtil.persistInstallStatus(updates); - Map persisted = InstallUtil.getPersistedInstallStatus(); + Map persisted = InstallUtil.getPersistedInstallStatus(); - Assert.assertEquals(nameMap.get("Pending"), persisted.get("pending-plug")); - Assert.assertEquals("Pending", persisted.get("installing-plug")); // only marked as success/fail after successful install - Assert.assertEquals(nameMap.get("Failure"), persisted.get("failure-plug")); - Assert.assertEquals(nameMap.get("Success"), persisted.get("success-plug")); + Assert.assertEquals(nameMap.get("Pending"), persisted.get("pending-plug")); + Assert.assertEquals("Pending", persisted.get("installing-plug")); // only marked as success/fail after successful install + Assert.assertEquals(nameMap.get("Failure"), persisted.get("failure-plug")); + Assert.assertEquals(nameMap.get("Success"), persisted.get("success-plug")); InstallUtil.clearInstallStatus(); - persisted = InstallUtil.getPersistedInstallStatus(); + persisted = InstallUtil.getPersistedInstallStatus(); - Assert.assertNull(persisted); // should be deleted + Assert.assertNull(persisted); // should be deleted } } diff --git a/test/src/test/java/jenkins/install/LoadDetachedPluginsTest.java b/test/src/test/java/jenkins/install/LoadDetachedPluginsTest.java index 265992bf37e11..29c2b7317c329 100644 --- a/test/src/test/java/jenkins/install/LoadDetachedPluginsTest.java +++ b/test/src/test/java/jenkins/install/LoadDetachedPluginsTest.java @@ -36,6 +36,7 @@ import static org.junit.Assert.assertTrue; import hudson.ClassicPluginStrategy; +import hudson.ExtensionList; import hudson.PluginManager; import hudson.PluginManagerUtil; import hudson.PluginWrapper; @@ -47,6 +48,8 @@ import java.util.stream.Collectors; import jenkins.plugins.DetachedPluginsUtil; import jenkins.plugins.DetachedPluginsUtil.DetachedPlugin; +import jenkins.security.UpdateSiteWarningsMonitor; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -67,7 +70,7 @@ public class LoadDetachedPluginsTest { @Test @LocalData public void upgradeFromJenkins1() throws IOException { - VersionNumber since = new VersionNumber("1.550"); + VersionNumber since = new VersionNumber("1.490"); rr.then(r -> { List detachedPlugins = DetachedPluginsUtil.getDetachedPlugins(since); assertThat("Plugins have been detached since the pre-upgrade version", @@ -78,6 +81,17 @@ public void upgradeFromJenkins1() throws IOException { }); } + @Test + @Ignore("Only useful while updating bundled plugins, otherwise new security warnings fail unrelated builds") + @LocalData + public void noUpdateSiteWarnings() { + rr.then(r -> { + r.jenkins.getUpdateCenter().updateAllSites(); + final UpdateSiteWarningsMonitor monitor = ExtensionList.lookupSingleton(UpdateSiteWarningsMonitor.class); + assertThat("There should be no active plugin security warnings", monitor.getActivePluginWarningsByPlugin().keySet(), empty()); + }); + } + @Issue("JENKINS-48365") @Test @LocalData @@ -128,6 +142,7 @@ public void installDetachedDependencies() { assertThat("it had various implicit detached dependencies so those should have been loaded too", activePlugins, hasSize(greaterThan(1))); }); } + private void assertLoader(Class c, String expectedPlugin, JenkinsRule r) { PluginWrapper pw = r.jenkins.pluginManager.whichPlugin(c); assertNotNull("did not expect to be loading " + c + " from " + c.getClassLoader(), pw); diff --git a/test/src/test/java/jenkins/install/SetupWizardTest.java b/test/src/test/java/jenkins/install/SetupWizardTest.java index cf9897ec118e3..23664e0961c01 100644 --- a/test/src/test/java/jenkins/install/SetupWizardTest.java +++ b/test/src/test/java/jenkins/install/SetupWizardTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.install; import static org.hamcrest.MatcherAssert.assertThat; @@ -40,6 +41,7 @@ import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; @@ -75,22 +77,22 @@ public class SetupWizardTest { @Rule public JenkinsRule j = new JenkinsRule(); - + @Rule public TemporaryFolder tmpdir = new TemporaryFolder(); - - @Before + + @Before public void initSetupWizard() throws IOException, InterruptedException { final SetupWizard wizard = j.jenkins.getSetupWizard(); wizard.init(true); - + // Retrieve admin credentials final FilePath adminPassFile = wizard.getInitialAdminPasswordFile(); ByteArrayOutputStream ostream = new ByteArrayOutputStream(); adminPassFile.copyTo(ostream); - final String password = ostream.toString(); + final String password = ostream.toString(StandardCharsets.UTF_8.name()); } - + @Test public void shouldReturnPluginListsByDefault() throws Exception { JenkinsRule.WebClient wc = j.createWebClient(); @@ -99,7 +101,7 @@ public void shouldReturnPluginListsByDefault() throws Exception { j.jenkins.setAuthorizationStrategy(AuthorizationStrategy.UNSECURED); // wc.setCredentialsProvider(adminCredentialsProvider); // wc.login("admin"); - + String response = jsonRequest(wc, "setupWizard/platformPluginList"); assertThat("Missing plugin is suggestions ", response, containsString("active-directory")); assertThat("Missing category is suggestions ", response, containsString("Pipelines and Continuous Delivery")); @@ -350,7 +352,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques baseRequest.setHandled(true); response.setContentType("text/plain; charset=utf-8"); response.setStatus(HttpServletResponse.SC_OK); - response.getOutputStream().write(responseBody.getBytes()); + response.getOutputStream().write(responseBody.getBytes(StandardCharsets.UTF_8)); } else { response.sendError(404); } @@ -455,7 +457,7 @@ private static class CustomJSONSignatureValidator extends JSONSignatureValidator protected Set loadTrustAnchors(CertificateFactory cf) throws IOException { Set trustAnchors = new HashSet<>(); try { - Certificate certificate = cf.generateCertificate(new ByteArrayInputStream(cert.getBytes())); + Certificate certificate = cf.generateCertificate(new ByteArrayInputStream(cert.getBytes(StandardCharsets.UTF_8))); trustAnchors.add(new TrustAnchor((X509Certificate) certificate, null)); } catch (CertificateException ex) { throw new IOException(ex); diff --git a/test/src/test/java/jenkins/management/AdministrativeMonitorsDecoratorTest.java b/test/src/test/java/jenkins/management/AdministrativeMonitorsDecoratorTest.java index 34dc2cd0da0b1..37d28638e65b2 100644 --- a/test/src/test/java/jenkins/management/AdministrativeMonitorsDecoratorTest.java +++ b/test/src/test/java/jenkins/management/AdministrativeMonitorsDecoratorTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.management; import static org.junit.Assert.assertEquals; diff --git a/test/src/test/java/jenkins/model/BuildDiscarderPropertyTest.java b/test/src/test/java/jenkins/model/BuildDiscarderPropertyTest.java index a01189a904f60..60af91ad7ec87 100644 --- a/test/src/test/java/jenkins/model/BuildDiscarderPropertyTest.java +++ b/test/src/test/java/jenkins/model/BuildDiscarderPropertyTest.java @@ -73,7 +73,7 @@ private void verifyBuildDiscarder(FreeStyleProject p) { @LocalData @Test public void logRotatorField() throws Exception { - AbstractProject p = r.jenkins.getItemByFullName("foo", AbstractProject.class); + AbstractProject p = r.jenkins.getItemByFullName("foo", AbstractProject.class); verifyLogRotatorSanity(p); // now persist in the new format @@ -89,7 +89,7 @@ public void logRotatorField() throws Exception { assertTrue(xml, xml.contains("")); } - private static void verifyLogRotatorSanity(AbstractProject p) { + private static void verifyLogRotatorSanity(AbstractProject p) { LogRotator d = (LogRotator) p.getBuildDiscarder(); assertEquals(4, d.getDaysToKeep()); assertEquals(3, d.getNumToKeep()); diff --git a/test/src/test/java/jenkins/model/BuiltInNodeMigrationPropertyTest.java b/test/src/test/java/jenkins/model/BuiltInNodeMigrationPropertyTest.java index 07dfa44310a7b..3f34fc0f5ed49 100644 --- a/test/src/test/java/jenkins/model/BuiltInNodeMigrationPropertyTest.java +++ b/test/src/test/java/jenkins/model/BuiltInNodeMigrationPropertyTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.model; import org.junit.AfterClass; diff --git a/test/src/test/java/jenkins/model/BuiltInNodeMigrationTest.java b/test/src/test/java/jenkins/model/BuiltInNodeMigrationTest.java index 67614b7e70a2f..b02d75477f769 100644 --- a/test/src/test/java/jenkins/model/BuiltInNodeMigrationTest.java +++ b/test/src/test/java/jenkins/model/BuiltInNodeMigrationTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.model; import static org.junit.Assert.assertEquals; diff --git a/test/src/test/java/jenkins/model/ContextMenuTest.java b/test/src/test/java/jenkins/model/ContextMenuTest.java index a9a786980cbc4..84e0046e3abd6 100644 --- a/test/src/test/java/jenkins/model/ContextMenuTest.java +++ b/test/src/test/java/jenkins/model/ContextMenuTest.java @@ -63,7 +63,7 @@ public class ContextMenuTest { ActionFactory f = j.jenkins.getExtensionList(TransientProjectActionFactory.class).get(ActionFactory.class); f.visible = true; ContextMenu menu = j.executeOnServer(doContextMenu); - Map parsed = parse(menu); + Map parsed = parse(menu); assertEquals(parsed.toString(), "Hello", parsed.get("testing")); f.visible = false; menu = j.executeOnServer(doContextMenu); @@ -81,12 +81,15 @@ public class ContextMenuTest { @Override public boolean isVisible() { return visible; } + @Override public String getIconFileName() { return "whatever"; } + @Override public String getDisplayName() { return "Hello"; } + @Override public String getUrlName() { return "testing"; } @@ -95,8 +98,8 @@ public class ContextMenuTest { } - private static Map parse(ContextMenu menu) { - Map r = new TreeMap<>(); + private static Map parse(ContextMenu menu) { + Map r = new TreeMap<>(); for (MenuItem mi : menu.items) { r.put(mi.url.replaceFirst("^.*/(.)", "$1"), mi.displayName); } diff --git a/test/src/test/java/jenkins/model/ExtensionTypeHierarchyTest.java b/test/src/test/java/jenkins/model/ExtensionTypeHierarchyTest.java index 665e66dd4b539..29e8f2d80f75a 100644 --- a/test/src/test/java/jenkins/model/ExtensionTypeHierarchyTest.java +++ b/test/src/test/java/jenkins/model/ExtensionTypeHierarchyTest.java @@ -21,10 +21,12 @@ public class ExtensionTypeHierarchyTest { public JenkinsRule j = new JenkinsRule(); public interface Animal extends ExtensionPoint {} + public interface White extends ExtensionPoint {} @TestExtension public static class Swan implements Animal, White {} + @TestExtension public static class Crow implements Animal {} @@ -49,7 +51,7 @@ public void sameExtensionCanImplementMultipleExtensionPoints() { * Sort by class name */ private T[] sort(T[] a) { - Arrays.sort(a,new Comparator() { + Arrays.sort(a, new Comparator() { @Override public int compare(T o1, T o2) { return o1.getClass().getName().compareTo(o2.getClass().getName()); diff --git a/test/src/test/java/jenkins/model/GlobalBuildDiscarderTest.java b/test/src/test/java/jenkins/model/GlobalBuildDiscarderTest.java index 8c3be81c0d7cb..a6f2ab02f4e03 100644 --- a/test/src/test/java/jenkins/model/GlobalBuildDiscarderTest.java +++ b/test/src/test/java/jenkins/model/GlobalBuildDiscarderTest.java @@ -31,7 +31,7 @@ public void testLoadingWithDiscarders() throws Exception { final DescribableList configuredBuildDiscarders = GlobalBuildDiscarderConfiguration.get().getConfiguredBuildDiscarders(); Assert.assertEquals(2, configuredBuildDiscarders.size()); Assert.assertNotNull(configuredBuildDiscarders.get(JobGlobalBuildDiscarderStrategy.class)); - Assert.assertEquals(5, ((LogRotator)configuredBuildDiscarders.get(SimpleGlobalBuildDiscarderStrategy.class).getDiscarder()).getNumToKeep()); + Assert.assertEquals(5, ((LogRotator) configuredBuildDiscarders.get(SimpleGlobalBuildDiscarderStrategy.class).getDiscarder()).getNumToKeep()); } @Test @@ -96,7 +96,7 @@ public void testJobBuildDiscarder() throws Exception { j.buildAndAssertSuccess(p1); j.buildAndAssertSuccess(p1); j.buildAndAssertSuccess(p1); - Assert.assertArrayEquals("job with 5 builds", p1.getBuilds().stream().mapToInt(Run::getNumber).toArray(), new int[]{7,6,5,4,3,2,1}); + Assert.assertArrayEquals("job with 5 builds", p1.getBuilds().stream().mapToInt(Run::getNumber).toArray(), new int[]{7, 6, 5, 4, 3, 2, 1}); p1.setBuildDiscarder(new LogRotator(null, "5", null, null)); FreeStyleProject p2 = j.createFreeStyleProject(); @@ -106,7 +106,7 @@ public void testJobBuildDiscarder() throws Exception { j.buildAndAssertSuccess(p2); j.buildAndAssertSuccess(p2); j.buildAndAssertSuccess(p2); - Assert.assertArrayEquals("job with 3 builds", p2.getBuilds().stream().mapToInt(Run::getNumber).toArray(), new int[]{6,5,4,3,2,1}); + Assert.assertArrayEquals("job with 3 builds", p2.getBuilds().stream().mapToInt(Run::getNumber).toArray(), new int[]{6, 5, 4, 3, 2, 1}); p2.setBuildDiscarder(new LogRotator(null, "3", null, null)); GlobalBuildDiscarderConfiguration.get().getConfiguredBuildDiscarders().add(new SimpleGlobalBuildDiscarderStrategy(new LogRotator(null, "4", null, null))); @@ -122,7 +122,7 @@ public void testJobBuildDiscarder() throws Exception { { // job 2 with more aggressive local build discarder j.buildAndAssertSuccess(p2); - Assert.assertArrayEquals("job 1 discards down to 3", p2.getBuilds().stream().mapToInt(Run::getNumber).toArray(), new int[]{7,6,5}); + Assert.assertArrayEquals("job 1 discards down to 3", p2.getBuilds().stream().mapToInt(Run::getNumber).toArray(), new int[]{7, 6, 5}); } } } diff --git a/test/src/test/java/jenkins/model/GlobalSCMRetryCountConfigurationTest.java b/test/src/test/java/jenkins/model/GlobalSCMRetryCountConfigurationTest.java index 5e8903c191d86..d55b8f3fa39c1 100644 --- a/test/src/test/java/jenkins/model/GlobalSCMRetryCountConfigurationTest.java +++ b/test/src/test/java/jenkins/model/GlobalSCMRetryCountConfigurationTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.model; import static org.hamcrest.CoreMatchers.equalTo; diff --git a/test/src/test/java/jenkins/model/JenkinsBuildsAndWorkspacesDirectoriesTest.java b/test/src/test/java/jenkins/model/JenkinsBuildsAndWorkspacesDirectoriesTest.java index f5e6c471eb6dc..c3f476e6a40bb 100644 --- a/test/src/test/java/jenkins/model/JenkinsBuildsAndWorkspacesDirectoriesTest.java +++ b/test/src/test/java/jenkins/model/JenkinsBuildsAndWorkspacesDirectoriesTest.java @@ -275,10 +275,10 @@ private boolean logWasFound(String searched) { .anyMatch(record -> record.getMessage().contains(searched)); } - private boolean logWasFoundAtLevel(String searched, Level level) { - return loggerRule.getRecords().stream() + private boolean logWasFoundAtLevel(String searched, Level level) { + return loggerRule.getRecords().stream() .filter(record -> record.getMessage().contains(searched)).anyMatch(record -> record.getLevel().equals(level)); - } + } @Test @Issue("JENKINS-17138") diff --git a/test/src/test/java/jenkins/model/JenkinsLocationConfigurationTest.java b/test/src/test/java/jenkins/model/JenkinsLocationConfigurationTest.java index 86f2c0ea4b647..7e3f40d14c048 100644 --- a/test/src/test/java/jenkins/model/JenkinsLocationConfigurationTest.java +++ b/test/src/test/java/jenkins/model/JenkinsLocationConfigurationTest.java @@ -21,7 +21,6 @@ import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.concurrent.atomic.AtomicReference; -import junit.framework.AssertionFailedError; import org.apache.commons.io.FileUtils; import org.junit.Rule; import org.junit.Test; @@ -38,7 +37,7 @@ public class JenkinsLocationConfigurationTest { private boolean lastRootUrlSet; @Rule - public JenkinsRule j = new JenkinsRule(){ + public JenkinsRule j = new JenkinsRule() { @Override public URL getURL() throws IOException { // first call for the "Running on xxx" log message, Jenkins not being set at that point @@ -51,7 +50,7 @@ public URL getURL() throws IOException { return super.getURL(); } }; - + /** * Makes sure the use of "localhost" in the Hudson URL reports a warning. */ @@ -141,7 +140,7 @@ public void cannotInjectJavaScriptUsingRootUrl_inNewViewLinkAction() throws Exce HtmlAnchor newViewLink = page.getDocumentElement().getElementsByTagName("a").stream() .filter(HtmlAnchor.class::isInstance).map(HtmlAnchor.class::cast) .filter(a -> a.getHrefAttribute().endsWith("newView")) - .findFirst().orElseThrow(AssertionFailedError::new); + .findFirst().orElseThrow(AssertionError::new); // last verification assertFalse(alertAppeared.get()); @@ -173,7 +172,7 @@ public void cannotInjectJavaScriptUsingRootUrl_inLabelAbsoluteLink() throws Exce HtmlAnchor labelAnchor = projectConfigurePage.getDocumentElement().getElementsByTagName("a").stream() .filter(HtmlAnchor.class::isInstance).map(HtmlAnchor.class::cast) .filter(a -> a.getHrefAttribute().contains("/label/")) - .findFirst().orElseThrow(AssertionFailedError::new); + .findFirst().orElseThrow(AssertionError::new); assertFalse(alertAppeared.get()); HtmlElementUtil.click(labelAnchor); diff --git a/test/src/test/java/jenkins/model/JenkinsLogRecordsTest.java b/test/src/test/java/jenkins/model/JenkinsLogRecordsTest.java index 892f9b30f6e23..ce478c0e9640f 100644 --- a/test/src/test/java/jenkins/model/JenkinsLogRecordsTest.java +++ b/test/src/test/java/jenkins/model/JenkinsLogRecordsTest.java @@ -28,6 +28,7 @@ public class JenkinsLogRecordsTest { public void logRecordsArePresentOnController() throws Throwable { rr.then(JenkinsLogRecordsTest::_logRecordsArePresentOnController); } + private static void _logRecordsArePresentOnController(JenkinsRule r) throws Throwable { List logRecords = Jenkins.logRecords; assertThat(logRecords, not(empty())); diff --git a/test/src/test/java/jenkins/model/JenkinsManagePermissionTest.java b/test/src/test/java/jenkins/model/JenkinsManagePermissionTest.java index 0f42e419d3a8b..81516f19170b6 100644 --- a/test/src/test/java/jenkins/model/JenkinsManagePermissionTest.java +++ b/test/src/test/java/jenkins/model/JenkinsManagePermissionTest.java @@ -130,7 +130,7 @@ public void someGlobalConfigurationIsNotDisplayedWithManagePermission() throws E //WHEN the user goes to /configure page HtmlForm form = j.createWebClient().goTo("configure").getFormByName("config"); - String formText = form.asText(); + String formText = form.asNormalizedText(); //THEN items restricted to ADMINISTER only should not be displayed. assertThat("Should be able to configure system message", formText, not(containsString("systemMessage"))); assertThat("Should be able to configure project naming strategy", formText, not(containsString("useProjectNamingStrategy"))); @@ -154,7 +154,7 @@ public void someGlobalConfigCanNotBeModifiedWithManagePermission() throws Except String shell = getShell(); View view = j.jenkins.getPrimaryView(); HtmlForm form = j.createWebClient().goTo("configure").getFormByName("config"); - form.getInputByName("_.numExecutors").setValueAttribute(""+(currentNumberExecutors+1)); + form.getInputByName("_.numExecutors").setValueAttribute("" + (currentNumberExecutors + 1)); form.getInputByName("_.shell").setValueAttribute("/fakeShell"); form.getSelectByName("primaryView").setSelectedAttribute("testView", true); @@ -254,27 +254,27 @@ public void managePermissionShouldBeAllowedToRestart() throws IOException { //WHEN Asking for restart or safe-restart //THEN MANAGE and ADMINISTER are allowed but not READ CLICommandInvoker.Result result = new CLICommandInvoker(j, "restart").asUser(readUser.getId()).invoke(); - assertThat(result, allOf(failedWith(6),hasNoStandardOutput())); + assertThat(result, allOf(failedWith(6), hasNoStandardOutput())); result = new CLICommandInvoker(j, "safe-restart").asUser(readUser.getId()).invoke(); - assertThat(result, allOf(failedWith(6),hasNoStandardOutput())); + assertThat(result, allOf(failedWith(6), hasNoStandardOutput())); // We should assert that cli result is 0 // but as restart is not allowed in JenkinsRule, we assert that it has tried to restart. result = new CLICommandInvoker(j, "restart").asUser(manageUser.getId()).invoke(); assertThat(result, failedWith(1)); - assertThat(result.stderr(),containsString("RestartNotSupportedException")); + assertThat(result.stderr(), containsString("RestartNotSupportedException")); result = new CLICommandInvoker(j, "safe-restart").asUser(manageUser.getId()).invoke(); assertThat(result, failedWith(1)); - assertThat(result.stderr(),containsString("RestartNotSupportedException")); + assertThat(result.stderr(), containsString("RestartNotSupportedException")); result = new CLICommandInvoker(j, "restart").asUser(adminUser.getId()).invoke(); assertThat(result, failedWith(1)); - assertThat(result.stderr(),containsString("RestartNotSupportedException")); + assertThat(result.stderr(), containsString("RestartNotSupportedException")); result = new CLICommandInvoker(j, "safe-restart").asUser(adminUser.getId()).invoke(); assertThat(result, failedWith(1)); - assertThat(result.stderr(),containsString("RestartNotSupportedException")); + assertThat(result.stderr(), containsString("RestartNotSupportedException")); } } diff --git a/test/src/test/java/jenkins/model/JenkinsReloadConfigurationTest.java b/test/src/test/java/jenkins/model/JenkinsReloadConfigurationTest.java index b0b2918fe9cbf..a783ff67f052e 100644 --- a/test/src/test/java/jenkins/model/JenkinsReloadConfigurationTest.java +++ b/test/src/test/java/jenkins/model/JenkinsReloadConfigurationTest.java @@ -9,8 +9,11 @@ import hudson.model.User; import hudson.tasks.Mailer; import java.io.File; -import java.io.FileWriter; import java.io.IOException; +import java.io.UncheckedIOException; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; @@ -45,7 +48,7 @@ public void reloadAgentConfig() throws Exception { } private void modifyNode(Node node) throws Exception { - replace(node.getNodeName().equals("") ? "config.xml" : String.format("nodes/%s/config.xml",node.getNodeName()), "oldLabel", "newLabel"); + replace(node.getNodeName().equals("") ? "config.xml" : String.format("nodes/%s/config.xml", node.getNodeName()), "oldLabel", "newLabel"); assertEquals("oldLabel", node.getLabelString()); @@ -126,16 +129,19 @@ private Mailer.DescriptorImpl mailerDescriptor() { private void replace(String path, String search, String replace) { File configFile = new File(j.jenkins.getRootDir(), path); + String oldConfig; try { - String oldConfig = Util.loadFile(configFile); + oldConfig = Util.loadFile(configFile, StandardCharsets.UTF_8); + } catch (IOException e) { + throw new UncheckedIOException(e); + } - String newConfig = oldConfig.replaceAll(search, replace); + String newConfig = oldConfig.replaceAll(search, replace); - FileWriter fw = new FileWriter(configFile); - fw.write(newConfig); - fw.close(); - } catch (IOException ex) { - throw new AssertionError(ex); + try (Writer writer = Files.newBufferedWriter(configFile.toPath(), StandardCharsets.UTF_8)) { + writer.write(newConfig); + } catch (IOException e) { + throw new UncheckedIOException(e); } } } diff --git a/test/src/test/java/jenkins/model/JenkinsTest.java b/test/src/test/java/jenkins/model/JenkinsTest.java index 176bdf52b215d..2d33f0879856c 100644 --- a/test/src/test/java/jenkins/model/JenkinsTest.java +++ b/test/src/test/java/jenkins/model/JenkinsTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.model; import static org.hamcrest.MatcherAssert.assertThat; @@ -125,10 +126,10 @@ public void testIsDisplayNameUniqueTrue() throws Exception { final String jobName = "jobName"; FreeStyleProject curProject = j.createFreeStyleProject(curJobName); curProject.setDisplayName("currentProjectDisplayName"); - + FreeStyleProject p = j.createFreeStyleProject(jobName); p.setDisplayName("displayName"); - + Jenkins jenkins = Jenkins.get(); assertTrue(jenkins.isDisplayNameUnique("displayName1", curJobName)); assertTrue(jenkins.isDisplayNameUnique(jobName, curJobName)); @@ -139,37 +140,37 @@ public void testIsDisplayNameUniqueFalse() throws Exception { final String curJobName = "curJobName"; final String jobName = "jobName"; final String displayName = "displayName"; - + FreeStyleProject curProject = j.createFreeStyleProject(curJobName); curProject.setDisplayName("currentProjectDisplayName"); - + FreeStyleProject p = j.createFreeStyleProject(jobName); p.setDisplayName(displayName); - + Jenkins jenkins = Jenkins.get(); assertFalse(jenkins.isDisplayNameUnique(displayName, curJobName)); } - + @Test public void testIsDisplayNameUniqueSameAsCurrentJob() throws Exception { final String curJobName = "curJobName"; final String displayName = "currentProjectDisplayName"; - + FreeStyleProject curProject = j.createFreeStyleProject(curJobName); curProject.setDisplayName(displayName); - + Jenkins jenkins = Jenkins.get(); // should be true as we don't test against the current job assertTrue(jenkins.isDisplayNameUnique(displayName, curJobName)); } - + @Test public void testIsNameUniqueTrue() throws Exception { final String curJobName = "curJobName"; final String jobName = "jobName"; j.createFreeStyleProject(curJobName); j.createFreeStyleProject(jobName); - + Jenkins jenkins = Jenkins.get(); assertTrue(jenkins.isNameUnique("jobName1", curJobName)); } @@ -180,7 +181,7 @@ public void testIsNameUniqueFalse() throws Exception { final String jobName = "jobName"; j.createFreeStyleProject(curJobName); j.createFreeStyleProject(jobName); - + Jenkins jenkins = Jenkins.get(); assertFalse(jenkins.isNameUnique(jobName, curJobName)); } @@ -191,22 +192,22 @@ public void testIsNameUniqueSameAsCurrentJob() throws Exception { final String jobName = "jobName"; j.createFreeStyleProject(curJobName); j.createFreeStyleProject(jobName); - + Jenkins jenkins = Jenkins.get(); // true because we don't test against the current job assertTrue(jenkins.isNameUnique(curJobName, curJobName)); } - + @Test public void testDoCheckDisplayNameUnique() throws Exception { final String curJobName = "curJobName"; final String jobName = "jobName"; FreeStyleProject curProject = j.createFreeStyleProject(curJobName); curProject.setDisplayName("currentProjectDisplayName"); - + FreeStyleProject p = j.createFreeStyleProject(jobName); p.setDisplayName("displayName"); - + Jenkins jenkins = Jenkins.get(); FormValidation v = jenkins.doCheckDisplayName("1displayName", curJobName); assertEquals(FormValidation.ok(), v); @@ -219,10 +220,10 @@ public void testDoCheckDisplayNameSameAsDisplayName() throws Exception { final String displayName = "displayName"; FreeStyleProject curProject = j.createFreeStyleProject(curJobName); curProject.setDisplayName("currentProjectDisplayName"); - + FreeStyleProject p = j.createFreeStyleProject(jobName); p.setDisplayName(displayName); - + Jenkins jenkins = Jenkins.get(); FormValidation v = jenkins.doCheckDisplayName(displayName, curJobName); assertEquals(FormValidation.Kind.WARNING, v.kind); @@ -235,10 +236,10 @@ public void testDoCheckDisplayNameSameAsJobName() throws Exception { final String displayName = "displayName"; FreeStyleProject curProject = j.createFreeStyleProject(curJobName); curProject.setDisplayName("currentProjectDisplayName"); - + FreeStyleProject p = j.createFreeStyleProject(jobName); p.setDisplayName(displayName); - + Jenkins jenkins = Jenkins.get(); FormValidation v = jenkins.doCheckDisplayName(jobName, curJobName); assertEquals(FormValidation.Kind.WARNING, v.kind); @@ -250,7 +251,7 @@ public void testDoCheckViewName_GoodName() throws Exception { "", "Jenkins", }; - + Jenkins jenkins = Jenkins.get(); for (String viewName : viewNames) { FormValidation v = jenkins.doCheckViewName(viewName); @@ -272,15 +273,15 @@ public void testDoCheckViewName_NotGoodName() throws Exception { "^Jenkins", "..", }; - + Jenkins jenkins = Jenkins.get(); - + for (String viewName : viewNames) { FormValidation v = jenkins.doCheckViewName(viewName); assertEquals(FormValidation.Kind.ERROR, v.kind); } } - + /** * Makes sure access to "/foobar" for UnprotectedRootAction gets through. @@ -297,13 +298,13 @@ public void testUnprotectedRootAction() throws Exception { // and make sure this fails wc.assertFails("foobar-zot/", HttpURLConnection.HTTP_INTERNAL_ERROR); - assertEquals(3,j.jenkins.getExtensionList(RootAction.class).get(RootActionImpl.class).count); + assertEquals(3, j.jenkins.getExtensionList(RootAction.class).get(RootActionImpl.class).count); } @Test public void testDoScript() throws Exception { ApiTokenTestHelper.enableLegacyBehavior(); - + j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); j.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy(). grant(Jenkins.ADMINISTER).everywhere().to("alice"). @@ -343,7 +344,7 @@ public void testDoScriptTextDoesNotOutputExtraWhitespace() throws Exception { @Test public void testDoEval() throws Exception { ApiTokenTestHelper.enableLegacyBehavior(); - + j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); j.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy(). grant(Jenkins.ADMINISTER).everywhere().to("alice"). @@ -359,8 +360,8 @@ public void testDoEval() throws Exception { wc.withBasicApiToken(User.getById("bob", true)); Page page = eval(wc); - assertEquals("bob has only READ", - HttpURLConnection.HTTP_FORBIDDEN, + assertEquals("bob has only READ", + HttpURLConnection.HTTP_FORBIDDEN, page.getWebResponse().getStatusCode()); wc.withBasicApiToken(User.getById("charlie", true)); @@ -369,6 +370,7 @@ public void testDoEval() throws Exception { HttpURLConnection.HTTP_OK, page.getWebResponse().getStatusCode()); } + private Page eval(WebClient wc) throws Exception { WebRequest req = new WebRequest(new URL(wc.getContextPath() + "eval"), HttpMethod.POST); req.setEncodingType(null); @@ -430,7 +432,7 @@ public void testErrorPageShouldBeAnonymousAccessible() throws Exception { .withThrowExceptionOnFailingStatusCode(false); HtmlPage p = wc.goTo("error/reportError"); - assertEquals(p.asText(), HttpURLConnection.HTTP_BAD_REQUEST, p.getWebResponse().getStatusCode()); // not 403 forbidden + assertEquals(p.asNormalizedText(), HttpURLConnection.HTTP_BAD_REQUEST, p.getWebResponse().getStatusCode()); // not 403 forbidden assertTrue(p.getWebResponse().getContentAsString().contains("My car is black")); } @@ -534,23 +536,23 @@ public void onOnline(Computer c, TaskListener listener) throws IOException, Inte @Issue("JENKINS-39465") public void agentProtocols_singleEnable_roundtrip() throws Exception { final Set defaultProtocols = Collections.unmodifiableSet(j.jenkins.getAgentProtocols()); - + final Set newProtocols = new HashSet<>(defaultProtocols); newProtocols.add(MockOptInProtocol1.NAME); j.jenkins.setAgentProtocols(newProtocols); j.jenkins.save(); final Set agentProtocolsBeforeReload = j.jenkins.getAgentProtocols(); assertProtocolEnabled(MockOptInProtocol1.NAME, "before the roundtrip"); - + j.jenkins.reload(); - + final Set reloadedProtocols = j.jenkins.getAgentProtocols(); assertNotSame("The protocol list must have been really reloaded", agentProtocolsBeforeReload, reloadedProtocols); - assertThat("We should have additional enabled protocol", + assertThat("We should have additional enabled protocol", reloadedProtocols.size(), equalTo(defaultProtocols.size() + 1)); assertProtocolEnabled(MockOptInProtocol1.NAME, "after the roundtrip"); } - + @Test @Issue("JENKINS-39465") public void agentProtocols_multipleDisable_roundtrip() throws Exception { @@ -564,14 +566,14 @@ public void agentProtocols_multipleDisable_roundtrip() throws Exception { assertProtocolDisabled(MockOptOutProtocol1.NAME, "before the roundtrip"); final Set agentProtocolsBeforeReload = j.jenkins.getAgentProtocols(); j.jenkins.reload(); - + assertNotSame("The protocol list must have been really refreshed", agentProtocolsBeforeReload, j.jenkins.getAgentProtocols()); - assertThat("We should have disabled one protocol", + assertThat("We should have disabled one protocol", j.jenkins.getAgentProtocols().size(), equalTo(defaultProtocols.size() - 1)); assertProtocolDisabled(MockOptOutProtocol1.NAME, "after the roundtrip"); } - + @Test @Issue("JENKINS-39465") public void agentProtocols_multipleEnable_roundtrip() throws Exception { @@ -587,7 +589,7 @@ public void agentProtocols_multipleEnable_roundtrip() throws Exception { assertProtocolEnabled(MockOptInProtocol2.NAME, "before the roundtrip"); j.jenkins.reload(); - + final Set reloadedProtocols = j.jenkins.getAgentProtocols(); assertNotSame("The protocol list must have been really reloaded", agentProtocolsBeforeReload, reloadedProtocols); assertThat("There should be two additional enabled protocols", @@ -595,14 +597,14 @@ public void agentProtocols_multipleEnable_roundtrip() throws Exception { assertProtocolEnabled(MockOptInProtocol1.NAME, "after the roundtrip"); assertProtocolEnabled(MockOptInProtocol2.NAME, "after the roundtrip"); } - + @Test @Issue("JENKINS-39465") public void agentProtocols_singleDisable_roundtrip() throws Exception { final Set defaultProtocols = Collections.unmodifiableSet(j.jenkins.getAgentProtocols()); final String protocolToDisable1 = MockOptOutProtocol1.NAME; final String protocolToDisable2 = MockOptOutProtocol2.NAME; - + final Set newProtocols = new HashSet<>(defaultProtocols); newProtocols.remove(protocolToDisable1); newProtocols.remove(protocolToDisable2); @@ -612,9 +614,9 @@ public void agentProtocols_singleDisable_roundtrip() throws Exception { assertProtocolDisabled(protocolToDisable2, "before the roundtrip"); final Set agentProtocolsBeforeReload = j.jenkins.getAgentProtocols(); j.jenkins.reload(); - + assertNotSame("The protocol list must have been really reloaded", agentProtocolsBeforeReload, j.jenkins.getAgentProtocols()); - assertThat("We should have disabled two protocols", + assertThat("We should have disabled two protocols", j.jenkins.getAgentProtocols().size(), equalTo(defaultProtocols.size() - 2)); assertProtocolDisabled(protocolToDisable1, "after the roundtrip"); assertProtocolDisabled(protocolToDisable2, "after the roundtrip"); diff --git a/test/src/test/java/jenkins/model/MasterBuildConfigurationTest.java b/test/src/test/java/jenkins/model/MasterBuildConfigurationTest.java index 6897bcbe4f168..97e894354bae4 100644 --- a/test/src/test/java/jenkins/model/MasterBuildConfigurationTest.java +++ b/test/src/test/java/jenkins/model/MasterBuildConfigurationTest.java @@ -11,22 +11,22 @@ public class MasterBuildConfigurationTest { @Rule public JenkinsRule j = new JenkinsRule(); - + @Test @Issue("JENKINS-23966") public void retainMasterLabelWhenNoSlaveDefined() throws Exception { Jenkins jenkins = j.getInstance(); assertEquals("Test is for controller with no agent", 1, jenkins.getComputers().length); - + // set our own label & mode final String myTestLabel = "TestLabelx0123"; jenkins.setLabelString(myTestLabel); jenkins.setMode(Mode.EXCLUSIVE); - + // call global config page j.configRoundtrip(); - + // make sure settings were not lost assertEquals("Built in node's label is lost", myTestLabel, jenkins.getLabelString()); assertEquals("Built in node's mode is lost", Mode.EXCLUSIVE, jenkins.getMode()); diff --git a/test/src/test/java/jenkins/model/NodeListenerTest.java b/test/src/test/java/jenkins/model/NodeListenerTest.java index b387acd751a00..d6241ff13d618 100644 --- a/test/src/test/java/jenkins/model/NodeListenerTest.java +++ b/test/src/test/java/jenkins/model/NodeListenerTest.java @@ -15,6 +15,7 @@ import hudson.cli.UpdateNodeCommand; import hudson.model.Node; import java.io.ByteArrayInputStream; +import java.nio.charset.Charset; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -36,10 +37,10 @@ public void setUp() { public void crud() throws Exception { Node agent = j.createSlave(); String xml = cli(new GetNodeCommand()).invokeWithArgs(agent.getNodeName()).stdout(); - cli(new UpdateNodeCommand()).withStdin(new ByteArrayInputStream(xml.getBytes())).invokeWithArgs(agent.getNodeName()); + cli(new UpdateNodeCommand()).withStdin(new ByteArrayInputStream(xml.getBytes(Charset.defaultCharset()))).invokeWithArgs(agent.getNodeName()); cli(new DeleteNodeCommand()).invokeWithArgs(agent.getNodeName()); - cli(new CreateNodeCommand()).withStdin(new ByteArrayInputStream(xml.getBytes())).invokeWithArgs("replica"); + cli(new CreateNodeCommand()).withStdin(new ByteArrayInputStream(xml.getBytes(Charset.defaultCharset()))).invokeWithArgs("replica"); j.jenkins.getComputer("replica").doDoDelete(); verify(mock, times(2)).onCreated(any(Node.class)); diff --git a/test/src/test/java/jenkins/model/NodesTest.java b/test/src/test/java/jenkins/model/NodesTest.java index 8df019806881e..1c9bafe9030c2 100644 --- a/test/src/test/java/jenkins/model/NodesTest.java +++ b/test/src/test/java/jenkins/model/NodesTest.java @@ -93,18 +93,22 @@ public void addNodeShouldReplaceExistingNode() throws Exception { assertEquals(1, l.updated); assertEquals(1, l.created); } + @TestExtension("addNodeShouldReplaceExistingNode") public static final class ListenerImpl extends NodeListener { int deleted, updated, created; + @Override protected void onDeleted(Node node) { deleted++; } + @Override protected void onUpdated(Node oldOne, Node newOne) { assertNotSame(oldOne, newOne); updated++; } + @Override protected void onCreated(Node node) { created++; diff --git a/test/src/test/java/jenkins/model/ParameterizedJobMixInTest.java b/test/src/test/java/jenkins/model/ParameterizedJobMixInTest.java index a5dccb9c8b9c5..0ef25291bdb16 100644 --- a/test/src/test/java/jenkins/model/ParameterizedJobMixInTest.java +++ b/test/src/test/java/jenkins/model/ParameterizedJobMixInTest.java @@ -21,12 +21,21 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.model; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertThrows; + +import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; +import com.gargoylesoftware.htmlunit.HttpMethod; +import com.gargoylesoftware.htmlunit.WebRequest; import hudson.model.FreeStyleProject; import hudson.model.ParametersDefinitionProperty; import hudson.model.Queue; import hudson.model.StringParameterDefinition; +import java.net.URL; import javax.servlet.http.HttpServletResponse; import org.junit.Assert; import org.junit.Rule; @@ -39,28 +48,33 @@ * @author Oleg Nenashev */ public class ParameterizedJobMixInTest { - + @Rule public JenkinsRule j = new JenkinsRule(); - + @Test public void doBuild_shouldFailWhenInvokingDisabledProject() throws Exception { final FreeStyleProject project = j.createFreeStyleProject(); project.doDisable(); - + final JenkinsRule.WebClient webClient = j.createWebClient(); webClient.assertFails(project.getUrl() + "build", HttpServletResponse.SC_CONFLICT); } - + @Test @Issue("JENKINS-36193") public void doBuildWithParameters_shouldFailWhenInvokingDisabledProject() throws Exception { final FreeStyleProject project = j.createFreeStyleProject(); project.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("FOO", "BAR"))); project.doDisable(); - + final JenkinsRule.WebClient webClient = j.createWebClient(); - webClient.assertFails(project.getUrl() + "buildWithParameters", HttpServletResponse.SC_CONFLICT); + + FailingHttpStatusCodeException fex = assertThrows( + "should fail when invoking disabled project", + FailingHttpStatusCodeException.class, + () -> webClient.getPage(webClient.addCrumb(new WebRequest(new URL(j.getURL(), project.getUrl() + "build?delay=0"), HttpMethod.POST)))); + assertThat("Should fail with conflict", fex.getStatusCode(), is(409)); } @Test @@ -72,7 +86,7 @@ public void doBuildQuietPeriodInSeconds() throws Exception { project.setQuietPeriod(projectQuietPeriodInSeconds); final JenkinsRule.WebClient webClient = j.createWebClient(); - webClient.goTo(project.getUrl() + "build", ""); + webClient.getPage(webClient.addCrumb(new WebRequest(new URL(j.getURL(), project.getUrl() + "build"), HttpMethod.POST))); long triggerTime = System.currentTimeMillis(); Queue.Item item = Jenkins.get().getQueue().getItem(1); diff --git a/test/src/test/java/jenkins/model/PeepholePermalinkTest.java b/test/src/test/java/jenkins/model/PeepholePermalinkTest.java index df4b9b1191547..0273e014fb24f 100644 --- a/test/src/test/java/jenkins/model/PeepholePermalinkTest.java +++ b/test/src/test/java/jenkins/model/PeepholePermalinkTest.java @@ -31,7 +31,7 @@ public class PeepholePermalinkTest { @Test public void basics() throws Exception { FreeStyleProject p = j.createFreeStyleProject(); - FreeStyleBuild b1 = j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + FreeStyleBuild b1 = j.buildAndAssertSuccess(p); String lsb = "lastSuccessfulBuild"; String lfb = "lastFailedBuild"; @@ -53,7 +53,7 @@ public void basics() throws Exception { // one more build and this time it succeeds p.getBuildersList().clear(); - FreeStyleBuild b3 = j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + FreeStyleBuild b3 = j.buildAndAssertSuccess(p); assertStorage(lsb, p, b3); assertStorage(lfb, p, b2); diff --git a/test/src/test/java/jenkins/model/StartupTest.java b/test/src/test/java/jenkins/model/StartupTest.java index d4fa48b79cef5..668c977012ef7 100644 --- a/test/src/test/java/jenkins/model/StartupTest.java +++ b/test/src/test/java/jenkins/model/StartupTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.model; import static org.junit.Assert.assertEquals; diff --git a/test/src/test/java/jenkins/model/TransientActionFactoryTest.java b/test/src/test/java/jenkins/model/TransientActionFactoryTest.java index 77cc2fd4ee749..c1750b4fd902a 100644 --- a/test/src/test/java/jenkins/model/TransientActionFactoryTest.java +++ b/test/src/test/java/jenkins/model/TransientActionFactoryTest.java @@ -64,9 +64,16 @@ public class TransientActionFactoryTest { assertNotNull(r.createFolder("d").getAction(MyAction.class)); assertNotNull(r.createFreeStyleProject().getAction(MyAction.class)); } + @TestExtension("addedToAbstractItem") public static class TestItemFactory extends TransientActionFactory { - @Override public Class type() {return AbstractItem.class;} - @Override public Class actionType() {return MyAction.class;} + @Override public Class type() { + return AbstractItem.class; + } + + @Override public Class actionType() { + return MyAction.class; + } + @Override public Collection createFor(AbstractItem i) { return Collections.singleton(new MyAction()); } @@ -76,9 +83,11 @@ private static class MyAction implements Action { @Override public String getIconFileName() { return null; } + @Override public String getDisplayName() { return null; } + @Override public String getUrlName() { return null; } @@ -120,11 +129,19 @@ private static class MyAction implements Action { assertThat(d.getActions(ProminentProjectAction.class), Matchers.iterableWithSize(0)); assertEquals(0, LazyFactory.count); } + @SuppressWarnings("rawtypes") @TestExtension("laziness") public static class LazyFactory extends TransientActionFactory { static int count; - @Override public Class type() {return AbstractProject.class;} - @Override public Class actionType() {return ProminentProjectAction.class;} + + @Override public Class type() { + return AbstractProject.class; + } + + @Override public Class actionType() { + return ProminentProjectAction.class; + } + @Override public Collection createFor(AbstractProject p) { count++; return Collections.singleton(new MyProminentProjectAction()); @@ -151,9 +168,14 @@ private static class MyAction implements Action { assertThat(p.getActions(ProminentProjectAction.class), Matchers.iterableWithSize(1)); assertEquals(2, OldFactory.count); } + @TestExtension("compatibility") public static class OldFactory extends TransientActionFactory { static int count; - @Override public Class type() {return FreeStyleProject.class;} + + @Override public Class type() { + return FreeStyleProject.class; + } + @Override public Collection createFor(FreeStyleProject p) { count++; return Collections.singleton(new MyProminentProjectAction()); diff --git a/test/src/test/java/jenkins/model/UnlabeledLoadStatisticsTest.java b/test/src/test/java/jenkins/model/UnlabeledLoadStatisticsTest.java index 47c9c47edec14..bf84beb1ab55a 100644 --- a/test/src/test/java/jenkins/model/UnlabeledLoadStatisticsTest.java +++ b/test/src/test/java/jenkins/model/UnlabeledLoadStatisticsTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.model; import static org.junit.Assert.assertEquals; @@ -44,35 +45,35 @@ * @author Oleg Nenashev */ public class UnlabeledLoadStatisticsTest { - + @Rule public JenkinsRule j = new JenkinsRule(); - + private final LoadStatistics unlabeledLoad = new UnlabeledLoadStatistics(); - + @After public void clearQueue() { j.getInstance().getQueue().clear(); } - + @Test @Issue("JENKINS-28446") public void computeQueueLength() throws Exception { - final Queue queue = j.jenkins.getQueue(); + final Queue queue = j.jenkins.getQueue(); assertEquals("Queue must be empty when the test starts", 0, queue.getBuildableItems().size()); assertEquals("Statistics must return 0 when the test starts", 0, unlabeledLoad.computeQueueLength()); - + // Disable builds by default, create an agent to prevent assigning of "built-in" labels j.jenkins.setNumExecutors(0); DumbSlave slave = j.createOnlineSlave(new LabelAtom("testLabel")); slave.setMode(Node.Mode.EXCLUSIVE); - + // Init project FreeStyleProject unlabeledProject = j.createFreeStyleProject("UnlabeledProject"); unlabeledProject.setConcurrentBuild(true); FreeStyleProject labeledProject = j.createFreeStyleProject("LabeledProject"); labeledProject.setAssignedLabel(new LabelAtom("foo")); - + // Put unlabeled build into the queue unlabeledProject.scheduleBuild2(0, new ParametersAction(new StringParameterValue("FOO", "BAR1"))); queue.maintain(); @@ -80,12 +81,12 @@ public void computeQueueLength() throws Exception { unlabeledProject.scheduleBuild2(0, new ParametersAction(new StringParameterValue("FOO", "BAR2"))); queue.maintain(); assertEquals("Second Unlabeled build must be taken into account", 2, unlabeledLoad.computeQueueLength()); - + // Put labeled build into the queue labeledProject.scheduleBuild2(0); queue.maintain(); assertEquals("Labeled builds must be ignored", 2, unlabeledLoad.computeQueueLength()); - + // Allow executions of unlabeled builds on built-in node, all unlabeled builds should pass j.jenkins.setNumExecutors(1); j.buildAndAssertSuccess(unlabeledProject); @@ -93,5 +94,5 @@ public void computeQueueLength() throws Exception { assertEquals("Queue must contain the labeled project build", 1, queue.getBuildableItems().size()); assertEquals("Statistics must return 0 after all builds", 0, unlabeledLoad.computeQueueLength()); } - + } diff --git a/test/src/test/java/jenkins/model/lazy/LazyBuildMixInTest.java b/test/src/test/java/jenkins/model/lazy/LazyBuildMixInTest.java index 656df07b9bf7d..b95aa83bfdbe8 100644 --- a/test/src/test/java/jenkins/model/lazy/LazyBuildMixInTest.java +++ b/test/src/test/java/jenkins/model/lazy/LazyBuildMixInTest.java @@ -90,9 +90,10 @@ public class LazyBuildMixInTest { @Test public void newRunningBuildRelationFromPrevious() throws Exception { FreeStyleProject p = r.createFreeStyleProject(); p.getBuildersList().add(new SleepBuilder(1000)); - FreeStyleBuild b1 = p.scheduleBuild2(0).get(); + FreeStyleBuild b1 = r.buildAndAssertSuccess(p); assertNull(b1.getNextBuild()); FreeStyleBuild b2 = p.scheduleBuild2(0).waitForStart(); assertSame(b2, b1.getNextBuild()); + r.assertBuildStatusSuccess(r.waitForCompletion(b2)); } } diff --git a/test/src/test/java/jenkins/scm/SCMCheckoutStrategyTest.java b/test/src/test/java/jenkins/scm/SCMCheckoutStrategyTest.java index 8f28d3dcd91be..65f38d2ec55db 100644 --- a/test/src/test/java/jenkins/scm/SCMCheckoutStrategyTest.java +++ b/test/src/test/java/jenkins/scm/SCMCheckoutStrategyTest.java @@ -29,7 +29,7 @@ public class SCMCheckoutStrategyTest { @Test public void configRoundtrip1() throws Exception { - assertEquals(1,SCMCheckoutStrategyDescriptor.all().size()); + assertEquals(1, SCMCheckoutStrategyDescriptor.all().size()); FreeStyleProject p = j.createFreeStyleProject(); assertFalse(pageHasUI(p)); // no configuration UI because there's only one option } @@ -39,15 +39,15 @@ public void configRoundtrip1() throws Exception { */ @Test public void configRoundtrip2() throws Exception { - assertEquals(2,SCMCheckoutStrategyDescriptor.all().size()); + assertEquals(2, SCMCheckoutStrategyDescriptor.all().size()); FreeStyleProject p = j.createFreeStyleProject(); System.out.println(SCMCheckoutStrategyDescriptor.all()); TestSCMCheckoutStrategy before = new TestSCMCheckoutStrategy(); p.setScmCheckoutStrategy(before); - j.configRoundtrip((Item)p); + j.configRoundtrip((Item) p); SCMCheckoutStrategy after = p.getScmCheckoutStrategy(); - assertNotSame(before,after); + assertNotSame(before, after); assertSame(before.getClass(), after.getClass()); assertTrue(pageHasUI(p)); diff --git a/test/src/test/java/jenkins/security/AgentToControllerSecurityTest.java b/test/src/test/java/jenkins/security/AgentToControllerSecurityTest.java new file mode 100644 index 0000000000000..0555cec0f1fe2 --- /dev/null +++ b/test/src/test/java/jenkins/security/AgentToControllerSecurityTest.java @@ -0,0 +1,211 @@ +package jenkins.security; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import hudson.FilePath; +import hudson.remoting.Callable; +import hudson.remoting.VirtualChannel; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Objects; +import jenkins.MasterToSlaveFileCallable; +import jenkins.SlaveToMasterFileCallable; +import jenkins.agents.AgentComputerUtil; +import jenkins.security.s2m.CallableDirectionChecker; +import jenkins.util.JenkinsJVM; +import org.jenkinsci.remoting.RoleChecker; +import org.junit.Rule; +import org.junit.Test; +import org.junit.function.ThrowingRunnable; +import org.jvnet.hudson.test.Issue; +import org.jvnet.hudson.test.JenkinsRule; + +public class AgentToControllerSecurityTest { + + @Rule + public JenkinsRule j = new JenkinsRule(); + + // ----- try to run a legacy callable + + @Test + public void testLegacyCallable() { + final SecurityException securityException = assertThrowsIOExceptionCausedBySecurityException(() -> Objects.requireNonNull(j.createOnlineSlave().getChannel()).call(new CallLegacyCallableCallable())); + assertThat(securityException.getMessage(), containsString("Sending jenkins.security.AgentToControllerSecurityTest$LegacyCallable from agent to controller is prohibited")); + } + + private static class CallLegacyCallableCallable extends MasterToSlaveCallable { + @Override + public Void call() throws Exception { + Objects.requireNonNull(AgentComputerUtil.getChannelToController()).call(new LegacyCallable()); + return null; + } + } + + private static class LegacyCallable implements Callable { + @Override + public Void call() throws Exception { + fail("LegacyCallable got called"); + return null; + } + + @Override + public void checkRoles(RoleChecker checker) throws SecurityException { + throw new AbstractMethodError("pretending to be a legacy Callable"); + } + } + + // ----- Attempt any file path access using a FilePath method + + @Test + public void testFilePaths() { + final SecurityException securityException = assertThrowsIOExceptionCausedBySecurityException(() -> Objects.requireNonNull(j.createOnlineSlave().getChannel()).call(new AccessControllerFilePathCallable())); + assertThat(securityException.getMessage(), containsString("Sending hudson.FilePath$ReadLink from agent to controller is prohibited")); + } + + private static class AccessControllerFilePathCallable extends MasterToSlaveCallable { + @Override + public Void call() throws Exception { + new FilePath(AgentComputerUtil.getChannelToController(), "foo").readLink(); + return null; + } + } + + // ----- Agent to controller access is still possible using SlaveToMaster[File]Callable + + @Test + public void testAgentToControllerFileCallable() throws Exception { + Objects.requireNonNull(j.createOnlineSlave().getChannel()).call(new InvokeAgentToControllerCallables()); + } + + private static class InvokeAgentToControllerCallables extends MasterToSlaveCallable { + @Override + public Void call() throws Exception { + assertFalse(JenkinsJVM.isJenkinsJVM()); + final VirtualChannel channelToController = AgentComputerUtil.getChannelToController(); + assertNotNull(channelToController); + channelToController.call(new A2CCallable()); + new FilePath(channelToController, "foo").act(new A2CFileCallable()); + return null; + } + } + + private static class A2CFileCallable extends SlaveToMasterFileCallable { + @Override + public Void invoke(File f, VirtualChannel channel) throws IOException, InterruptedException { + assertTrue(JenkinsJVM.isJenkinsJVM()); + return null; + } + } + + private static class A2CCallable extends SlaveToMasterCallable { + @Override + public Void call() throws Exception { + assertTrue(JenkinsJVM.isJenkinsJVM()); + return null; + } + } + + // ----- Agent to controller access control can be disabled using system property (but really shouldn't) + @Test + public void ensureBypass() throws Exception { + CallableDirectionChecker.BYPASS = true; + try { + Objects.requireNonNull(j.createOnlineSlave().getChannel()).call(new InvokeControllerToAgentCallables()); + } finally { + CallableDirectionChecker.BYPASS = false; + } + } + + private static class InvokeControllerToAgentCallables extends MasterToSlaveCallable { + @Override + public Void call() throws Exception { + assertFalse(JenkinsJVM.isJenkinsJVM()); + final VirtualChannel channelToController = AgentComputerUtil.getChannelToController(); + assertNotNull(channelToController); + channelToController.call(new NoopMasterToSlaveCallable()); + new FilePath(channelToController, "foo").act(new NoopMasterToSlaveFileCallable()); + return null; + } + } + + private static class NoopMasterToSlaveCallable extends MasterToSlaveCallable { + @Override + public Void call() throws Exception { + return null; + } + } + + private static class NoopMasterToSlaveFileCallable extends MasterToSlaveFileCallable { + @Override + public Void invoke(File f, VirtualChannel channel) throws IOException, InterruptedException { + return null; + } + } + + // --- Ensure local FilePath operations work inside a Callable + + @Test + @Issue("JENKINS-67189") + public void controllerToControllerTest() throws Exception { + // Send a callable to the agent, which sends a callable to the controller, which invokes a method of a local FilePath + Objects.requireNonNull(j.createOnlineSlave().getChannel()).call(new BackToControllerCallable()); + } + + private static class BackToControllerCallable extends MasterToSlaveCallable { + @Override + public String call() throws Exception { + assertFalse(JenkinsJVM.isJenkinsJVM()); + return Objects.requireNonNull(AgentComputerUtil.getChannelToController()).call(new LocalFileOpCallable(true)); + } + } + + // Used for both agent-to-agent and controller-to-controller, so make it S2MC + private static class LocalFileOpCallable extends SlaveToMasterCallable { + private final boolean executesOnJenkinsJVM; + + LocalFileOpCallable(boolean executesOnJenkinsJVM) { + this.executesOnJenkinsJVM = executesOnJenkinsJVM; + } + + @Override + public String call() throws Exception { + assertEquals(executesOnJenkinsJVM, JenkinsJVM.isJenkinsJVM()); + final File tempFile = Files.createTempFile("jenkins-test", null).toFile(); + return new FilePath(tempFile).readToString(); + } + } + + @Test + @Issue("JENKINS-67189") // but this test works even in 2.319 because no agent side filtering + public void agentToAgentTest() throws Exception { + Objects.requireNonNull(j.createOnlineSlave().getChannel()).call(new LocalFileOpCallable(false)); + } + + // ----- Utility methods + + public static SecurityException assertThrowsIOExceptionCausedBySecurityException(ThrowingRunnable runnable) { + return assertThrowsIOExceptionCausedBy(SecurityException.class, runnable); + } + + public static X assertThrowsIOExceptionCausedBy(Class causeClass, ThrowingRunnable runnable) { + try { + runnable.run(); + } catch (IOException ex) { + final Throwable cause = ex.getCause(); + assertTrue("IOException with message: '" + ex.getMessage() + "' wasn't caused by " + causeClass + ": " + (cause == null ? "(null)" : (cause.getClass().getName() + ": " + cause.getMessage())), + cause != null && causeClass.isAssignableFrom(cause.getClass())); + return causeClass.cast(cause); + } catch (Throwable t) { + fail("Threw other Throwable: " + t.getClass() + " with message " + t.getMessage()); + } + fail("Expected exception but passed"); + return null; + } +} diff --git a/test/src/test/java/jenkins/security/ApiCrumbExclusionTest.java b/test/src/test/java/jenkins/security/ApiCrumbExclusionTest.java index f231b33a43259..2c43a3b93d988 100644 --- a/test/src/test/java/jenkins/security/ApiCrumbExclusionTest.java +++ b/test/src/test/java/jenkins/security/ApiCrumbExclusionTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.security; import static org.junit.Assert.assertEquals; @@ -39,7 +40,6 @@ import hudson.util.HttpResponses; import java.io.IOException; import java.net.URL; -import jenkins.security.apitoken.ApiTokenTestHelper; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.Issue; @@ -58,8 +58,6 @@ public class ApiCrumbExclusionTest { @Test @Issue("JENKINS-22474") public void callUsingApiTokenDoesNotRequireCSRFToken() throws Exception { - ApiTokenTestHelper.enableLegacyBehavior(); - j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); j.jenkins.setCrumbIssuer(null); User foo = User.getOrCreateByIdOrFullName("foo"); diff --git a/test/src/test/java/jenkins/security/ApiTokenPropertyTest.java b/test/src/test/java/jenkins/security/ApiTokenPropertyTest.java index c3ba3aa2eb0cb..1ffd8af735195 100644 --- a/test/src/test/java/jenkins/security/ApiTokenPropertyTest.java +++ b/test/src/test/java/jenkins/security/ApiTokenPropertyTest.java @@ -58,10 +58,10 @@ public class ApiTokenPropertyTest { public JenkinsRule j = new JenkinsRule(); @Before - public void setupLegacyConfig(){ + public void setupLegacyConfig() { ApiTokenTestHelper.enableLegacyBehavior(); } - + /** * Tests the UI interaction and authentication. */ @@ -69,6 +69,7 @@ public void setupLegacyConfig(){ public void basics() throws Exception { j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); User u = User.getById("foo", true); + j.createWebClient().withBasicApiToken(u); final ApiTokenProperty t = u.getProperty(ApiTokenProperty.class); final String token = t.getApiToken(); @@ -80,7 +81,7 @@ public void basics() throws Exception { // test the authentication via Token WebClient wc = createClientForUser("foo"); assertEquals(u, wc.executeOnServer(User::current)); - + // Make sure the UI shows the token to the user HtmlPage config = wc.goTo(u.getUrl() + "/configure"); HtmlForm form = config.getFormByName("config"); @@ -106,14 +107,14 @@ public void security49Upgrade() throws Exception { // the replacement for the compromised value must be consistent and cannot be random ApiTokenProperty t2 = new ApiTokenProperty(historicalInitialValue); u.addProperty(t2); - assertEquals(apiToken1,t2.getApiToken()); + assertEquals(apiToken1, t2.getApiToken()); // any other value is OK. those are changed values - t = new ApiTokenProperty(historicalInitialValue+"somethingElse"); + t = new ApiTokenProperty(historicalInitialValue + "somethingElse"); u.addProperty(t); - assertEquals(t.getApiToken(), Util.getDigestOf(historicalInitialValue+"somethingElse")); + assertEquals(t.getApiToken(), Util.getDigestOf(historicalInitialValue + "somethingElse")); } - + @Issue("SECURITY-200") @Test public void adminsShouldBeUnableToSeeTokensByDefault() throws Exception { @@ -121,14 +122,14 @@ public void adminsShouldBeUnableToSeeTokensByDefault() throws Exception { User u = User.getOrCreateByIdOrFullName("foo"); final ApiTokenProperty t = u.getProperty(ApiTokenProperty.class); final String token = t.getApiToken(); - + // Make sure the UI does not show the token to another user WebClient wc = createClientForUser("bar"); HtmlPage config = wc.goTo(u.getUrl() + "/configure"); HtmlForm form = config.getFormByName("config"); assertEquals(Messages.ApiTokenProperty_ChangeToken_TokenIsHidden(), form.getInputByName("_.apiToken").getValueAttribute()); } - + @Issue("SECURITY-200") @Test public void adminsShouldBeUnableToChangeTokensByDefault() throws Exception { @@ -137,23 +138,23 @@ public void adminsShouldBeUnableToChangeTokensByDefault() throws Exception { User bar = User.getOrCreateByIdOrFullName("bar"); final ApiTokenProperty t = foo.getProperty(ApiTokenProperty.class); final ApiTokenProperty.DescriptorImpl descriptor = (ApiTokenProperty.DescriptorImpl) t.getDescriptor(); - + // Make sure that Admin can reset a token of another user WebClient wc = createClientForUser("bar") .withThrowExceptionOnFailingStatusCode(false); - HtmlPage requirePOST = wc.goTo(foo.getUrl() + "/" + descriptor.getDescriptorUrl()+ "/changeToken"); - assertEquals("method should not be allowed", - HttpURLConnection.HTTP_BAD_METHOD, + HtmlPage requirePOST = wc.goTo(foo.getUrl() + "/" + descriptor.getDescriptorUrl() + "/changeToken"); + assertEquals("method should not be allowed", + HttpURLConnection.HTTP_BAD_METHOD, requirePOST.getWebResponse().getStatusCode()); wc.setThrowExceptionOnFailingStatusCode(true); - WebRequest request = new WebRequest(new URL(j.getURL().toString() + foo.getUrl() + "/" + descriptor.getDescriptorUrl()+ "/changeToken"), HttpMethod.POST); + WebRequest request = new WebRequest(new URL(j.getURL().toString() + foo.getUrl() + "/" + descriptor.getDescriptorUrl() + "/changeToken"), HttpMethod.POST); HtmlPage res = wc.getPage(request); // TODO This nicer alternative requires https://github.com/jenkinsci/jenkins/pull/2268 or similar to work // HtmlPage res = requirePOST.getPage().getForms().get(0).getElementsByAttribute("input", "type", "submit").get(0).click(); - assertEquals("Update token response is incorrect", - Messages.ApiTokenProperty_ChangeToken_SuccessHidden(), "
    " + res.getBody().asText() + "
    "); + assertEquals("Update token response is incorrect", + Messages.ApiTokenProperty_ChangeToken_SuccessHidden(), "
    " + res.getBody().asNormalizedText() + "
    "); } @Test @@ -176,106 +177,106 @@ public void postWithUsernameAndTokenInBasicAuthHeader() throws Exception { @NonNull private WebClient createClientForUser(final String id) throws Exception { User u = User.getById(id, true); - + WebClient wc = j.createWebClient(); wc.withBasicApiToken(u); return wc; } - + @Test @Issue("JENKINS-32776") public void generateNewTokenWithoutName() throws Exception { j.jenkins.setCrumbIssuer(null); j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); - + // user is still able to connect with legacy token User admin = User.getById("admin", true); - + WebClient wc = j.createWebClient(); wc.withBasicCredentials("admin", "admin"); - + GenerateNewTokenResponse token1 = generateNewToken(wc, "admin", ""); assertNotEquals("", token1.tokenName.trim()); - + GenerateNewTokenResponse token2 = generateNewToken(wc, "admin", "New Token"); assertEquals("New Token", token2.tokenName); } - + @Test @LocalData @Issue("JENKINS-32776") public void migrationFromLegacyToken() throws Exception { j.jenkins.setCrumbIssuer(null); - + // user is still able to connect with legacy token User admin = User.getById("admin", false); assertNotNull("Admin user not configured correctly in local data", admin); ApiTokenProperty apiTokenProperty = admin.getProperty(ApiTokenProperty.class); - + WebClient wc = j.createWebClient(); wc.withBasicCredentials("admin", "admin"); checkUserIsConnected(wc); - + // 7be8e81ad5a350fa3f3e2acfae4adb14 String localLegacyToken = apiTokenProperty.getApiTokenInsecure(); wc = j.createWebClient(); wc.withBasicCredentials("admin", localLegacyToken); checkUserIsConnected(wc); - + // can still renew it after (using API) assertEquals(1, apiTokenProperty.getTokenList().size()); apiTokenProperty.changeApiToken(); assertEquals(1, apiTokenProperty.getTokenList().size()); String newLegacyToken = apiTokenProperty.getApiTokenInsecure(); - + // use the new legacy api token wc = j.createWebClient(); wc.withBasicCredentials("admin", newLegacyToken); checkUserIsConnected(wc); - + // but previous one is not more usable wc = j.createWebClient(); wc.withBasicCredentials("admin", localLegacyToken); checkUserIsNotConnected(wc); - + // ===== new system ===== - + // revoke the legacy ApiTokenStore.HashedToken legacyToken = apiTokenProperty.getTokenStore().getLegacyToken(); assertNotNull(legacyToken); String legacyUuid = legacyToken.getUuid(); - + wc = j.createWebClient(); wc.withBasicCredentials("admin", newLegacyToken); revokeToken(wc, "admin", legacyUuid); - + assertEquals(0, apiTokenProperty.getTokenList().size()); - + // check it does not work any more wc = j.createWebClient(); wc.withBasicCredentials("admin", newLegacyToken); checkUserIsNotConnected(wc); - + wc = j.createWebClient(); wc.withBasicCredentials("admin", localLegacyToken); checkUserIsNotConnected(wc); - + // ensure the user can still connect using its username / password wc = j.createWebClient(); wc.withBasicCredentials("admin", "admin"); checkUserIsConnected(wc); - + // generate new token with the new system wc = j.createWebClient(); wc.login("admin", "admin"); GenerateNewTokenResponse newToken = generateNewToken(wc, "admin", "New Token"); - + // use the new one wc = j.createWebClient(); wc.withBasicCredentials("admin", newToken.tokenValue); checkUserIsConnected(wc); } - + private void checkUserIsConnected(WebClient wc) throws Exception { XmlPage xmlPage = wc.goToXml("whoAmI/api/xml"); assertThat(xmlPage, hasXPath("//name", is("admin"))); @@ -283,59 +284,59 @@ private void checkUserIsConnected(WebClient wc) throws Exception { assertThat(xmlPage, hasXPath("//authenticated", is("true"))); assertThat(xmlPage, hasXPath("//authority", is("authenticated"))); } - + private void checkUserIsNotConnected(WebClient wc) throws Exception { - try{ + try { wc.goToXml("whoAmI/api/xml"); fail(); } - catch(FailingHttpStatusCodeException e){ + catch (FailingHttpStatusCodeException e) { assertEquals(401, e.getStatusCode()); } } - + @Test @Issue("JENKINS-32776") public void legacyTokenChange() throws Exception { j.jenkins.setCrumbIssuer(null); j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); - + ApiTokenPropertyConfiguration config = ApiTokenPropertyConfiguration.get(); - + config.setTokenGenerationOnCreationEnabled(true); - + User user = User.getById("user", true); WebClient wc = j.createWebClient(); wc.withBasicCredentials("user", "user"); ApiTokenProperty apiTokenProperty = user.getProperty(ApiTokenProperty.class); - + { // with one legacy token, we can change it using web UI or direct internal call String currentLegacyToken = apiTokenProperty.getApiToken(); assertEquals(1, apiTokenProperty.getTokenList().size()); - + config.setCreationOfLegacyTokenEnabled(true); { // change using web UI changeLegacyToken(wc, "user", true); String newLegacyToken = apiTokenProperty.getApiToken(); assertNotEquals(newLegacyToken, currentLegacyToken); - + // change using internal call apiTokenProperty.changeApiToken(); String newLegacyToken2 = apiTokenProperty.getApiToken(); assertNotEquals(newLegacyToken2, newLegacyToken); assertNotEquals(newLegacyToken2, currentLegacyToken); - + currentLegacyToken = newLegacyToken2; } - + config.setCreationOfLegacyTokenEnabled(false); { // change using web UI changeLegacyToken(wc, "user", true); String newLegacyToken = apiTokenProperty.getApiToken(); assertNotEquals(newLegacyToken, currentLegacyToken); - + // change using internal call apiTokenProperty.changeApiToken(); String newLegacyToken2 = apiTokenProperty.getApiToken(); @@ -345,77 +346,77 @@ public void legacyTokenChange() throws Exception { } { // but without any legacy token, the direct internal call remains but web UI depends on config revokeAllToken(wc, user); - + checkCombinationWithConfigAndMethodForLegacyTokenCreation(config, wc, user); } - {// only the legacy token have impact on that capability + { // only the legacy token have impact on that capability generateNewToken(wc, "user", "New token"); - + checkCombinationWithConfigAndMethodForLegacyTokenCreation(config, wc, user); } } - + private void checkCombinationWithConfigAndMethodForLegacyTokenCreation( ApiTokenPropertyConfiguration config, WebClient wc, User user ) throws Exception { ApiTokenProperty apiTokenProperty = user.getProperty(ApiTokenProperty.class); - + config.setCreationOfLegacyTokenEnabled(true); { - {// change using web UI + { // change using web UI changeLegacyToken(wc, "user", true); String newLegacyToken = apiTokenProperty.getApiToken(); assertNotEquals(newLegacyToken, Messages.ApiTokenProperty_ChangeToken_CapabilityNotAllowed()); } revokeLegacyToken(wc, user); - + // always possible changeTokenByDirectCall(apiTokenProperty); revokeLegacyToken(wc, user); } - + revokeAllToken(wc, user); - + config.setCreationOfLegacyTokenEnabled(false); { - {// change not possible using web UI + { // change not possible using web UI changeLegacyToken(wc, "user", false); String newLegacyToken = apiTokenProperty.getApiToken(); assertEquals(newLegacyToken, Messages.ApiTokenProperty_NoLegacyToken()); } revokeLegacyToken(wc, user); - + // always possible changeTokenByDirectCall(apiTokenProperty); revokeLegacyToken(wc, user); } } - + private void changeTokenByDirectCall(ApiTokenProperty apiTokenProperty) throws Exception { apiTokenProperty.changeApiToken(); String newLegacyToken = apiTokenProperty.getApiToken(); assertNotEquals(newLegacyToken, Messages.ApiTokenProperty_ChangeToken_CapabilityNotAllowed()); } - + private void revokeAllToken(WebClient wc, User user) throws Exception { revokeAllTokenUsingFilter(wc, user, it -> true); } - + private void revokeLegacyToken(WebClient wc, User user) throws Exception { revokeAllTokenUsingFilter(wc, user, ApiTokenStore.HashedToken::isLegacy); } - + private void revokeAllTokenUsingFilter(WebClient wc, User user, Predicate filter) throws Exception { ApiTokenProperty apiTokenProperty = user.getProperty(ApiTokenProperty.class); List uuidList = apiTokenProperty.getTokenStore().getTokenListSortedByName().stream() .filter(filter) .map(ApiTokenStore.HashedToken::getUuid) .collect(Collectors.toList()); - for(String uuid : uuidList){ + for (String uuid : uuidList) { revokeToken(wc, user.getId(), uuid); } } - + private void revokeToken(WebClient wc, String login, String tokenUuid) throws Exception { WebRequest request = new WebRequest( new URL(j.getURL(), "user/" + login + "/descriptorByName/" + ApiTokenProperty.class.getName() + "/revoke/?tokenUuid=" + tokenUuid), @@ -424,7 +425,7 @@ private void revokeToken(WebClient wc, String login, String tokenUuid) throws Ex Page p = wc.getPage(request); assertEquals(200, p.getWebResponse().getStatusCode()); } - + private void changeLegacyToken(WebClient wc, String login, boolean success) throws Exception { WebRequest request = new WebRequest( new URL(j.getURL(), "user/" + login + "/descriptorByName/" + ApiTokenProperty.class.getName() + "/changeToken/"), @@ -432,19 +433,19 @@ private void changeLegacyToken(WebClient wc, String login, boolean success) thro ); Page p = wc.getPage(request); assertEquals(200, p.getWebResponse().getStatusCode()); - if(success){ + if (success) { assertThat(p.getWebResponse().getContentAsString(), not(containsString(Messages.ApiTokenProperty_ChangeToken_CapabilityNotAllowed()))); - }else{ + } else { assertThat(p.getWebResponse().getContentAsString(), containsString(Messages.ApiTokenProperty_ChangeToken_CapabilityNotAllowed())); } } - + public static class GenerateNewTokenResponse { public String tokenUuid; public String tokenName; public String tokenValue; } - + private GenerateNewTokenResponse generateNewToken(WebClient wc, String login, String tokenName) throws Exception { WebRequest request = new WebRequest( new URL(j.getURL(), "user/" + login + "/descriptorByName/" + ApiTokenProperty.class.getName() + "/generateNewToken/?newTokenName=" + tokenName), @@ -452,7 +453,7 @@ private GenerateNewTokenResponse generateNewToken(WebClient wc, String login, St ); Page p = wc.getPage(request); assertEquals(200, p.getWebResponse().getStatusCode()); - + String response = p.getWebResponse().getContentAsString(); JSONObject responseJson = JSONObject.fromObject(response); Object result = responseJson.getJSONObject("data").toBean(GenerateNewTokenResponse.class); @@ -488,10 +489,10 @@ public void script_addFixedNewToken_Invalid() throws Exception { Collection beforeTokenList = apiTokenProperty.getTokenStore().getTokenListSortedByName(); - checkInvalidTokenValue(apiTokenProperty,"invalid-token: too-long", "110123456789abcdef0123456789abcdefg"); - checkInvalidTokenValue(apiTokenProperty,"invalid-token: too-short", "110123456789abcdef0123456789abcde"); - checkInvalidTokenValue(apiTokenProperty,"invalid-token: non-hex", "110123456789abcdef0123456789abcdeg"); - checkInvalidTokenValue(apiTokenProperty,"invalid-token: invalid-version", "120123456789abcdef0123456789abcdef"); + checkInvalidTokenValue(apiTokenProperty, "invalid-token: too-long", "110123456789abcdef0123456789abcdefg"); + checkInvalidTokenValue(apiTokenProperty, "invalid-token: too-short", "110123456789abcdef0123456789abcde"); + checkInvalidTokenValue(apiTokenProperty, "invalid-token: non-hex", "110123456789abcdef0123456789abcdeg"); + checkInvalidTokenValue(apiTokenProperty, "invalid-token: invalid-version", "120123456789abcdef0123456789abcdef"); Collection afterTokenList = apiTokenProperty.getTokenStore().getTokenListSortedByName(); // ensure there is no new tokens @@ -615,9 +616,9 @@ public void script_revokeToken() throws Exception { checkTokenIsWorking(user.getId(), token1.plainValue); checkTokenIsWorking(user.getId(), token2.plainValue); checkTokenIsWorking(user.getId(), token3.plainValue); - + apiTokenProperty.revokeToken(token1.tokenUuid); - + checkTokenIsNotWorking(user.getId(), token1.plainValue); checkTokenIsWorking(user.getId(), token2.plainValue); checkTokenIsWorking(user.getId(), token3.plainValue); diff --git a/test/src/test/java/jenkins/security/BasicHeaderApiTokenAuthenticatorTest.java b/test/src/test/java/jenkins/security/BasicHeaderApiTokenAuthenticatorTest.java index 675eede71785e..a74a5d71026b9 100644 --- a/test/src/test/java/jenkins/security/BasicHeaderApiTokenAuthenticatorTest.java +++ b/test/src/test/java/jenkins/security/BasicHeaderApiTokenAuthenticatorTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.security; import static org.hamcrest.MatcherAssert.assertThat; @@ -55,7 +56,7 @@ public class BasicHeaderApiTokenAuthenticatorTest { @Rule public JenkinsSessionRule sessions = new JenkinsSessionRule(); - + @Test @Issue("SECURITY-896") public void legacyToken_regularCase() throws Throwable { @@ -63,7 +64,7 @@ public void legacyToken_regularCase() throws Throwable { sessions.then(j -> { enableLegacyTokenGenerationOnUserCreation(); configureSecurity(j); - + { JenkinsRule.WebClient wc = j.createWebClient(); // default SecurityListener will save the user when adding the LastGrantedAuthoritiesProperty @@ -77,10 +78,10 @@ public void legacyToken_regularCase() throws Throwable { sessions.then(j -> { User user = User.getById("user1", false); assertNotNull(user); - + JenkinsRule.WebClient wc = j.createWebClient(); wc.getOptions().setThrowExceptionOnFailingStatusCode(false); - + { // for invalid token, no effect WebRequest request = new WebRequest(new URL(j.jenkins.getRootUrl() + "whoAmI/api/xml")); request.setAdditionalHeader("Authorization", base64("user1", "invalid-token")); @@ -91,9 +92,9 @@ public void legacyToken_regularCase() throws Throwable { request.setAdditionalHeader("Authorization", base64("user-not-valid", token.get())); assertThat(wc.getPage(request).getWebResponse().getStatusCode(), equalTo(401)); } - + assertNull(User.getById("user-not-valid", false)); - + { // valid user with valid token, ok WebRequest request = new WebRequest(new URL(j.jenkins.getRootUrl() + "whoAmI/api/xml")); request.setAdditionalHeader("Authorization", base64("user1", token.get())); @@ -102,7 +103,7 @@ public void legacyToken_regularCase() throws Throwable { } }); } - + /* * The user is not saved after login without the default SecurityListener#fireAuthenticated */ @@ -113,7 +114,7 @@ public void legacyToken_withoutLastGrantedAuthorities() throws Throwable { sessions.then(j -> { enableLegacyTokenGenerationOnUserCreation(); configureSecurity(j); - + { JenkinsRule.WebClient wc = j.createWebClient(); wc.login("user1"); @@ -125,10 +126,10 @@ public void legacyToken_withoutLastGrantedAuthorities() throws Throwable { sessions.then(j -> { User user = User.getById("user1", false); assertNull(user); - + JenkinsRule.WebClient wc = j.createWebClient(); wc.getOptions().setThrowExceptionOnFailingStatusCode(false); - + { // for invalid token, no effect WebRequest request = new WebRequest(new URL(j.jenkins.getRootUrl() + "whoAmI/api/xml")); request.setAdditionalHeader("Authorization", base64("user1", "invalid-token")); @@ -139,10 +140,10 @@ public void legacyToken_withoutLastGrantedAuthorities() throws Throwable { request.setAdditionalHeader("Authorization", base64("user-not-valid", token.get())); assertThat(wc.getPage(request).getWebResponse().getStatusCode(), equalTo(401)); } - + assertNull(User.getById("user1", false)); assertNull(User.getById("user-not-valid", false)); - + { // valid user with valid token, ok WebRequest request = new WebRequest(new URL(j.jenkins.getRootUrl() + "whoAmI/api/xml")); request.setAdditionalHeader("Authorization", base64("user1", token.get())); @@ -155,7 +156,7 @@ public void legacyToken_withoutLastGrantedAuthorities() throws Throwable { assertNull(user); }); } - + @TestExtension("legacyToken_withoutLastGrantedAuthorities") public static class RemoveDefaultSecurityListener extends ExtensionFilter { @Override @@ -163,21 +164,21 @@ public boolean allows(Class type, ExtensionComponent component) { return !SecurityListener.class.isAssignableFrom(type); } } - - private static void enableLegacyTokenGenerationOnUserCreation() throws Exception { + + private static void enableLegacyTokenGenerationOnUserCreation() { ApiTokenPropertyConfiguration apiTokenConfiguration = GlobalConfiguration.all().getInstance(ApiTokenPropertyConfiguration.class); // by default it's false apiTokenConfiguration.setTokenGenerationOnCreationEnabled(true); } - + private static void configureSecurity(JenkinsRule j) throws Exception { j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); j.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy() .grant(Jenkins.ADMINISTER).everywhere().toEveryone()); - + j.jenkins.save(); } - + private static String base64(String login, String password) { return "Basic " + Base64.getEncoder().encodeToString((login + ":" + password).getBytes(StandardCharsets.UTF_8)); } diff --git a/test/src/test/java/jenkins/security/BasicHeaderProcessorTest.java b/test/src/test/java/jenkins/security/BasicHeaderProcessorTest.java index c097611b22cdc..c6eeb0622b542 100644 --- a/test/src/test/java/jenkins/security/BasicHeaderProcessorTest.java +++ b/test/src/test/java/jenkins/security/BasicHeaderProcessorTest.java @@ -36,7 +36,7 @@ public class BasicHeaderProcessorTest { private SpySecurityListener spySecurityListener; @Before - public void prepareListeners(){ + public void prepareListeners() { this.spySecurityListener = ExtensionList.lookupSingleton(SpySecurityListener.class); } @@ -61,7 +61,7 @@ public void testVariousWaysToCall() throws Exception { // call with API token wc = j.createWebClient(); wc.withBasicApiToken("foo"); - makeRequestAndVerify("foo"); + makeRequestAndVerify("foo"); spySecurityListener.authenticatedCalls.assertLastEventIsAndThenRemoveIt(u -> u.getUsername().equals("foo")); // call with invalid API token @@ -108,14 +108,14 @@ private void makeRequestAndFail() throws IOException, SAXException { makeRequestWithAuthCodeAndFail(null); } - private void makeRequestAndVerify(String expectedLogin) throws IOException, SAXException { + private void makeRequestAndVerify(String expectedLogin) throws IOException { makeRequestWithAuthCodeAndVerify(null, expectedLogin); } @Test public void testAuthHeaderCaseInSensitive() throws Exception { ApiTokenTestHelper.enableLegacyBehavior(); - + j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); User foo = User.getOrCreateByIdOrFullName("foo"); wc = j.createWebClient(); @@ -126,44 +126,44 @@ public void testAuthHeaderCaseInSensitive() throws Exception { // call with API token ApiTokenProperty t = foo.getProperty(ApiTokenProperty.class); final String token = t.getApiToken(); - String authCode1 = encode(prefix,"foo:"+token); + String authCode1 = encode(prefix, "foo:" + token); makeRequestWithAuthCodeAndVerify(authCode1, "foo"); spySecurityListener.authenticatedCalls.assertLastEventIsAndThenRemoveIt(u -> u.getUsername().equals("foo")); // call with invalid API token - String authCode2 = encode(prefix,"foo:abcd"+token); + String authCode2 = encode(prefix, "foo:abcd" + token); makeRequestWithAuthCodeAndFail(authCode2); spySecurityListener.failedToAuthenticateCalls.assertLastEventIsAndThenRemoveIt("foo"); // call with password - String authCode3 = encode(prefix,"foo:foo"); + String authCode3 = encode(prefix, "foo:foo"); makeRequestWithAuthCodeAndVerify(authCode3, "foo"); spySecurityListener.authenticatedCalls.assertLastEventIsAndThenRemoveIt(u -> u.getUsername().equals("foo")); // call with incorrect password - String authCode4 = encode(prefix,"foo:bar"); + String authCode4 = encode(prefix, "foo:bar"); makeRequestWithAuthCodeAndFail(authCode4); spySecurityListener.failedToAuthenticateCalls.assertLastEventIsAndThenRemoveIt("foo"); } } private String encode(String prefix, String userAndPass) { - if (userAndPass==null) { + if (userAndPass == null) { return null; } return prefix + " " + Base64.getEncoder().encodeToString(userAndPass.getBytes(StandardCharsets.UTF_8)); } private void makeRequestWithAuthCodeAndVerify(String authCode, String expectedLogin) throws IOException { - WebRequest req = new WebRequest(new URL(j.getURL(),"test")); + WebRequest req = new WebRequest(new URL(j.getURL(), "test")); req.setEncodingType(null); - if (authCode!=null) + if (authCode != null) req.setAdditionalHeader("Authorization", authCode); Page p = wc.getPage(req); assertEquals(expectedLogin, p.getWebResponse().getContentAsString()); } - private void makeRequestWithAuthCodeAndFail(String authCode) throws IOException, SAXException { + private void makeRequestWithAuthCodeAndFail(String authCode) throws IOException { try { makeRequestWithAuthCodeAndVerify(authCode, "-"); fail(); @@ -191,7 +191,7 @@ public String getUrlName() { public HttpResponse doIndex() { User u = User.current(); - return HttpResponses.text(u!=null ? u.getId() : "anonymous"); + return HttpResponses.text(u != null ? u.getId() : "anonymous"); } } diff --git a/test/src/test/java/jenkins/security/ClassFilterImplTest.java b/test/src/test/java/jenkins/security/ClassFilterImplTest.java index cb793c0b8c4c7..2b689b9c6f594 100644 --- a/test/src/test/java/jenkins/security/ClassFilterImplTest.java +++ b/test/src/test/java/jenkins/security/ClassFilterImplTest.java @@ -82,12 +82,14 @@ public void controllerToAgentBypassesWhitelist() throws Exception { p.getBuildersList().add(new M2SBuilder()); r.assertLogContains("sent {}", r.buildAndAssertSuccess(p)); } + public static class M2SBuilder extends Builder { @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { listener.getLogger().println("sent " + launcher.getChannel().call(new M2S())); return true; } + @TestExtension("controllerToAgentBypassesWhitelist") public static class DescriptorImpl extends BuildStepDescriptor { @SuppressWarnings("rawtypes") @@ -97,8 +99,10 @@ public boolean isApplicable(Class jobType) { } } } + private static class M2S extends MasterToSlaveCallable { private final LinkedListMultimap obj = LinkedListMultimap.create(); + @Override public String call() throws RuntimeException { return obj.toString(); @@ -113,14 +117,16 @@ public void agentToControllerRequiresWhitelist() throws Exception { FreeStyleProject p = r.createFreeStyleProject(); p.setAssignedNode(r.createSlave()); p.getBuildersList().add(new S2MBuilder()); - r.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0)); + r.buildAndAssertStatus(Result.FAILURE, p); } + public static class S2MBuilder extends Builder { @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { listener.getLogger().println("received " + launcher.getChannel().call(new S2M())); return true; } + @TestExtension("agentToControllerRequiresWhitelist") public static class DescriptorImpl extends BuildStepDescriptor { @SuppressWarnings("rawtypes") @@ -130,6 +136,7 @@ public boolean isApplicable(Class jobType) { } } } + private static class S2M extends MasterToSlaveCallable, RuntimeException> { @Override public LinkedListMultimap call() throws RuntimeException { @@ -170,6 +177,7 @@ public void moduleClassesShouldBeWhitelisted() { public static class Config extends GlobalConfiguration { LinkedListMultimap obj; String unrelated; + @Override protected XmlFile getConfigFile() { return super.getConfigFile(); diff --git a/test/src/test/java/jenkins/security/FilePathSecureTest.java b/test/src/test/java/jenkins/security/FilePathSecureTest.java index 02ca3a68cdde7..936fc47fe3141 100644 --- a/test/src/test/java/jenkins/security/FilePathSecureTest.java +++ b/test/src/test/java/jenkins/security/FilePathSecureTest.java @@ -35,6 +35,7 @@ import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; +// TODO What is this even testing? public class FilePathSecureTest { @Rule public JenkinsRule r = new JenkinsRule(); diff --git a/test/src/test/java/jenkins/security/LastGrantedAuthoritiesPropertyTest.java b/test/src/test/java/jenkins/security/LastGrantedAuthoritiesPropertyTest.java index ed70d8f43c6d5..6979be3d9b0a4 100644 --- a/test/src/test/java/jenkins/security/LastGrantedAuthoritiesPropertyTest.java +++ b/test/src/test/java/jenkins/security/LastGrantedAuthoritiesPropertyTest.java @@ -72,7 +72,7 @@ private void assertAuthorities(Authentication auth, String expected) { _assertAuthorities(auth.getAuthorities(), expected); } - private void _assertAuthorities(Collection grantedAuthorities, String expected){ + private void _assertAuthorities(Collection grantedAuthorities, String expected) { List authorities = grantedAuthorities.stream().map(GrantedAuthority::getAuthority).sorted().collect(Collectors.toList()); assertEquals(expected, String.join(":", authorities)); diff --git a/test/src/test/java/jenkins/security/RedactSecretJsonInErrorMessageSanitizerHtmlTest.java b/test/src/test/java/jenkins/security/RedactSecretJsonInErrorMessageSanitizerHtmlTest.java index 23240866bf30f..3235010056e4d 100644 --- a/test/src/test/java/jenkins/security/RedactSecretJsonInErrorMessageSanitizerHtmlTest.java +++ b/test/src/test/java/jenkins/security/RedactSecretJsonInErrorMessageSanitizerHtmlTest.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.security; import static org.hamcrest.CoreMatchers.allOf; @@ -58,43 +59,43 @@ @Restricted(NoExternalUse.class) public class RedactSecretJsonInErrorMessageSanitizerHtmlTest { - + @Rule public JenkinsRule j = new JenkinsRule(); - + @Rule public LoggerRule logging = new LoggerRule(); - + @Test @Issue("SECURITY-765") public void passwordsAreRedacted_andOtherStayTheSame() throws Exception { j.jenkins.setCrumbIssuer(null); TestPassword testPassword = j.jenkins.getExtensionList(RootAction.class).get(TestPassword.class); - + JenkinsRule.WebClient wc = j.createWebClient(); HtmlPage page = wc.goTo("test"); - + String textSimple = "plain-1"; String pwdSimple = "secret-1"; ((HtmlInput) page.getElementById("text-simple")).setValueAttribute(textSimple); ((HtmlInput) page.getElementById("pwd-simple")).setValueAttribute(pwdSimple); - + String textLevelOne = "plain-2"; String pwdLevelOneA = "secret-2"; ((HtmlInput) page.getElementById("text-level-one")).setValueAttribute(textLevelOne); ((HtmlInput) page.getElementById("pwd-level-one-a")).setValueAttribute(pwdLevelOneA); - + HtmlForm form = page.getFormByName("config"); Page formSubmitPage = j.submit(form); assertThat(formSubmitPage.getWebResponse().getStatusCode(), equalTo(200)); - + JSONObject rawJson = testPassword.lastJsonReceived; String rawJsonToString = rawJson.toString(); assertThat(rawJsonToString, containsString(textSimple)); assertThat(rawJsonToString, containsString(pwdSimple)); assertThat(rawJsonToString, containsString(textLevelOne)); assertThat(rawJsonToString, containsString(pwdLevelOneA)); - + assertThat(rawJson.getString(RedactSecretJsonInErrorMessageSanitizer.REDACT_KEY), equalTo("pwd-simple")); assertThat( rawJson.getJSONObject("sub-one").getJSONArray(RedactSecretJsonInErrorMessageSanitizer.REDACT_KEY), @@ -103,7 +104,7 @@ public void passwordsAreRedacted_andOtherStayTheSame() throws Exception { hasItem("pwd-level-one-b") ) ); - + String pwdLevelOneB = "pre-set secret"; // set in Jelly JSONObject redactedJson = RedactSecretJsonInErrorMessageSanitizer.INSTANCE.sanitize(rawJson); String redactedJsonToString = redactedJson.toString(); @@ -114,54 +115,54 @@ public void passwordsAreRedacted_andOtherStayTheSame() throws Exception { assertThat(redactedJsonToString, not(containsString(pwdLevelOneB))); assertThat(redactedJsonToString, containsString(RedactSecretJsonInErrorMessageSanitizer.REDACT_VALUE)); } - + @TestExtension("passwordsAreRedacted_andOtherStayTheSame") public static class TestPassword implements RootAction { - + public JSONObject lastJsonReceived; - + public void doSubmitTest(StaplerRequest req, StaplerResponse res) throws Exception { lastJsonReceived = req.getSubmittedForm(); - + res.setStatus(200); } - + @Override public String getIconFileName() { return null; } - + @Override public String getDisplayName() { return null; } - + @Override public String getUrlName() { return "test"; } } - + @Test @Issue("SECURITY-765") public void checkSanitizationIsApplied_inDescriptor() throws Exception { logging.record("", Level.WARNING).capture(100); - + j.jenkins.setCrumbIssuer(null); - + JenkinsRule.WebClient wc = j.createWebClient(); wc.getOptions().setThrowExceptionOnFailingStatusCode(false); HtmlPage page = wc.goTo("testDescribable"); String secret = "s3cr3t"; ((HtmlInput) page.getElementById("password")).setValueAttribute(secret); - + HtmlForm form = page.getFormByName("config"); Page formSubmitPage = j.submit(form); assertThat(formSubmitPage.getWebResponse().getContentAsString(), allOf( containsString(RedactSecretJsonInErrorMessageSanitizer.REDACT_VALUE), not(containsString(secret)) )); - + // check the system log also Throwable thrown = logging.getRecords().stream().filter(r -> r.getMessage().contains("Error while serving")).findAny().get().getThrown(); // the exception from Descriptor @@ -169,13 +170,13 @@ public void checkSanitizationIsApplied_inDescriptor() throws Exception { containsString(RedactSecretJsonInErrorMessageSanitizer.REDACT_VALUE), not(containsString(secret)) )); - + // the exception from RequestImpl assertThat(thrown.getCause().getCause().getMessage(), allOf( containsString(RedactSecretJsonInErrorMessageSanitizer.REDACT_VALUE), not(containsString(secret)) )); - + StringWriter buffer = new StringWriter(); thrown.printStackTrace(new PrintWriter(buffer)); String fullStack = buffer.getBuffer().toString(); @@ -184,27 +185,27 @@ public void checkSanitizationIsApplied_inDescriptor() throws Exception { not(containsString(secret)) )); } - + @Test @Issue("SECURITY-765") public void checkSanitizationIsApplied_inStapler() throws Exception { logging.record("", Level.WARNING).capture(100); - + j.jenkins.setCrumbIssuer(null); - + JenkinsRule.WebClient wc = j.createWebClient(); wc.getOptions().setThrowExceptionOnFailingStatusCode(false); HtmlPage page = wc.goTo("testStapler"); String secret = "s3cr3t"; ((HtmlInput) page.getElementById("password")).setValueAttribute(secret); - + HtmlForm form = page.getFormByName("config"); Page formSubmitPage = j.submit(form); assertThat(formSubmitPage.getWebResponse().getContentAsString(), allOf( containsString(RedactSecretJsonInErrorMessageSanitizer.REDACT_VALUE), not(containsString(secret)) )); - + // check the system log also Throwable thrown = logging.getRecords().stream().filter(r -> r.getMessage().contains("Error while serving")).findAny().get().getThrown(); // the exception from RequestImpl @@ -212,7 +213,7 @@ public void checkSanitizationIsApplied_inStapler() throws Exception { containsString(RedactSecretJsonInErrorMessageSanitizer.REDACT_VALUE), not(containsString(secret)) )); - + StringWriter buffer = new StringWriter(); thrown.printStackTrace(new PrintWriter(buffer)); String fullStack = buffer.getBuffer().toString(); @@ -221,74 +222,74 @@ public void checkSanitizationIsApplied_inStapler() throws Exception { not(containsString(secret)) )); } - + public static class TestDescribable implements Describable { - + @DataBoundConstructor public TestDescribable(Secret password) { throw new IllegalArgumentException("Try to steal my password"); } - + @Override public DescriptorImpl getDescriptor() { return Jenkins.get().getDescriptorByType(TestDescribable.DescriptorImpl.class); } - + @TestExtension({ "checkSanitizationIsApplied_inStapler", "checkSanitizationIsApplied_inDescriptor" }) public static final class DescriptorImpl extends Descriptor { - + } } - + @TestExtension("checkSanitizationIsApplied_inDescriptor") public static class TestDescribablePage implements RootAction { - + public TestDescribable testDescribable; - + @POST public void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws Exception { Jenkins.get().getDescriptorOrDie(TestDescribable.class).newInstance(req, req.getSubmittedForm()); } - + @Override public String getIconFileName() { return null; } - + @Override public String getDisplayName() { return null; } - + @Override public String getUrlName() { return "testDescribable"; } } - + @TestExtension("checkSanitizationIsApplied_inStapler") public static class TestStaplerPage implements RootAction { - + public TestDescribable testDescribable; - + @POST public void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws Exception { req.bindJSON(TestDescribable.class, req.getSubmittedForm()); } - + @Override public String getIconFileName() { return null; } - + @Override public String getDisplayName() { return null; } - + @Override public String getUrlName() { return "testStapler"; diff --git a/test/src/test/java/jenkins/security/RekeySecretAdminMonitorTest.java b/test/src/test/java/jenkins/security/RekeySecretAdminMonitorTest.java index d0a2397fd3ef2..0ff44e3a26dc6 100644 --- a/test/src/test/java/jenkins/security/RekeySecretAdminMonitorTest.java +++ b/test/src/test/java/jenkins/security/RekeySecretAdminMonitorTest.java @@ -89,12 +89,12 @@ public void decorateHome(JenkinsRule jenkinsRule, File home) throws Exception { private static void putSomeOldData(File dir) throws Exception { File xml = new File(dir, "foo.xml"); - FileUtils.writeStringToFile(xml,"" + encryptOld(TEST_KEY) + ""); + FileUtils.writeStringToFile(xml, "" + encryptOld(TEST_KEY) + "", StandardCharsets.UTF_8); } private void verifyRewrite(File dir) throws Exception { File xml = new File(dir, "foo.xml"); - Pattern pattern = Pattern.compile(""+plain_regex_match+""); + Pattern pattern = Pattern.compile("" + plain_regex_match + ""); MatcherAssert.assertThat(FileUtils.readFileToString(xml, StandardCharsets.UTF_8).trim(), Matchers.matchesRegex(pattern)); } @@ -149,7 +149,7 @@ private HtmlButton getButton(HtmlForm form, int index) { if (index > 0) { buttonStream = buttonStream.skip(index); } - + return buttonStream .findFirst() .orElse(null); @@ -177,7 +177,7 @@ public void testScanOnBoot() throws Exception { private static String encryptOld(String str) throws Exception { Cipher cipher = Secret.getCipher("AES"); cipher.init(Cipher.ENCRYPT_MODE, Util.toAes128Key(TEST_KEY)); - return new String(Base64.getEncoder().encode(cipher.doFinal((str + "::::MAGIC::::").getBytes(StandardCharsets.UTF_8)))); + return Base64.getEncoder().encodeToString(cipher.doFinal((str + "::::MAGIC::::").getBytes(StandardCharsets.UTF_8))); } private String encryptNew(String str) { diff --git a/test/src/test/java/jenkins/security/ResourceDomainTest.java b/test/src/test/java/jenkins/security/ResourceDomainTest.java index 57a88a523f35b..3f85238381f8f 100644 --- a/test/src/test/java/jenkins/security/ResourceDomainTest.java +++ b/test/src/test/java/jenkins/security/ResourceDomainTest.java @@ -271,12 +271,12 @@ public void projectWasRenamedCauses404() throws Exception { } // @Test - public void indexFileIsUsedIfDefined() throws Exception { + public void indexFileIsUsedIfDefined() { // TODO Test with DBS with and without directory index file } @Test - public void adminMonitorShowsUpWithOverriddenCSP() throws Exception { + public void adminMonitorShowsUpWithOverriddenCSP() { ResourceDomainRecommendation monitor = ExtensionList.lookupSingleton(ResourceDomainRecommendation.class); Assert.assertFalse(monitor.isActivated()); System.setProperty(DirectoryBrowserSupport.class.getName() + ".CSP", ""); @@ -310,7 +310,7 @@ public void testColonUserName() throws Exception { } @Test - public void testRedirectUrls() throws Exception { + public void testRedirectUrls() { ResourceDomainRootAction rootAction = ResourceDomainRootAction.get(); String url = rootAction.getRedirectUrl(new ResourceDomainRootAction.Token("foo", "bar", Instant.now()), "foo bar baz"); Assert.assertFalse("urlencoded", url.contains(" ")); diff --git a/test/src/test/java/jenkins/security/Security177Test.java b/test/src/test/java/jenkins/security/Security177Test.java index e5647cbada9e8..eaa2e06236191 100644 --- a/test/src/test/java/jenkins/security/Security177Test.java +++ b/test/src/test/java/jenkins/security/Security177Test.java @@ -17,7 +17,7 @@ public class Security177Test { @Rule public JenkinsRule jenkins = new JenkinsRule(); - + @Test public void nosniff() throws Exception { WebClient wc = jenkins.createWebClient() diff --git a/test/src/test/java/jenkins/security/Security218Test.java b/test/src/test/java/jenkins/security/Security218Test.java index 2654a24fbb507..355a605083ac3 100644 --- a/test/src/test/java/jenkins/security/Security218Test.java +++ b/test/src/test/java/jenkins/security/Security218Test.java @@ -71,7 +71,7 @@ public void jnlpSlave() throws Exception { * returns a malicious response. */ @SuppressWarnings("ConstantConditions") - private void check(DumbSlave s) throws Exception { + private void check(DumbSlave s) { try { Object o = s.getComputer().getChannel().call(new EvilReturnValue()); fail("Expected the connection to die: " + o); @@ -79,6 +79,7 @@ private void check(DumbSlave s) throws Exception { assertThat(e.getMessage(), containsString(MethodClosure.class.getName())); } } + private static class EvilReturnValue extends MasterToSlaveCallable { @Override public Object call() { @@ -103,14 +104,14 @@ public DumbSlave createJnlpSlave(String name) throws Exception { * Launch a JNLP agent created by {@link #createJnlpSlave(String)} */ public Channel launchJnlpSlave(Slave slave) throws Exception { - j.createWebClient().goTo("computer/"+slave.getNodeName()+"/jenkins-agent.jnlp?encrypt=true", "application/octet-stream"); + j.createWebClient().goTo("computer/" + slave.getNodeName() + "/jenkins-agent.jnlp?encrypt=true", "application/octet-stream"); String secret = slave.getComputer().getJnlpMac(); File slaveJar = tmp.newFile(); FileUtils.copyURLToFile(new Slave.JnlpJar("agent.jar").getURL(), slaveJar); // To watch it fail: secret = secret.replace('1', '2'); ProcessBuilder pb = new ProcessBuilder(JavaEnvUtils.getJreExecutable("java"), "-jar", slaveJar.getAbsolutePath(), - "-jnlpUrl", j.getURL() + "computer/"+slave.getNodeName()+"/jenkins-agent.jnlp", "-secret", secret); + "-jnlpUrl", j.getURL() + "computer/" + slave.getNodeName() + "/jenkins-agent.jnlp", "-secret", secret); pb.inheritIO(); System.err.println("Running: " + pb.command()); @@ -129,7 +130,7 @@ public Channel launchJnlpSlave(Slave slave) throws Exception { @After public void tearDown() { - if (jnlp !=null) + if (jnlp != null) jnlp.destroy(); } } diff --git a/test/src/test/java/jenkins/security/Security2278Test.java b/test/src/test/java/jenkins/security/Security2278Test.java index 5cd7c0c2ddfb6..e998e3b5e3fc8 100644 --- a/test/src/test/java/jenkins/security/Security2278Test.java +++ b/test/src/test/java/jenkins/security/Security2278Test.java @@ -110,7 +110,7 @@ public void testWebMethodWithoutPermission() throws Exception { assertNotNull(computer); final List executors = computer.getExecutors(); int found = -1; - for (int i = 0; i < computer.getNumExecutors(); i ++) { + for (int i = 0; i < computer.getNumExecutors(); i++) { if (executors.get(i) == busyExecutor) { found = i; break; diff --git a/test/src/test/java/jenkins/security/Security2455Test.java b/test/src/test/java/jenkins/security/Security2455Test.java deleted file mode 100644 index 77c5035ed8759..0000000000000 --- a/test/src/test/java/jenkins/security/Security2455Test.java +++ /dev/null @@ -1,865 +0,0 @@ -package jenkins.security; - -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.not; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.junit.Assume.assumeFalse; -import static org.jvnet.hudson.test.LoggerRule.recorded; - -import hudson.ExtensionList; -import hudson.FilePath; -import hudson.Functions; -import hudson.Util; -import hudson.model.Cause; -import hudson.model.FreeStyleBuild; -import hudson.model.FreeStyleProject; -import hudson.model.Node; -import hudson.model.TaskListener; -import hudson.remoting.VirtualChannel; -import hudson.slaves.DumbSlave; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.net.URI; -import java.nio.file.Files; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.logging.Level; -import jenkins.SlaveToMasterFileCallable; -import jenkins.SoloFilePathFilter; -import jenkins.agents.AgentComputerUtil; -import jenkins.security.s2m.AdminWhitelistRule; -import jenkins.security.s2m.RunningBuildFilePathFilter; -import org.apache.commons.io.IOUtils; -import org.apache.commons.io.output.NullOutputStream; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.function.ThrowingRunnable; -import org.jvnet.hudson.test.FlagRule; -import org.jvnet.hudson.test.Issue; -import org.jvnet.hudson.test.JenkinsRule; -import org.jvnet.hudson.test.LoggerRule; -import org.jvnet.hudson.test.MockFolder; -import org.jvnet.hudson.test.recipes.LocalData; - -@SuppressWarnings("ThrowableNotThrown") -@Issue("SECURITY-2455") -public class Security2455Test { - - @Rule - public final FlagRule flagRule = FlagRule.systemProperty(RunningBuildFilePathFilter.class.getName() + ".FAIL", "false"); - - @Rule - public JenkinsRule j = new JenkinsRule(); - - @Rule - public LoggerRule logging = new LoggerRule().record(SoloFilePathFilter.class, Level.WARNING); - - @Before - public void setup() { - ExtensionList.lookupSingleton(AdminWhitelistRule.class).setMasterKillSwitch(false); - } - - // -------- - - @Test - @Issue("SECURITY-2427") - public void mkdirsParentsTest() { - final File buildStuff = new File(j.jenkins.getRootDir(), "job/nonexistent/builds/1/foo/bar"); - logging.capture(10); - SecurityException ex = assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new MkdirsParentsCallable(buildStuff))); - assertThat(logging, recorded(containsString("foo" + File.separator + "bar"))); - assertThat(ex.getMessage(), not(containsString("foo" + File.separator + "bar"))); // test error redaction - - SoloFilePathFilter.REDACT_ERRORS = false; - try { - SecurityException ex2 = assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new MkdirsParentsCallable(buildStuff))); - assertThat(ex2.getMessage(), containsString("foo" + File.separator + "bar")); // test error redaction - } finally { - SoloFilePathFilter.REDACT_ERRORS = true; - } - } - private static class MkdirsParentsCallable extends MasterToSlaveCallable { - private final File file; - - private MkdirsParentsCallable(File file) { - this.file = file; - } - - @Override - public String call() throws Exception { - toFilePathOnController(this.file).mkdirs(); - return null; - } - } - - // -------- - - @Test - @Issue("SECURITY-2444") - public void testNonCanonicalPath() throws Exception { - assumeFalse(Functions.isWindows()); - final FreeStyleBuild build = j.createFreeStyleProject().scheduleBuild2(0, new Cause.UserIdCause()).waitForStart(); - j.waitForCompletion(build); - final File link = new File(build.getRootDir(), "link"); - final File secrets = new File(j.jenkins.getRootDir(), "secrets/master.key"); - Files.createSymbolicLink(link.toPath(), secrets.toPath()); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new ReadToStringCallable(link))); - } - @Test - @Issue("SECURITY-2444") - public void testNonCanonicalPathOnController() throws Exception { - assumeFalse(Functions.isWindows()); - final FreeStyleBuild build = j.createFreeStyleProject().scheduleBuild2(0, new Cause.UserIdCause()).waitForStart(); - j.waitForCompletion(build); - final File link = new File(build.getRootDir(), "link"); - final File secrets = new File(j.jenkins.getRootDir(), "secrets/master.key"); - Files.createSymbolicLink(link.toPath(), secrets.toPath()); - String result = FilePath.localChannel.call(new ReadToStringCallable(link)); - assertEquals(IOUtils.readLines(new FileReader(secrets)).get(0), result); - } - - private static class ReadToStringCallable extends MasterToSlaveCallable { - - final String abs; - - ReadToStringCallable(File link) { - abs = link.getPath(); - } - - @Override - public String call() throws IOException { - FilePath p = toFilePathOnController(new File(abs)); - try { - return p.readToString(); - } catch (InterruptedException e) { - throw new IOException(e); - } - } - } - - // -------- - - @Test - @Issue({"SECURITY-2446", "SECURITY-2531"}) - // $ tar tvf symlink.tar - // lrwxr-xr-x 0 501 20 0 Oct 5 09:50 foo -> ../../../../secrets - @LocalData - public void testUntaringSymlinksFails() throws Exception { - final FreeStyleBuild freeStyleBuild = j.buildAndAssertSuccess(j.createFreeStyleProject()); - final File symlinkTarFile = new File(j.jenkins.getRootDir(), "symlink.tar"); - final File untarTargetFile = new File(freeStyleBuild.getRootDir(), "foo"); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new UntarFileCallable(symlinkTarFile, untarTargetFile))); - } - private static final class UntarFileCallable extends MasterToSlaveCallable { - private final File source; - private final File destination; - - private UntarFileCallable(File source, File destination) { - this.source = source; - this.destination = destination; - } - - @Override - public Integer call() throws Exception { - final FilePath sourceFilePath = new FilePath(source); - final FilePath destinationFilePath = toFilePathOnController(destination); - sourceFilePath.untar(destinationFilePath, FilePath.TarCompression.NONE); - return 1; - } - } - - // -------- - - @Test - @Issue("SECURITY-2453") - public void testTarSymlinksThatAreSafe() throws Exception { - assumeFalse(Functions.isWindows()); - final File buildDir = j.buildAndAssertSuccess(j.createFreeStyleProject()).getRootDir(); - // We cannot touch the build dir itself - final File innerDir = new File(buildDir, "dir"); - final File innerDir2 = new File(buildDir, "dir2"); - assertTrue(innerDir.mkdirs()); - assertTrue(innerDir2.mkdirs()); - assertTrue(new File(innerDir2, "the-file").createNewFile()); - Util.createSymlink(innerDir, "../dir2", "link", TaskListener.NULL); - assertTrue(new File(innerDir, "link/the-file").exists()); - final int files = invokeOnAgent(new TarCaller(innerDir)); - assertEquals(1, files); - } - @Test - @Issue("SECURITY-2453") - public void testTarSymlinksOutsideAllowedDirs() throws Exception { - assumeFalse(Functions.isWindows()); - final File buildDir = j.buildAndAssertSuccess(j.createFreeStyleProject()).getRootDir(); - // We cannot touch the build dir itself - final File innerDir = new File(buildDir, "dir"); - assertTrue(innerDir.mkdirs()); - Util.createSymlink(innerDir, "../../../../../secrets", "secrets-link", TaskListener.NULL); - assertTrue(new File(innerDir, "secrets-link/master.key").exists()); - logging.capture(10); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new TarCaller(innerDir))); - assertThat(logging, recorded(containsString("filepath-filters.d"))); - } - - private static class TarCaller extends MasterToSlaveCallable { - private final File root; - - private TarCaller(File root) { - this.root = root; - } - - @Override - public Integer call() throws Exception { - return toFilePathOnController(root).tar(NullOutputStream.NULL_OUTPUT_STREAM, "**"); - } - } - - // -------- - - @Test - @Issue("SECURITY-2484") - public void zipTest() { - final File secrets = new File(j.jenkins.getRootDir(), "secrets"); - assertTrue(secrets.exists()); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new ZipTestCallable(secrets))); - } - @Test - @Issue("SECURITY-2484") - public void zipTestController() throws Exception { - final File secrets = new File(j.jenkins.getRootDir(), "secrets"); - assertTrue(secrets.exists()); - FilePath.localChannel.call(new ZipTestCallable(secrets)); - } - - private static class ZipTestCallable extends MasterToSlaveCallable { - private final File file; - - private ZipTestCallable(File file) { - this.file = file; - } - - @Override - public String call() throws Exception { - final File tmp = File.createTempFile("security2455_", ".zip"); - tmp.deleteOnExit(); - toFilePathOnController(file).zip(new FilePath(tmp)); - return tmp.getName(); - } - } - - // -------- - - @Test - @Issue("SECURITY-2485") - @LocalData - public void unzipRemoteTest() { - final File targetDir = j.jenkins.getRootDir(); - final File source = new File(targetDir, "file.zip"); // in this test, controller and agent are on same FS so this works -- file needs to exist but content should not be read - assertTrue(targetDir.exists()); - final List filesBefore = Arrays.asList(Objects.requireNonNull(targetDir.listFiles())); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new UnzipRemoteTestCallable(targetDir, source))); - final List filesAfter = Arrays.asList(Objects.requireNonNull(targetDir.listFiles())); - // We cannot do a direct comparison here because `logs/` appears during execution - assertEquals(filesBefore.size(), filesAfter.stream().filter(it -> !it.getName().equals("logs")).count()); - } - - private static class UnzipRemoteTestCallable extends MasterToSlaveCallable { - private final File destination; - private final File source; - - private UnzipRemoteTestCallable(File destination, File source) { - this.destination = destination; - this.source = source; - } - - @Override - public String call() throws Exception { - FilePath onAgent = new FilePath(source); - onAgent.unzip(toFilePathOnController(destination)); - return null; - } - } - - // -------- - - @Test - @Issue("SECURITY-2485") - public void testCopyRecursiveFromControllerToAgent() { - IOException ex = assertThrowsIOExceptionCausedBy(IOException.class, () -> invokeOnAgent(new CopyRecursiveToFromControllerToAgentCallable(new FilePath(new File(j.jenkins.getRootDir(), "secrets"))))); - assertThat(Objects.requireNonNull(ex).getMessage(), containsString("Unexpected end of ZLIB input stream")); // TODO this used to say "premature", why the change? - } - private static class CopyRecursiveToFromControllerToAgentCallable extends MasterToSlaveCallable { - private final FilePath controllerFilePath; - - private CopyRecursiveToFromControllerToAgentCallable(FilePath controllerFilePath) { - this.controllerFilePath = controllerFilePath; - } - - @Override - public Integer call() throws Exception { - return controllerFilePath.copyRecursiveTo(new FilePath(Files.createTempDirectory("jenkins-test").toFile())); - } - } - - // -------- - - @Test - @Issue("SECURITY-2485") - public void testCopyRecursiveFromAgentToController() { - assertThrowsIOExceptionCausedBy(SecurityException.class, () -> invokeOnAgent(new CopyRecursiveToFromAgentToControllerCallable(new FilePath(new File(j.jenkins.getRootDir(), "secrets"))))); - } - private static class CopyRecursiveToFromAgentToControllerCallable extends MasterToSlaveCallable { - private final FilePath controllerFilePath; - - private CopyRecursiveToFromAgentToControllerCallable(FilePath controllerFilePath) { - this.controllerFilePath = controllerFilePath; - } - - @Override - public Integer call() throws Exception { - final File localPath = Files.createTempDirectory("jenkins-test").toFile(); - assertTrue(new File(localPath, "tmpfile").createNewFile()); - return new FilePath(localPath).copyRecursiveTo(controllerFilePath); - } - } - - // -------- - - @Test - @Issue("SECURITY-2486") - public void testDecoyWrapper() { - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new ReadToStringBypassCallable(j.jenkins.getRootDir()))); - } - - private static class ReadToStringBypassCallable extends MasterToSlaveCallable { - private final File file; - - private ReadToStringBypassCallable(File file) { - this.file = file; - } - - @Override - public String call() throws Exception { - final Class readToStringClass = Class.forName("hudson.FilePath$ReadToString"); - final Constructor constructor = readToStringClass.getDeclaredConstructor(); // Used to have FilePath.class from non-static context - constructor.setAccessible(true); - - //FilePath agentFilePath = new FilePath(new File("on agent lol")); // only used for the core code before fix - - final SlaveToMasterFileCallable callable = (SlaveToMasterFileCallable) constructor.newInstance(); // agentFilePath - - FilePath controllerFilePath = toFilePathOnController(new File(file, "secrets/master.key")); - final Object returned = controllerFilePath.act(callable); - return (String) returned; - } - } - - // -------- - - @Test - @Issue("SECURITY-2531") - public void testSymlinkCheck() throws Exception { - final File buildDir = j.buildAndAssertSuccess(j.createFreeStyleProject()).getRootDir(); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new SymlinkCreator(buildDir))); - } - private static class SymlinkCreator extends MasterToSlaveCallable { - private final File baseDir; - private SymlinkCreator(File baseDir) { - this.baseDir = baseDir; - } - - @Override - public String call() throws Exception { - toFilePathOnController(new File(baseDir, "child")).symlinkTo(baseDir.getPath() + "child2", TaskListener.NULL); - return null; - } - } - - // -------- - - // -------- - - @Test - @Issue("SECURITY-2538") // SECURITY-2538 adjacent, confirms that reading, stating etc. is supposed to be possible for userContent - public void testReadUserContent() throws Exception { - invokeOnAgent(new UserContentReader(new File(j.jenkins.getRootDir(), "userContent"))); - } - private static class UserContentReader extends MasterToSlaveCallable { - private final File userContent; - - private UserContentReader(File userContent) { - this.userContent = userContent; - } - - @Override - public String call() throws Exception { - final FilePath userContentFilePath = toFilePathOnController(userContent); - userContentFilePath.lastModified(); - userContentFilePath.zip(NullOutputStream.NULL_OUTPUT_STREAM); - assertThat(userContentFilePath.child("readme.txt").readToString(), containsString(hudson.model.Messages.Hudson_USER_CONTENT_README())); - return null; - } - } - - @Test - @Issue("SECURITY-2538") - public void testRenameTo() throws Exception { - final File buildDir = j.buildAndAssertSuccess(j.createFreeStyleProject()).getRootDir(); - final File userContentDir = new File(j.jenkins.getRootDir(), "userContent"); - final File readme = new File(userContentDir, "readme.txt"); - final File to = new File(buildDir, "readme.txt"); - assertTrue("readme.txt is a file", readme.isFile()); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new RenameToCaller(readme, to))); - assertTrue("readme.txt is still a file", readme.isFile()); - assertFalse("to does not exist", to.exists()); - } - private static class RenameToCaller extends MasterToSlaveCallable { - private final File from; - private final File to; - - private RenameToCaller(File from, File to) { - this.from = from; - this.to = to; - } - - @Override - public String call() throws Exception { - toFilePathOnController(from).renameTo(toFilePathOnController(to)); - return null; - } - } - - @Test - @Issue("SECURITY-2538") - public void testMoveChildren() throws Exception { - final File buildDir = j.buildAndAssertSuccess(j.createFreeStyleProject()).getRootDir(); - final File userContentDir = new File(j.jenkins.getRootDir(), "userContent"); - // The implementation of MoveAllChildrenTo seems odd and ends up removing the source directory, so work only in subdir of userContent - final File userContentSubDir = new File(userContentDir, "stuff"); - assertTrue(userContentSubDir.mkdirs()); - final File userContentSubDirFileA = new File(userContentSubDir, "fileA"); - final File userContentSubDirFileB = new File(userContentSubDir, "fileB"); - assertTrue(userContentSubDirFileA.createNewFile()); - assertTrue(userContentSubDirFileB.createNewFile()); - assertTrue("userContentSubDir is a directory", userContentSubDir.isDirectory()); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new MoveAllChildrenToCaller(userContentSubDir, buildDir))); - assertTrue("userContentSubDir is a directory", userContentSubDir.isDirectory()); - assertFalse("no fileA in buildDir", new File(buildDir, "fileA").exists()); - assertFalse("no fileB in buildDir", new File(buildDir, "fileB").exists()); - assertTrue("fileA is still a file", userContentSubDirFileA.isFile()); - assertTrue("fileB is still a file", userContentSubDirFileB.isFile()); - } - private static class MoveAllChildrenToCaller extends MasterToSlaveCallable { - private final File from; - private final File to; - - private MoveAllChildrenToCaller(File from, File to) { - this.from = from; - this.to = to; - } - - @Override - public String call() throws Exception { - toFilePathOnController(from).moveAllChildrenTo(toFilePathOnController(to)); - return null; - } - } - - // -------- - - @Test - @Issue("SECURITY-2539") - public void testCreateTempFile() { - final File rootDir = j.jenkins.getRootDir(); - assertFalse(Arrays.stream(Objects.requireNonNull(rootDir.listFiles())).anyMatch(it -> it.getName().contains("prefix"))); - - // Extra level of catch/throw - logging.capture(10); - final IOException ioException = assertThrowsIOExceptionCausedBy(IOException.class, () -> invokeOnAgent(new CreateTempFileCaller(rootDir))); - assertNotNull(ioException); - final Throwable cause = ioException.getCause(); - assertNotNull(cause); - assertTrue(cause instanceof SecurityException); - assertThat(cause.getMessage(), not(containsString("prefix"))); // redacted - assertThat(logging, recorded(containsString("'create'"))); - assertThat(logging, recorded(containsString(File.separator + "prefix-security-check-dummy-suffix"))); - assertFalse(Arrays.stream(Objects.requireNonNull(rootDir.listFiles())).anyMatch(it -> it.getName().contains("prefix"))); - } - private static class CreateTempFileCaller extends MasterToSlaveCallable { - private final File baseDir; - - private CreateTempFileCaller(File baseDir) { - this.baseDir = baseDir; - } - - @Override - public String call() throws Exception { - toFilePathOnController(baseDir).createTempFile("prefix", "suffix"); - return null; - } - } - - - @Test - @Issue("SECURITY-2539") - public void testCreateTextTempFile() { - final File rootDir = j.jenkins.getRootDir(); - assertFalse(Arrays.stream(Objects.requireNonNull(rootDir.listFiles())).anyMatch(it -> it.getName().contains("prefix"))); - - // Extra level of catch/throw - logging.capture(10); - final IOException ioException = assertThrowsIOExceptionCausedBy(IOException.class, () -> invokeOnAgent(new CreateTextTempFileCaller(rootDir))); - assertNotNull(ioException); - final Throwable cause = ioException.getCause(); - assertNotNull(cause); - assertTrue(cause instanceof SecurityException); - assertThat(cause.getMessage(), not(containsString("prefix"))); // redacted - assertThat(logging, recorded(containsString("'create'"))); - assertThat(logging, recorded(containsString(File.separator + "prefix-security-check-dummy-suffix"))); - assertFalse(Arrays.stream(Objects.requireNonNull(rootDir.listFiles())).anyMatch(it -> it.getName().contains("prefix"))); - } - private static class CreateTextTempFileCaller extends MasterToSlaveCallable { - private final File baseDir; - - private CreateTextTempFileCaller(File baseDir) { - this.baseDir = baseDir; - } - - @Override - public String call() throws Exception { - toFilePathOnController(baseDir).createTextTempFile("prefix", "suffix", "content"); - return null; - } - } - - @Test - @Issue("SECURITY-2539") - public void testCreateTempDir() { - final File rootDir = j.jenkins.getRootDir(); - assertFalse(Arrays.stream(Objects.requireNonNull(rootDir.listFiles())).anyMatch(it -> it.getName().contains("prefix"))); - - // Extra level of catch/throw - logging.capture(10); - final IOException ioException = assertThrowsIOExceptionCausedBy(IOException.class, () -> invokeOnAgent(new CreateTempDirCaller(rootDir))); - assertNotNull(ioException); - final Throwable cause = ioException.getCause(); - assertNotNull(cause); - assertTrue(cause instanceof SecurityException); - assertThat(cause.getMessage(), not(containsString("prefix"))); // redacted - assertThat(logging, recorded(containsString("'mkdirs'"))); - assertThat(logging, recorded(containsString(File.separator + "prefix.suffix-security-test"))); // weird but that's what it looks like - assertFalse(Arrays.stream(Objects.requireNonNull(rootDir.listFiles())).anyMatch(it -> it.getName().contains("prefix"))); - } - private static class CreateTempDirCaller extends MasterToSlaveCallable { - private final File baseDir; - - private CreateTempDirCaller(File baseDir) { - this.baseDir = baseDir; - } - - @Override - public String call() throws Exception { - toFilePathOnController(baseDir).createTempDir("prefix", "suffix"); - return null; - } - } - // -------- - - @Test - @Issue("SECURITY-2541") - public void testStatStuff() { - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new ToURICaller(j.jenkins.getRootDir()))); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new FreeDiskSpaceCaller(j.jenkins.getRootDir()))); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new TotalDiskSpaceCaller(j.jenkins.getRootDir()))); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new UsableDiskSpaceCaller(j.jenkins.getRootDir()))); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new AbsolutizeCaller(j.jenkins.getRootDir()))); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new HasSymlinkCaller(new File (j.jenkins.getRootDir(), "secrets"), j.jenkins.getRootDir()))); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new IsDescendantCaller(j.jenkins.getRootDir(), "secrets"))); - } - - private static class ToURICaller extends MasterToSlaveCallable { - private final File file; - - private ToURICaller(File file) { - this.file = file; - } - - @Override - public URI call() throws Exception { - return toFilePathOnController(file).toURI(); - } - } - private static class AbsolutizeCaller extends MasterToSlaveCallable { - private final File file; - - private AbsolutizeCaller(File file) { - this.file = file; - } - - @Override - public String call() throws Exception { - return toFilePathOnController(file).absolutize().getRemote(); - } - } - private static class HasSymlinkCaller extends MasterToSlaveCallable { - private final File file; - private final File root; - - private HasSymlinkCaller(File file, File root) { - this.file = file; - this.root = root; - } - - @Override - public Boolean call() throws Exception { - return toFilePathOnController(file).hasSymlink(toFilePathOnController(root), false); - } - } - private static class IsDescendantCaller extends MasterToSlaveCallable { - private final File file; - private final String childPath; - - private IsDescendantCaller(File file, String childPath) { - this.file = file; - this.childPath = childPath; - } - - @Override - public Boolean call() throws Exception { - return toFilePathOnController(file).isDescendant(childPath); - } - } - private static class FreeDiskSpaceCaller extends MasterToSlaveCallable { - private final File file; - - private FreeDiskSpaceCaller(File file) { - this.file = file; - } - - @Override - public Long call() throws Exception { - return toFilePathOnController(file).getFreeDiskSpace(); - } - } - private static class UsableDiskSpaceCaller extends MasterToSlaveCallable { - private final File file; - - private UsableDiskSpaceCaller(File file) { - this.file = file; - } - - @Override - public Long call() throws Exception { - return toFilePathOnController(file).getUsableDiskSpace(); - } - } - private static class TotalDiskSpaceCaller extends MasterToSlaveCallable { - private final File file; - - private TotalDiskSpaceCaller(File file) { - this.file = file; - } - - @Override - public Long call() throws Exception { - return toFilePathOnController(file).getTotalDiskSpace(); - } - } - - // -------- - - @Test - @Issue("SECURITY-2542") // adjacent, this confirms we follow symlinks when it's within allowed directories - public void testGlobFollowsSymlinks() throws Exception { - assumeFalse(Functions.isWindows()); - final File buildDir = j.buildAndAssertSuccess(j.createFreeStyleProject()).getRootDir(); - // We cannot touch the build dir itself - final File innerDir = new File(buildDir, "dir"); - final File innerDir2 = new File(buildDir, "dir2"); - assertTrue(innerDir.mkdirs()); - assertTrue(innerDir2.mkdirs()); - assertTrue(new File(innerDir2, "the-file").createNewFile()); - Util.createSymlink(innerDir, "../dir2", "link", TaskListener.NULL); - assertTrue(new File(innerDir, "link/the-file").exists()); - final int files = invokeOnAgent(new GlobCaller(innerDir)); - assertEquals(1, files); - } - @Test - @Issue("SECURITY-2542") - public void testGlobSymlinksThrowsOutsideAllowedDirectories() throws Exception { - assumeFalse(Functions.isWindows()); - final File buildDir = j.buildAndAssertSuccess(j.createFreeStyleProject()).getRootDir(); - // We cannot touch the build dir itself - final File innerDir = new File(buildDir, "dir"); - assertTrue(innerDir.mkdirs()); - Util.createSymlink(innerDir, "../../../../../secrets", "secrets-link", TaskListener.NULL); - assertTrue(new File(innerDir, "secrets-link/master.key").exists()); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new GlobCaller(innerDir))); - } - private static class GlobCaller extends MasterToSlaveCallable { - private final File root; - - private GlobCaller(File root) { - this.root = root; - } - - @Override - public Integer call() throws Exception { - return toFilePathOnController(root).list("**/*", "", false).length; - } - } - - // -------- - - @Issue("SECURITY-2455") // general issue -- Maven Projects would no longer be allowed to perform some actions - @Test - public void testMavenReportersAllowListForTopLevelJob() throws Exception { - final FreeStyleProject project = j.createFreeStyleProject(); - final File topLevelProjectDir = project.getRootDir(); - - // similar but wrong names: - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new MkDirsWriter(new File(topLevelProjectDir, "not-site")))); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new MkDirsWriter(new File(topLevelProjectDir, "not-javadoc")))); - - // project-level archived stuff: - invokeOnAgent(new MkDirsWriter(new File(topLevelProjectDir, "javadoc"))); - invokeOnAgent(new MkDirsWriter(new File(topLevelProjectDir, "test-javadoc"))); - invokeOnAgent(new MkDirsWriter(new File(topLevelProjectDir, "site"))); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new MkDirsWriter(new File(topLevelProjectDir, "cobertura")))); - - // cannot mkdirs this from agent: - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new MkDirsWriter(new File(topLevelProjectDir, "modules")))); - - final File mavenModuleDir = new File(topLevelProjectDir, "modules/pretend-maven-module"); - assertTrue(mavenModuleDir.mkdirs()); - - // module-level archived stuff: - invokeOnAgent(new MkDirsWriter(new File(mavenModuleDir, "javadoc"))); - invokeOnAgent(new MkDirsWriter(new File(mavenModuleDir, "test-javadoc"))); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new MkDirsWriter(new File(mavenModuleDir, "site")))); - invokeOnAgent(new MkDirsWriter(new File(mavenModuleDir, "cobertura"))); - } - - @Issue("SECURITY-2455") // general issue -- Maven Projects would no longer be allowed to perform some actions - @Test - public void testMavenReportersAllowListForJobInFolder() throws Exception { - final MockFolder theFolder = j.createFolder("theFolder"); - { - // basic child job - final FreeStyleProject childProject = theFolder.createProject(FreeStyleProject.class, "child"); - final File childProjectRootDir = childProject.getRootDir(); - - // project-level archived stuff for child project inside folder: - invokeOnAgent(new MkDirsWriter(new File(childProjectRootDir, "javadoc"))); - invokeOnAgent(new MkDirsWriter(new File(childProjectRootDir, "test-javadoc"))); - invokeOnAgent(new MkDirsWriter(new File(childProjectRootDir, "site"))); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new MkDirsWriter(new File(childProjectRootDir, "cobertura")))); - } - - { // misleadingly named child job (like one of the approved folders): - final FreeStyleProject siteChildProject = theFolder.createProject(FreeStyleProject.class, "site"); - final File siteChildProjectRootDir = siteChildProject.getRootDir(); - - // cannot mkdirs this from agent despite 'site' in the path (but on wrong level): - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new MkDirsWriter(siteChildProjectRootDir))); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new MkDirsWriter(new File(siteChildProjectRootDir, "foo")))); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new MkDirsWriter(new File(siteChildProjectRootDir, "modules")))); - - // project-level archived stuff for another child inside folder: - invokeOnAgent(new MkDirsWriter(new File(siteChildProjectRootDir, "javadoc"))); - invokeOnAgent(new MkDirsWriter(new File(siteChildProjectRootDir, "test-javadoc"))); - invokeOnAgent(new MkDirsWriter(new File(siteChildProjectRootDir, "site"))); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new MkDirsWriter(new File(siteChildProjectRootDir, "cobertura")))); - - final File childProjectMavenModuleDir = new File(siteChildProjectRootDir, "modules/pretend-maven-module"); - assertTrue(childProjectMavenModuleDir.mkdirs()); - - // module-level archived stuff: - invokeOnAgent(new MkDirsWriter(new File(childProjectMavenModuleDir, "javadoc"))); - invokeOnAgent(new MkDirsWriter(new File(childProjectMavenModuleDir, "test-javadoc"))); - assertThrowsIOExceptionCausedBySecurityException(() -> invokeOnAgent(new MkDirsWriter(new File(childProjectMavenModuleDir, "site")))); - invokeOnAgent(new MkDirsWriter(new File(childProjectMavenModuleDir, "cobertura"))); - } - } - - private static class MkDirsWriter extends MasterToSlaveCallable { - private final File root; - - private MkDirsWriter(File root) { - this.root = root; - } - - @Override - public Object call() throws Exception { - toFilePathOnController(root).mkdirs(); - toFilePathOnController(new File(root, "file.txt")).write("text", "UTF-8"); - return null; - } - } - - // -------- - - // Misc tests - - @LocalData - @Test - public void testRemoteLocalUnzip() throws Exception { - final DumbSlave onlineSlave = j.createOnlineSlave(); - final File zipFile = new File(j.jenkins.getRootDir(), "file.zip"); - assertTrue(zipFile.isFile()); - final FilePath agentRootPath = onlineSlave.getRootPath(); - final FilePath agentZipPath = agentRootPath.child("file.zip"); - new FilePath(zipFile).copyTo(agentZipPath); - agentZipPath.unzip(agentRootPath); - } - - // -------- - - // Utility functions - - protected static FilePath toFilePathOnController(File file) { - return toFilePathOnController(file.getPath()); - } - - protected static FilePath toFilePathOnController(String path) { - final VirtualChannel channel = AgentComputerUtil.getChannelToMaster(); - return new FilePath(channel, path); - } - - protected Node agent; - - protected T invokeOnAgent(MasterToSlaveCallable callable) throws Exception, X { - if (agent == null) { - agent = j.createOnlineSlave(); - } - return Objects.requireNonNull(agent.getChannel()).call(callable); - } - - private static SecurityException assertThrowsIOExceptionCausedBySecurityException(ThrowingRunnable runnable) { - return assertThrowsIOExceptionCausedBy(SecurityException.class, runnable); - } - - private static X assertThrowsIOExceptionCausedBy(Class causeClass, ThrowingRunnable runnable) { - try { - runnable.run(); - } catch (IOException ex) { - final Throwable cause = ex.getCause(); - assertTrue("IOException with message: '" + ex.getMessage() + "' wasn't caused by " + causeClass + ": " + (cause == null ? "(null)" : (cause.getClass().getName() + ": " + cause.getMessage())), - cause != null && causeClass.isAssignableFrom(cause.getClass())); - return causeClass.cast(cause); - } catch (Throwable t) { - fail("Threw other Throwable: " + t.getClass() + " with message " + t.getMessage()); - } - fail("Expected exception but passed"); - return null; - } -} diff --git a/test/src/test/java/jenkins/security/Security2458Test.java b/test/src/test/java/jenkins/security/Security2458Test.java index 795742aa1c318..fcd0e85b80acc 100644 --- a/test/src/test/java/jenkins/security/Security2458Test.java +++ b/test/src/test/java/jenkins/security/Security2458Test.java @@ -9,7 +9,6 @@ import java.util.Objects; import jenkins.agents.AgentComputerUtil; import jenkins.security.s2m.AdminWhitelistRule; -import jenkins.security.s2m.CallableDirectionChecker; import org.jenkinsci.remoting.RoleChecker; import org.junit.Before; import org.junit.Rule; @@ -32,19 +31,11 @@ public void rejectBadCallable() throws Throwable { // If the role check is empty, fail assertThrowsIOExceptionCausedBySecurityException(() -> Objects.requireNonNull(r.createOnlineSlave().getChannel()).call(new CallableCaller(new BadCallable()))); - // If it performs a no-op check, pass. Never do this in your plugin. - Objects.requireNonNull(r.createOnlineSlave().getChannel()).call(new CallableCaller(new EvilCallable())); + // If it performs a no-op check, fail. This used to work when required role checks were introduced, but later prohibited. + assertThrowsIOExceptionCausedBySecurityException(() -> Objects.requireNonNull(r.createOnlineSlave().getChannel()).call(new CallableCaller(new EvilCallable()))); // Explicit role check. Objects.requireNonNull(r.createOnlineSlave().getChannel()).call(new CallableCaller(new GoodCallable())); - - // No-op role checks can be disallowed - System.setProperty(CallableDirectionChecker.class.getName() + ".allowAnyRole", "false"); - try { - assertThrowsIOExceptionCausedBySecurityException(() -> Objects.requireNonNull(r.createOnlineSlave().getChannel()).call(new CallableCaller(new EvilCallable()))); - } finally { - System.clearProperty(CallableDirectionChecker.class.getName() + ".allowAnyRole"); - } } private static class CallableCaller extends MasterToSlaveCallable { @@ -66,6 +57,7 @@ private static class BadCallable implements Callable { public Object call() throws Exception { return null; } + @Override public void checkRoles(RoleChecker checker) throws SecurityException { // Deliberately empty @@ -77,9 +69,10 @@ private static class EvilCallable implements Callable { public Object call() throws Exception { return null; } + @Override public void checkRoles(RoleChecker checker) throws SecurityException { - checker.check(this); // Never do this + checker.check(this); // Was supported in 2.319 but later dropped } } @@ -88,6 +81,7 @@ private static class GoodCallable implements Callable { public Object call() throws Exception { return null; } + @Override public void checkRoles(RoleChecker checker) throws SecurityException { checker.check(this, Roles.MASTER); // Manual S2M diff --git a/test/src/test/java/jenkins/security/Security380Test.java b/test/src/test/java/jenkins/security/Security380Test.java index ff3edae589adf..3e74f229a2f3d 100644 --- a/test/src/test/java/jenkins/security/Security380Test.java +++ b/test/src/test/java/jenkins/security/Security380Test.java @@ -90,7 +90,7 @@ public String getUrlName() { } public HttpResponse doIndex() throws Exception { - return HttpResponses.plainText(Integer.toString(Jenkins.get().getItems().size())); + return HttpResponses.text(Integer.toString(Jenkins.get().getItems().size())); } } } diff --git a/test/src/test/java/jenkins/security/Security637Test.java b/test/src/test/java/jenkins/security/Security637Test.java index 4a94118708f3a..de9e0c0b83d2f 100644 --- a/test/src/test/java/jenkins/security/Security637Test.java +++ b/test/src/test/java/jenkins/security/Security637Test.java @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + package jenkins.security; import static org.hamcrest.CoreMatchers.containsString; @@ -29,7 +30,9 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assume.assumeNoException; +import hudson.EnvVars; import hudson.Launcher; import hudson.model.AbstractBuild; import hudson.model.BuildListener; @@ -37,6 +40,7 @@ import hudson.model.JobProperty; import hudson.model.JobPropertyDescriptor; import hudson.slaves.DumbSlave; +import hudson.util.VersionNumber; import java.io.IOException; import java.lang.reflect.Field; import java.net.URL; @@ -44,7 +48,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; -import org.apache.commons.lang.StringUtils; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; @@ -53,30 +56,33 @@ import org.jvnet.hudson.test.TestExtension; public class Security637Test { - + @Rule public JenkinsSessionRule sessions = new JenkinsSessionRule(); - + @Test @Issue("SECURITY-637") public void urlSafeDeserialization_handler_inSameJVMRemotingContext() throws Throwable { sessions.then(j -> { - DumbSlave slave = j.createOnlineSlave(); + EnvVars envVars = new VersionNumber(System.getProperty("java.specification.version")).isOlderThan(new VersionNumber("9")) + ? null + : new EnvVars("JAVA_TOOL_OPTIONS", "--add-opens=java.base/java.net=ALL-UNNAMED"); + DumbSlave slave = j.createOnlineSlave(null, envVars); String unsafeHandlerClassName = slave.getChannel().call(new URLHandlerCallable(new URL("https://www.google.com/"))); assertThat(unsafeHandlerClassName, containsString("SafeURLStreamHandler")); - + String safeHandlerClassName = slave.getChannel().call(new URLHandlerCallable(new URL("file", null, -1, "", null))); assertThat(safeHandlerClassName, not(containsString("SafeURLStreamHandler"))); }); } - + private static class URLHandlerCallable extends MasterToSlaveCallable { private URL url; - + URLHandlerCallable(URL url) { this.url = url; } - + @Override public String call() throws Exception { Field handlerField = URL.class.getDeclaredField("handler"); @@ -98,14 +104,14 @@ public void urlDnsEquivalence() throws Throwable { ); }); } - + @Ignore("TODO these map to different IPs now") @Test @Issue("SECURITY-637") public void urlSafeDeserialization_urlBuiltInAgent_inSameJVMRemotingContext() throws Throwable { sessions.then(j -> { DumbSlave slave = j.createOnlineSlave(); - + // we bypass the standard equals method that resolve the hostname assertThat( slave.getChannel().call(new URLBuilderCallable("https://jenkins.io")), @@ -115,27 +121,27 @@ public void urlSafeDeserialization_urlBuiltInAgent_inSameJVMRemotingContext() th ); }); } - + private static class URLBuilderCallable extends MasterToSlaveCallable { private String url; - + URLBuilderCallable(String url) { this.url = url; } - + @Override public URL call() throws Exception { return new URL(url); } } - + @Ignore("TODO these map to different IPs now") @Test @Issue("SECURITY-637") public void urlSafeDeserialization_urlBuiltInMaster_inSameJVMRemotingContext() throws Throwable { sessions.then(j -> { DumbSlave slave = j.createOnlineSlave(); - + // we bypass the standard equals method that resolve the hostname assertThat( slave.getChannel().call(new URLTransferCallable(new URL("https://jenkins.io"))), @@ -143,7 +149,7 @@ public void urlSafeDeserialization_urlBuiltInMaster_inSameJVMRemotingContext() t slave.getChannel().call(new URLTransferCallable(new URL("https://www.jenkins.io"))) )) ); - + // due to the DNS resolution they are equal assertEquals( new URL("https://jenkins.io"), @@ -151,21 +157,21 @@ public void urlSafeDeserialization_urlBuiltInMaster_inSameJVMRemotingContext() t ); }); } - + // the URL is serialized / deserialized twice, master => agent and then agent => master private static class URLTransferCallable extends MasterToSlaveCallable { private URL url; - + URLTransferCallable(URL url) { this.url = url; } - + @Override public URL call() throws Exception { return url; } } - + @Test @Issue("SECURITY-637") public void urlSafeDeserialization_inXStreamContext() throws Throwable { @@ -178,21 +184,25 @@ public void urlSafeDeserialization_inXStreamContext() throws Throwable { new URL("https", null, -1, "", null) ); project.addProperty(URLJobProperty); - + project.save(); }); - + sessions.then(j -> { FreeStyleProject project = j.jenkins.getItemByFullName("project-with-url", FreeStyleProject.class); assertNotNull(project); - + Field handlerField = URL.class.getDeclaredField("handler"); - handlerField.setAccessible(true); - + try { + handlerField.setAccessible(true); + } catch (RuntimeException e) { + assumeNoException(e); + } + URLJobProperty urlJobProperty = project.getProperty(URLJobProperty.class); for (URL url : urlJobProperty.urlSet) { URLStreamHandler handler = (URLStreamHandler) handlerField.get(url); - if (StringUtils.isEmpty(url.getHost())) { + if (url.getHost() == null || url.getHost().isEmpty()) { assertThat(handler.getClass().getName(), not(containsString("SafeURLStreamHandler"))); } else { assertThat(handler.getClass().getName(), containsString("SafeURLStreamHandler")); @@ -200,21 +210,21 @@ public void urlSafeDeserialization_inXStreamContext() throws Throwable { } }); } - + public static class URLJobProperty extends JobProperty { - + private Set urlSet; - + public URLJobProperty(URL... urls) { this.urlSet = new HashSet<>(); Collections.addAll(urlSet, urls); } - + @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { return true; } - + @TestExtension("urlSafeDeserialization_inXStreamContext") public static class DescriptorImpl extends JobPropertyDescriptor {} } diff --git a/test/src/test/java/jenkins/security/Security857Test.java b/test/src/test/java/jenkins/security/Security857Test.java index 81672baf8070d..3822d95805f37 100644 --- a/test/src/test/java/jenkins/security/Security857Test.java +++ b/test/src/test/java/jenkins/security/Security857Test.java @@ -3,8 +3,9 @@ import com.gargoylesoftware.htmlunit.HttpMethod; import com.gargoylesoftware.htmlunit.WebRequest; import com.gargoylesoftware.htmlunit.WebResponse; -import hudson.util.IOUtils; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; @@ -17,8 +18,6 @@ */ public class Security857Test { - private static String EVIDENCE = "