diff --git a/.mvn/jvm.config b/.mvn/jvm.config new file mode 100644 index 0000000000..e93a5b43ee --- /dev/null +++ b/.mvn/jvm.config @@ -0,0 +1 @@ +-Xmx800m diff --git a/Jenkinsfile b/Jenkinsfile index c3e7b6b643..cc03884ab9 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,4 +1,3 @@ -#!groovy /* * This Jenkinsfile is intended to run on https://ci.jenkins-ci.org and may fail anywhere else. * It makes assumptions about plugins being installed, labels mapping to nodes that can build what is needed, etc. @@ -16,7 +15,7 @@ properties([[$class: 'jenkins.model.BuildDiscarderProperty', strategy: [$class: numToKeepStr: '50', artifactNumToKeepStr: '20']]]) -String packagingBranch = (binding.hasVariable('packagingBranch')) ? packagingBranch : 'master' +String packagingBranch = (binding.hasVariable('packagingBranch')) ? packagingBranch : 'jenkins-2.0' timestampedNode('java') { @@ -166,7 +165,7 @@ void withMavenEnv(List envVars = [], def body) { // Using the "tool" Workflow call automatically installs those tools on the // node. String mvntool = tool name: "mvn3.3.3", type: 'hudson.tasks.Maven$MavenInstallation' - String jdktool = tool name: "jdk7_80", type: 'hudson.model.JDK' + String jdktool = tool name: "jdk8_51", type: 'hudson.model.JDK' // Set JAVA_HOME, MAVEN_HOME and special PATH variables for the tools we're // using. diff --git a/README.md b/README.md index f815b2ea6b..501778372d 100644 --- a/README.md +++ b/README.md @@ -53,12 +53,12 @@ Jenkins is **licensed** under the **[MIT License]**. The terms of the license ar OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -[ButlerImage]: http://jenkins-ci.org/sites/default/files/jenkins_logo.png +[ButlerImage]: https://jenkins.io/sites/default/files/jenkins_logo.png [MIT License]: https://github.com/jenkinsci/jenkins/raw/master/LICENSE.txt [Mirrors]: http://mirrors.jenkins-ci.org [GitHub]: https://github.com/jenkinsci/jenkins -[website]: http://jenkins-ci.org -[@jenkinsci]: http://twitter.com/jenkinsci +[website]: https://jenkins.io/ +[@jenkinsci]: https://twitter.com/jenkinsci [Contributing]: https://wiki.jenkins-ci.org/display/JENKINS/contributing [Extend Jenkins]: https://wiki.jenkins-ci.org/display/JENKINS/Extend+Jenkins [wiki]: https://wiki.jenkins-ci.org diff --git a/changelog.html b/changelog.html index 039e713471..e04568957c 100644 --- a/changelog.html +++ b/changelog.html @@ -24,7 +24,7 @@ Some tips: - +
Legend: @@ -33,6 +33,7 @@ Some tips: major bugmajor bug fix bugbug fix xxxxx
+

What's new in 1.653 (2016/03/13)

What's new in 1.652 (2016/03/06)

What's new in 1.651 (2016/02/28)

-Older changelogs can be found in a separate file +Older changelogs can be found in a separate file diff --git a/cli/pom.xml b/cli/pom.xml index 992b9f05c1..d8e6094ef6 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -5,7 +5,7 @@ org.jenkins-ci.main pom - 2.0-alpha-5-SNAPSHOT + 2.1-SNAPSHOT cli diff --git a/cli/src/main/java/hudson/cli/CLI.java b/cli/src/main/java/hudson/cli/CLI.java index de2d2bd795..9eca2ec8ef 100644 --- a/cli/src/main/java/hudson/cli/CLI.java +++ b/cli/src/main/java/hudson/cli/CLI.java @@ -131,13 +131,7 @@ public class CLI { try { _channel = connectViaHttp(url); } catch (IOException e2) { - try { // Java 7: e.addSuppressed(e2); - Throwable.class.getMethod("addSuppressed", Throwable.class).invoke(e, e2); - } catch (NoSuchMethodException _ignore) { - // Java 6 - } catch (Exception _huh) { - LOGGER.log(Level.SEVERE, null, _huh); - } + e.addSuppressed(e2); throw e; } } diff --git a/cli/src/main/resources/hudson/cli/client/Messages_de.properties b/cli/src/main/resources/hudson/cli/client/Messages_de.properties index aa7972afa4..55769d64de 100644 --- a/cli/src/main/resources/hudson/cli/client/Messages_de.properties +++ b/cli/src/main/resources/hudson/cli/client/Messages_de.properties @@ -3,11 +3,12 @@ CLI.Usage=Jenkins Kommandozeilenschnittstelle (Jenkins CLI)\n\ Verwendung: java -jar jenkins-cli.jar [-s URL] command [opts...] args...\n\ Optionen:\n\ -s URL : URL des Hudson-Servers (Wert der Umgebungsvariable JENKINS_URL ist der Vorgabewert)\n\ - -i KEY : Datei mit privatem SSH-Schlüssel zur Authentisierung\n\ - -p HOST\:PORT : HTTP-Proxy-Host und -Port für HTTPS-Proxy-Tunnel. Siehe http://jenkins-ci.org/https-proxy-tunnel\n\ - -noCertificateCheck : Überspringt die Zertifikatsprüfung bei HTTPS. Bitte mit Vorsicht einsetzen.\n\ + -i KEY : Datei mit privatem SSH-Schl\u00fcssel zur Authentisierung\n\ + -p HOST\:PORT : HTTP-Proxy-Host und -Port f\u00fcr HTTPS-Proxy-Tunnel. Siehe http://jenkins-ci.org/https-proxy-tunnel\n\ + -noCertificateCheck : \u00dcberspringt die Zertifikatspr\u00fcfung bei HTTPS. Bitte mit Vorsicht einsetzen.\n\ + -noKeyAuth : \u00dcberspringt die Authentifizierung mit einem privaten SSH-Schl\u00fcssel. Nicht kombinierbar mit -i\n\ \n\ - Die verfügbaren Kommandos hängen vom kontaktierten Server ab. Verwenden Sie das Kommando help, um eine Liste aller verfügbaren Kommandos anzuzeigen. + Die verf\u00fcgbaren Kommandos h\u00e4ngen vom kontaktierten Server ab. Verwenden Sie das Kommando help, um eine Liste aller verf\u00fcgbaren Kommandos anzuzeigen. CLI.NoURL=Weder die Option -s noch eine Umgebungsvariable JENKINS_URL wurde spezifiziert. CLI.NoSuchFileExists=Diese Datei existiert nicht {0} CLI.VersionMismatch=Versionskonflikt: Diese Version von Jenkins CLI ist nicht mit dem kontaktierten Jenkins-Server kompatibel. diff --git a/core/pom.xml b/core/pom.xml index ac6b04361b..bbda721530 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -29,7 +29,7 @@ THE SOFTWARE. org.jenkins-ci.main pom - 2.0-alpha-5-SNAPSHOT + 2.1-SNAPSHOT jenkins-core @@ -39,7 +39,7 @@ THE SOFTWARE. true - 1.240 + 1.239 2.5.6.SEC03 2.4.6 diff --git a/core/src/main/java/hudson/ClassicPluginStrategy.java b/core/src/main/java/hudson/ClassicPluginStrategy.java index 6903addc10..bbaed01f52 100644 --- a/core/src/main/java/hudson/ClassicPluginStrategy.java +++ b/core/src/main/java/hudson/ClassicPluginStrategy.java @@ -59,6 +59,7 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.net.URL; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -206,21 +207,8 @@ public class ClassicPluginStrategy implements PluginStrategy { if (libs != null) paths.addAll(Arrays.asList(libs)); - try { - Class pathJDK7 = Class.forName("java.nio.file.Path"); - Object toPath = File.class.getMethod("toPath").invoke(expandDir); - URI uri = (URI) pathJDK7.getMethod("toUri").invoke(toPath); + baseResourceURL = expandDir.toPath().toUri().toURL(); - baseResourceURL = uri.toURL(); - } catch (NoSuchMethodException e) { - throw new Error(e); - } catch (ClassNotFoundException e) { - baseResourceURL = expandDir.toURI().toURL(); - } catch (InvocationTargetException e) { - throw new Error(e); - } catch (IllegalAccessException e) { - throw new Error(e); - } } File disableFile = new File(archive.getPath() + ".disabled"); if (disableFile.exists()) { @@ -514,13 +502,9 @@ public class ClassicPluginStrategy implements PluginStrategy { throw new IOException(className+" doesn't extend from hudson.Plugin"); } wrapper.setPlugin((Plugin) o); - } catch (LinkageError e) { + } catch (LinkageError | ClassNotFoundException e) { throw new IOException("Unable to load " + className + " from " + wrapper.getShortName(),e); - } catch (ClassNotFoundException e) { - throw new IOException("Unable to load " + className + " from " + wrapper.getShortName(),e); - } catch (IllegalAccessException e) { - throw new IOException("Unable to create instance of " + className + " from " + wrapper.getShortName(),e); - } catch (InstantiationException e) { + } catch (IllegalAccessException | InstantiationException e) { throw new IOException("Unable to create instance of " + className + " from " + wrapper.getShortName(),e); } } @@ -849,9 +833,7 @@ public class ClassicPluginStrategy implements PluginStrategy { Field $pathComponents = AntClassLoader.class.getDeclaredField("pathComponents"); $pathComponents.setAccessible(true); pathComponents = (Vector)$pathComponents.get(this); - } catch (NoSuchFieldException e) { - throw new Error(e); - } catch (IllegalAccessException e) { + } catch (NoSuchFieldException | IllegalAccessException e) { throw new Error(e); } } diff --git a/core/src/main/java/hudson/ExtensionFinder.java b/core/src/main/java/hudson/ExtensionFinder.java index 1647abce6f..d262f68001 100644 --- a/core/src/main/java/hudson/ExtensionFinder.java +++ b/core/src/main/java/hudson/ExtensionFinder.java @@ -422,10 +422,7 @@ public abstract class ExtensionFinder implements ExtensionPoint { public T get() { try { return base.get(); - } catch (Exception e) { - error(key, e); - return null; - } catch (LinkageError e) { + } catch (Exception | LinkageError e) { error(key, e); return null; } @@ -496,10 +493,7 @@ public abstract class ExtensionFinder implements ExtensionPoint { @SuppressWarnings({"unchecked", "ChainOfInstanceofChecks"}) @Override protected void configure() { - int id=0; - for (final IndexItem item : index) { - id++; boolean optional = isOptional(item.annotation()); try { AnnotatedElement e = item.element(); @@ -524,8 +518,8 @@ public abstract class ExtensionFinder implements ExtensionPoint { resolve(extType); - // use arbitrary id to make unique key, because Guice wants that. - Key key = Key.get(extType, Names.named(String.valueOf(id))); + // make unique key, because Guice wants that. + Key key = Key.get(extType, Names.named(item.className() + "." + item.memberName())); annotations.put(key,a); bind(key).toProvider(new Provider() { public Object get() { diff --git a/core/src/main/java/hudson/Functions.java b/core/src/main/java/hudson/Functions.java index 4142366f42..188412b3c3 100644 --- a/core/src/main/java/hudson/Functions.java +++ b/core/src/main/java/hudson/Functions.java @@ -130,7 +130,6 @@ import javax.servlet.http.HttpServletResponse; import jenkins.model.GlobalConfiguration; import jenkins.model.GlobalConfigurationCategory; -import jenkins.model.GlobalConfigurationCategory.Unclassified; import jenkins.model.Jenkins; import jenkins.model.ModelObjectWithChildren; import jenkins.model.ModelObjectWithContextMenu; @@ -965,12 +964,8 @@ public class Functions { Descriptor d = c.getInstance(); if (d.getGlobalConfigPage()==null) continue; - if (d instanceof GlobalConfiguration) { - if (predicate.apply(((GlobalConfiguration)d).getCategory())) - r.add(new Tag(c.ordinal(), d)); - } else { - if (predicate.apply(GlobalConfigurationCategory.get(Unclassified.class))) - r.add(new Tag(0, d)); + if (predicate.apply(d.getCategory())) { + r.add(new Tag(c.ordinal(), d)); } } Collections.sort(r); @@ -1537,10 +1532,12 @@ public class Functions { /** * Computes the hyperlink to actions, to handle the situation when the {@link Action#getUrlName()} * returns absolute URL. + * + * @return null in case the action should not be presented to the user. */ - public static String getActionUrl(String itUrl,Action action) { + public static @CheckForNull String getActionUrl(String itUrl,Action action) { String urlName = action.getUrlName(); - if(urlName==null) return null; // to avoid NPE and fail to render the whole page + if(urlName==null) return null; // Should not be displayed try { if (new URI(urlName).isAbsolute()) { return urlName; @@ -1925,7 +1922,7 @@ public class Functions { TcpSlaveAgentListener tal = j.tcpSlaveAgentListener; if (tal !=null) { - int p = TcpSlaveAgentListener.CLI_PORT !=null ? TcpSlaveAgentListener.CLI_PORT : tal.getPort(); + int p = tal.getAdvertisedPort(); rsp.setIntHeader("X-Hudson-CLI-Port", p); rsp.setIntHeader("X-Jenkins-CLI-Port", p); rsp.setIntHeader("X-Jenkins-CLI2-Port", p); diff --git a/core/src/main/java/hudson/PluginManager.java b/core/src/main/java/hudson/PluginManager.java index ae96fc347a..a18c9fcac0 100644 --- a/core/src/main/java/hudson/PluginManager.java +++ b/core/src/main/java/hudson/PluginManager.java @@ -36,6 +36,8 @@ import hudson.model.Failure; import hudson.model.ItemGroupMixIn; import hudson.model.UpdateCenter; import hudson.model.UpdateSite; +import hudson.model.UpdateCenter.DownloadJob; +import hudson.model.UpdateCenter.InstallationJob; import hudson.security.Permission; import hudson.security.PermissionScope; import hudson.util.CyclicGraphDetector; @@ -62,6 +64,7 @@ import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.LogFactory; import org.jenkinsci.Symbol; import org.jenkinsci.bytecode.Transformer; @@ -994,6 +997,7 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas */ @Restricted(DoNotUse.class) // WebOnly public HttpResponse doPlugins() { + Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); JSONArray response = new JSONArray(); Map allPlugins = new HashMap<>(); for (PluginWrapper plugin : plugins) { @@ -1006,6 +1010,7 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas pluginInfo.put("bundled", plugin.isBundled); pluginInfo.put("deleted", plugin.isDeleted()); pluginInfo.put("downgradable", plugin.isDowngradable()); + pluginInfo.put("website", plugin.getUrl()); List dependencies = plugin.getDependencies(); if (dependencies != null && !dependencies.isEmpty()) { Map dependencyMap = new HashMap<>(); @@ -1030,6 +1035,7 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas pluginInfo.put("excerpt", plugin.excerpt); pluginInfo.put("site", site.getId()); pluginInfo.put("dependencies", plugin.dependencies); + pluginInfo.put("website", plugin.wiki); response.add(pluginInfo); } } @@ -1054,11 +1060,26 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas return new HttpRedirect("./sites"); } + + /** + * Called to progress status beyond installing plugins, e.g. if + * there were failures that prevented installation from naturally proceeding + */ + @RequirePOST + @Restricted(DoNotUse.class) // WebOnly + public void doInstallPluginsDone() { + Jenkins j = Jenkins.getInstance(); + j.checkPermission(Jenkins.ADMINISTER); + if(InstallState.INITIAL_PLUGINS_INSTALLING.equals(j.getInstallState())) { + Jenkins.getInstance().setInstallState(InstallState.INITIAL_PLUGINS_INSTALLING.getNextState()); + } + } /** * Performs the installation of the plugins. */ public void doInstall(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { + Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); Set plugins = new LinkedHashSet<>(); Enumeration en = req.getParameterNames(); @@ -1087,6 +1108,7 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas @RequirePOST @Restricted(DoNotUse.class) // WebOnly public HttpResponse doInstallPlugins(StaplerRequest req) throws IOException { + Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); String payload = IOUtils.toString(req.getInputStream(), req.getCharacterEncoding()); JSONObject request = JSONObject.fromObject(payload); JSONArray pluginListJSON = request.getJSONArray("plugins"); @@ -1119,6 +1141,7 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas * @return The install job list. * @since FIXME */ + @Restricted(NoExternalUse.class) public List> install(@Nonnull Collection plugins, boolean dynamicLoad) { return install(plugins, dynamicLoad, null); } @@ -1178,23 +1201,30 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas new Thread() { @Override public void run() { + boolean failures = false; INSTALLING: while (true) { try { - updateCenter.persistInstallStatus(); + updateCenter.persistInstallStatus(); Thread.sleep(500); + failures = false; for (Future jobFuture : installJobs) { if(!jobFuture.isDone() && !jobFuture.isCancelled()) { continue INSTALLING; } + UpdateCenter.UpdateCenterJob job = jobFuture.get(); + if(job instanceof InstallationJob && ((InstallationJob)job).status instanceof DownloadJob.Failure) { + failures = true; + } } - } catch (InterruptedException e) { + } catch (Exception e) { LOGGER.log(WARNING, "Unexpected error while waiting for initial plugin set to install.", e); } break; } - updateCenter.persistInstallStatus(); - jenkins.setInstallState(InstallState.INITIAL_PLUGINS_INSTALLING.getNextState()); - InstallUtil.saveLastExecVersion(); + updateCenter.persistInstallStatus(); + if(!failures) { + jenkins.setInstallState(InstallState.INITIAL_PLUGINS_INSTALLING.getNextState()); + } } }.start(); } @@ -1300,12 +1330,33 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas pluginUploaded = true; + JSONArray dependencies = new JSONArray(); + try { + Manifest m = new JarFile(t).getManifest(); + String deps = m.getMainAttributes().getValue("Plugin-Dependencies"); + + if (StringUtils.isNotBlank(deps)) { + // now we get to parse it! + String[] plugins = deps.split(","); + for (String p : plugins) { + // should have name:version[;resolution:=optional] + String[] attrs = p.split("[:;]"); + dependencies.add(new JSONObject() + .element("name", attrs[0]) + .element("version", attrs[1]) + .element("optional", p.contains("resolution:=optional"))); + } + } + } catch(IOException e) { + LOGGER.log(WARNING, "Unable to setup dependency list for plugin upload", e); + } + // Now create a dummy plugin that we can dynamically load (the InstallationJob will force a restart if one is needed): JSONObject cfg = new JSONObject(). element("name", baseName). element("version", "0"). // unused but mandatory element("url", t.toURI().toString()). - element("dependencies", new JSONArray()); + element("dependencies", dependencies); new UpdateSite(UpdateCenter.ID_UPLOAD, null).new Plugin(UpdateCenter.ID_UPLOAD, cfg).deploy(true); return new HttpRedirect("../updateCenter"); } catch (IOException e) { diff --git a/core/src/main/java/hudson/PluginWrapper.java b/core/src/main/java/hudson/PluginWrapper.java index c30dba8ae2..cdfecff910 100644 --- a/core/src/main/java/hudson/PluginWrapper.java +++ b/core/src/main/java/hudson/PluginWrapper.java @@ -656,6 +656,7 @@ public class PluginWrapper implements Comparable, ModelObject { @RequirePOST @Deprecated public HttpResponse doPin() throws IOException { + Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); // See https://groups.google.com/d/msg/jenkinsci-dev/kRobm-cxFw8/6V66uhibAwAJ LOGGER.log(WARNING, "Call to pin plugin has been ignored. Plugin name: " + shortName); return HttpResponses.ok(); @@ -664,6 +665,7 @@ public class PluginWrapper implements Comparable, ModelObject { @RequirePOST @Deprecated public HttpResponse doUnpin() throws IOException { + Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); // See https://groups.google.com/d/msg/jenkinsci-dev/kRobm-cxFw8/6V66uhibAwAJ LOGGER.log(WARNING, "Call to unpin plugin has been ignored. Plugin name: " + shortName); return HttpResponses.ok(); diff --git a/core/src/main/java/hudson/Proc.java b/core/src/main/java/hudson/Proc.java index 598fbca374..c011519101 100644 --- a/core/src/main/java/hudson/Proc.java +++ b/core/src/main/java/hudson/Proc.java @@ -156,11 +156,7 @@ public abstract class Proc { unit.toString().toLowerCase(Locale.ENGLISH)); kill(); } - } catch (InterruptedException x) { - x.printStackTrace(listener.error("Failed to join a process")); - } catch (IOException x) { - x.printStackTrace(listener.error("Failed to join a process")); - } catch (RuntimeException x) { + } catch (InterruptedException | IOException | RuntimeException x) { x.printStackTrace(listener.error("Failed to join a process")); } } diff --git a/core/src/main/java/hudson/ProxyConfiguration.java b/core/src/main/java/hudson/ProxyConfiguration.java index f841953062..3b469494bb 100644 --- a/core/src/main/java/hudson/ProxyConfiguration.java +++ b/core/src/main/java/hudson/ProxyConfiguration.java @@ -75,6 +75,12 @@ import org.kohsuke.stapler.QueryParameter; * @see jenkins.model.Jenkins#proxy */ public final class ProxyConfiguration extends AbstractDescribableImpl implements Saveable, Serializable { + /** + * Holds a default TCP connect timeout set on all connections returned from this class, + * note this is value is in milliseconds, it's passed directly to {@link URLConnection#setConnectTimeout(int)} + */ + private static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = Integer.getInteger("hudson.ProxyConfiguration.DEFAULT_CONNECT_TIMEOUT_MILLIS", 20 * 1000); + public final String name; public final int port; @@ -219,22 +225,29 @@ public final class ProxyConfiguration extends AbstractDescribableImpl 0) { + con.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT_MILLIS); + } + if (JenkinsJVM.isJenkinsJVM()) { // this code may run on a slave decorate(con); } @@ -330,7 +343,7 @@ public final class ProxyConfiguration extends AbstractDescribableImpl 0 ? DEFAULT_CONNECT_TIMEOUT_MILLIS : new Integer(30 * 1000)); HttpClient client = new HttpClient(); if (Util.fixEmptyAndTrim(name) != null) { diff --git a/core/src/main/java/hudson/TcpSlaveAgentListener.java b/core/src/main/java/hudson/TcpSlaveAgentListener.java index 8096c4b9a9..79b48fbf21 100644 --- a/core/src/main/java/hudson/TcpSlaveAgentListener.java +++ b/core/src/main/java/hudson/TcpSlaveAgentListener.java @@ -94,6 +94,14 @@ public final class TcpSlaveAgentListener extends Thread { return serverSocket.socket().getLocalPort(); } + /** + * Gets the TCP port number in which we are advertising. + * @since 1.656 + */ + public int getAdvertisedPort() { + return CLI_PORT != null ? CLI_PORT : getPort(); + } + @Override public void run() { try { diff --git a/core/src/main/java/hudson/Util.java b/core/src/main/java/hudson/Util.java index e9297a83eb..8403a8fd2e 100644 --- a/core/src/main/java/hudson/Util.java +++ b/core/src/main/java/hudson/Util.java @@ -63,6 +63,12 @@ import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.FileSystemException; +import java.nio.file.Files; +import java.nio.file.NotLinkException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.NumberFormat; @@ -251,19 +257,9 @@ public class Util { if(!f.delete() && f.exists()) { // trouble-shooting. - try { - Class.forName("java.nio.file.Files").getMethod("delete", Class.forName("java.nio.file.Path")).invoke(null, File.class.getMethod("toPath").invoke(f)); - } catch (InvocationTargetException x) { - Throwable x2 = x.getCause(); - if (x2 instanceof IOException) { - // may have a specific exception message - throw (IOException) x2; - } - // else suppress - } catch (Throwable x) { - // linkage errors, etc.; suppress - } - // see http://www.nabble.com/Sometimes-can%27t-delete-files-from-hudson.scm.SubversionSCM%24CheckOutTask.invoke%28%29-tt17333292.html + Files.deleteIfExists(f.toPath()); + + // see https://java.net/projects/hudson/lists/users/archive/2008-05/message/357 // I suspect other processes putting files in this directory File[] files = f.listFiles(); if(files!=null && files.length>0) @@ -346,9 +342,7 @@ public class Util { if (Functions.isWindows()) { try { return Kernel32Utils.isJunctionOrSymlink(file); - } catch (UnsupportedOperationException e) { - // fall through - } catch (LinkageError e) { + } catch (UnsupportedOperationException | LinkageError e) { // fall through } } @@ -369,10 +363,8 @@ public class Util { @SuppressWarnings("NP_BOOLEAN_RETURN_NULL") private static Boolean isSymlinkJava7(@Nonnull File file) throws IOException { try { - Object path = File.class.getMethod("toPath").invoke(file); - return (Boolean) Class.forName("java.nio.file.Files").getMethod("isSymbolicLink", Class.forName("java.nio.file.Path")).invoke(null, path); - } catch (NoSuchMethodException x) { - return null; // fine, Java 6 + Path path = file.toPath(); + return Files.isSymbolicLink(path); } catch (Exception x) { throw (IOException) new IOException(x.toString()).initCause(x); } @@ -1220,48 +1212,36 @@ public class Util { private static boolean createSymlinkJava7(@Nonnull File baseDir, @Nonnull String targetPath, @Nonnull String symlinkPath) throws IOException { try { - Object path = File.class.getMethod("toPath").invoke(new File(baseDir, symlinkPath)); - Object target = Class.forName("java.nio.file.Paths").getMethod("get", String.class, String[].class).invoke(null, targetPath, new String[0]); - Class filesC = Class.forName("java.nio.file.Files"); - Class pathC = Class.forName("java.nio.file.Path"); - Class fileAlreadyExistsExceptionC = Class.forName("java.nio.file.FileAlreadyExistsException"); + Path path = new File(baseDir, symlinkPath).toPath(); + Path target = Paths.get(targetPath, new String[0]); - Object noAttrs = Array.newInstance(Class.forName("java.nio.file.attribute.FileAttribute"), 0); final int maxNumberOfTries = 4; final int timeInMillis = 100; for (int tryNumber = 1; tryNumber <= maxNumberOfTries; tryNumber++) { - filesC.getMethod("deleteIfExists", pathC).invoke(null, path); + Files.deleteIfExists(path); try { - filesC.getMethod("createSymbolicLink", pathC, pathC, noAttrs.getClass()).invoke(null, path, target, noAttrs); + Files.createSymbolicLink(path, target); break; - } - catch (Exception x) { - if (fileAlreadyExistsExceptionC.isInstance(x)) { - if(tryNumber < maxNumberOfTries) { - TimeUnit.MILLISECONDS.sleep(timeInMillis); //trying to defeat likely ongoing race condition - continue; - } - LOGGER.warning("symlink FileAlreadyExistsException thrown "+maxNumberOfTries+" times => cannot createSymbolicLink"); + } catch (FileAlreadyExistsException fileAlreadyExistsException) { + if (tryNumber < maxNumberOfTries) { + TimeUnit.MILLISECONDS.sleep(timeInMillis); //trying to defeat likely ongoing race condition + continue; } - throw x; + LOGGER.warning("symlink FileAlreadyExistsException thrown " + maxNumberOfTries + " times => cannot createSymbolicLink"); + throw fileAlreadyExistsException; } } return true; - } catch (NoSuchMethodException x) { - return false; // fine, Java 6 - } catch (InvocationTargetException x) { - Throwable x2 = x.getCause(); - if (x2 instanceof UnsupportedOperationException) { + } catch (UnsupportedOperationException e) { return true; // no symlinks on this platform - } - if (Functions.isWindows() && String.valueOf(x2).contains("java.nio.file.FileSystemException")) { + } catch (FileSystemException e) { + if (Functions.isWindows()) { warnWindowsSymlink(); return true; } - if (x2 instanceof IOException) { - throw (IOException) x2; - } - throw (IOException) new IOException(x.toString()).initCause(x); + return false; + } catch (IOException x) { + throw x; } catch (Exception x) { throw (IOException) new IOException(x.toString()).initCause(x); } @@ -1312,62 +1292,19 @@ public class Util { */ @CheckForNull public static String resolveSymlink(@Nonnull File link) throws InterruptedException, IOException { - try { // Java 7 - Object path = File.class.getMethod("toPath").invoke(link); - return Class.forName("java.nio.file.Files").getMethod("readSymbolicLink", Class.forName("java.nio.file.Path")).invoke(null, path).toString(); - } catch (NoSuchMethodException x) { - // fine, Java 6; fall through - } catch (InvocationTargetException x) { - Throwable x2 = x.getCause(); - if (x2 instanceof UnsupportedOperationException) { - return null; // no symlinks on this platform - } - try { - if (Class.forName("java.nio.file.NotLinkException").isInstance(x2)) { - return null; - } - } catch (ClassNotFoundException x3) { - assert false : x3; // should be Java 7+ here - } - if (x2.getClass().getName().equals("java.nio.file.FileSystemException")) { - // Thrown ("Incorrect function.") on JDK 7u21 in Windows 2012 when called on a non-symlink, rather than NotLinkException, contrary to documentation. Maybe only when not on NTFS? - return null; - } - if (x2 instanceof IOException) { - throw (IOException) x2; - } - throw (IOException) new IOException(x.toString()).initCause(x); + try { + Path path = link.toPath(); + return Files.readSymbolicLink(path).toString(); + } catch (UnsupportedOperationException | FileSystemException x) { + // no symlinks on this platform (windows?), + // or not a link (// Thrown ("Incorrect function.") on JDK 7u21 in Windows 2012 when called on a non-symlink, + // rather than NotLinkException, contrary to documentation. Maybe only when not on NTFS?) ? + return null; + } catch (IOException x) { + throw x; } catch (Exception x) { throw (IOException) new IOException(x.toString()).initCause(x); } - - if(Functions.isWindows()) return null; - - String filename = link.getAbsolutePath(); - try { - for (int sz=512; sz < 65536; sz*=2) { - Memory m = new Memory(sz); - int r = LIBC.readlink(filename,m,new NativeLong(sz)); - if (r<0) { - int err = Native.getLastError(); - if (err==22/*EINVAL --- but is this really portable?*/) - return null; // this means it's not a symlink - throw new IOException("Failed to readlink "+link+" error="+ err+" "+ LIBC.strerror(err)); - } - if (r==sz) - continue; // buffer too small - - byte[] buf = new byte[r]; - m.read(0,buf,0,r); - return new String(buf); - } - // something is wrong. It can't be this long! - throw new IOException("Symlink too long: "+link); - } catch (LinkageError e) { - // if JNA is unavailable, fall back. - // we still prefer to try JNA first as PosixAPI supports even smaller platforms. - return PosixAPI.jnr().readlink(filename); - } } /** diff --git a/core/src/main/java/hudson/WebAppMain.java b/core/src/main/java/hudson/WebAppMain.java index 7a5a78c5f2..fce3cafa1f 100644 --- a/core/src/main/java/hudson/WebAppMain.java +++ b/core/src/main/java/hudson/WebAppMain.java @@ -27,6 +27,7 @@ import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider import com.thoughtworks.xstream.core.JVM; import com.trilead.ssh2.util.IOUtils; import hudson.model.Hudson; +import hudson.security.ACL; import hudson.util.BootFailure; import jenkins.model.Jenkins; import hudson.util.HudsonIsLoading; @@ -244,11 +245,8 @@ public class WebAppMain implements ServletContextListener { }; initThread.start(); } catch (BootFailure e) { - e.publish(context,home); - } catch (Error e) { - LOGGER.log(SEVERE, "Failed to initialize Jenkins",e); - throw e; - } catch (RuntimeException e) { + e.publish(context, home); + } catch (Error | RuntimeException e) { LOGGER.log(SEVERE, "Failed to initialize Jenkins",e); throw e; } @@ -367,19 +365,24 @@ public class WebAppMain implements ServletContextListener { public void contextDestroyed(ServletContextEvent event) { try { - terminated = true; - Jenkins instance = Jenkins.getInstanceOrNull(); - if(instance!=null) - instance.cleanUp(); - Thread t = initThread; - if (t != null && t.isAlive()) { - LOGGER.log(Level.INFO, "Shutting down a Jenkins instance that was still starting up", new Throwable("reason")); - t.interrupt(); - } + ACL.impersonate(ACL.SYSTEM, new Runnable() { + @Override + public void run() { + terminated = true; + Jenkins instance = Jenkins.getInstanceOrNull(); + if (instance != null) + instance.cleanUp(); + Thread t = initThread; + if (t != null && t.isAlive()) { + LOGGER.log(Level.INFO, "Shutting down a Jenkins instance that was still starting up", new Throwable("reason")); + t.interrupt(); + } - // Logger is in the system classloader, so if we don't do this - // the whole web app will never be undepoyed. - Logger.getLogger("").removeHandler(handler); + // Logger is in the system classloader, so if we don't do this + // the whole web app will never be undepoyed. + Logger.getLogger("").removeHandler(handler); + } + }); } finally { JenkinsJVMAccess._setJenkinsJVM(false); } diff --git a/core/src/main/java/hudson/cli/CLICommand.java b/core/src/main/java/hudson/cli/CLICommand.java index 2272ef64bd..e379f9fcb3 100644 --- a/core/src/main/java/hudson/cli/CLICommand.java +++ b/core/src/main/java/hudson/cli/CLICommand.java @@ -523,9 +523,7 @@ public abstract class CLICommand implements ExtensionPoint, Cloneable { protected CLICommand createClone() { try { return getClass().newInstance(); - } catch (IllegalAccessException e) { - throw new AssertionError(e); - } catch (InstantiationException e) { + } catch (IllegalAccessException | InstantiationException e) { throw new AssertionError(e); } } diff --git a/core/src/main/java/hudson/cli/CliProtocol2.java b/core/src/main/java/hudson/cli/CliProtocol2.java index 93ecde9c60..a4893cfd94 100644 --- a/core/src/main/java/hudson/cli/CliProtocol2.java +++ b/core/src/main/java/hudson/cli/CliProtocol2.java @@ -70,13 +70,7 @@ public class CliProtocol2 extends CliProtocol { signer.initSign(instanceId); signer.update(secret); c.writeByteArray(signer.sign()); - } catch (ClassNotFoundException e) { - throw new Error(e); - } catch (IllegalAccessException e) { - throw new Error(e); - } catch (InvocationTargetException e) { - throw new Error(e); - } catch (NoSuchMethodException e) { + } catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { throw new Error(e); } diff --git a/core/src/main/java/hudson/cli/ClientAuthenticationCache.java b/core/src/main/java/hudson/cli/ClientAuthenticationCache.java index 1f33b83376..7c2127bc6d 100644 --- a/core/src/main/java/hudson/cli/ClientAuthenticationCache.java +++ b/core/src/main/java/hudson/cli/ClientAuthenticationCache.java @@ -72,9 +72,7 @@ public class ClientAuthenticationCache implements Serializable { try { UserDetails u = h.getSecurityRealm().loadUserByUsername(userName.getPlainText()); return new UsernamePasswordAuthenticationToken(u.getUsername(), "", u.getAuthorities()); - } catch (AuthenticationException e) { - return Jenkins.ANONYMOUS; - } catch (DataAccessException e) { + } catch (AuthenticationException | DataAccessException e) { return Jenkins.ANONYMOUS; } } diff --git a/core/src/main/java/hudson/cli/CommandDuringBuild.java b/core/src/main/java/hudson/cli/CommandDuringBuild.java index 59f5329faa..67e7d64717 100644 --- a/core/src/main/java/hudson/cli/CommandDuringBuild.java +++ b/core/src/main/java/hudson/cli/CommandDuringBuild.java @@ -77,9 +77,7 @@ public abstract class CommandDuringBuild extends CLICommand { } catch (NumberFormatException e) { throw new IllegalArgumentException("Invalid build number: "+envs[1]); } - } catch (IOException e) { - throw new IllegalArgumentException("Failed to identify the build being executed",e); - } catch (InterruptedException e) { + } catch (IOException | InterruptedException e) { throw new IllegalArgumentException("Failed to identify the build being executed",e); } } diff --git a/core/src/main/java/hudson/cli/DeleteBuildsCommand.java b/core/src/main/java/hudson/cli/DeleteBuildsCommand.java index 7a20cea783..cfe21e072e 100644 --- a/core/src/main/java/hudson/cli/DeleteBuildsCommand.java +++ b/core/src/main/java/hudson/cli/DeleteBuildsCommand.java @@ -29,6 +29,7 @@ import hudson.model.Run; import java.io.IOException; import java.io.PrintStream; +import java.util.HashSet; import java.util.List; /** @@ -54,10 +55,16 @@ public class DeleteBuildsCommand extends AbstractBuildRangeCommand { protected int act(List> builds) throws IOException { job.checkPermission(Run.DELETE); - for (AbstractBuild build : builds) - build.delete(); + final HashSet hsBuilds = new HashSet(); - stdout.println("Deleted "+builds.size()+" builds"); + for (AbstractBuild build : builds) { + if (!hsBuilds.contains(build.number)) { + build.delete(); + hsBuilds.add(build.number); + } + } + + stdout.println("Deleted "+hsBuilds.size()+" builds"); return 0; } diff --git a/core/src/main/java/hudson/cli/SetBuildDescriptionCommand.java b/core/src/main/java/hudson/cli/SetBuildDescriptionCommand.java index c7767a796e..1863e5a22e 100644 --- a/core/src/main/java/hudson/cli/SetBuildDescriptionCommand.java +++ b/core/src/main/java/hudson/cli/SetBuildDescriptionCommand.java @@ -28,6 +28,9 @@ public class SetBuildDescriptionCommand extends CLICommand implements Serializab protected int run() throws Exception { Run run = job.getBuildByNumber(number); + if (run == null) + throw new IllegalArgumentException("No such build #"+number); + run.checkPermission(Run.UPDATE); if ("=".equals(description)) { diff --git a/core/src/main/java/hudson/diagnosis/NullIdDescriptorMonitor.java b/core/src/main/java/hudson/diagnosis/NullIdDescriptorMonitor.java index 4b21af3f85..7465b200e3 100644 --- a/core/src/main/java/hudson/diagnosis/NullIdDescriptorMonitor.java +++ b/core/src/main/java/hudson/diagnosis/NullIdDescriptorMonitor.java @@ -61,7 +61,8 @@ public class NullIdDescriptorMonitor extends AdministrativeMonitor { return Collections.unmodifiableList(problems); } - private void verify() { + @Initializer(after=EXTENSIONS_AUGMENTED) + public void verify() { Jenkins h = Jenkins.getInstance(); for (Descriptor d : h.getExtensionList(Descriptor.class)) { PluginWrapper p = h.getPluginManager().whichPlugin(d.getClass()); @@ -82,10 +83,5 @@ public class NullIdDescriptorMonitor extends AdministrativeMonitor { } } - @Initializer(after=EXTENSIONS_AUGMENTED) - public static void verifyId() { - AdministrativeMonitor.all().get(NullIdDescriptorMonitor.class).verify(); - } - private static final Logger LOGGER = Logger.getLogger(NullIdDescriptorMonitor.class.getName()); } diff --git a/core/src/main/java/hudson/init/InitMilestone.java b/core/src/main/java/hudson/init/InitMilestone.java index 0f5c51dba5..3d5412e0bf 100644 --- a/core/src/main/java/hudson/init/InitMilestone.java +++ b/core/src/main/java/hudson/init/InitMilestone.java @@ -36,7 +36,16 @@ import org.jvnet.hudson.reactor.TaskGraphBuilder; * (in addition to defining their own milestones by implementing {@link Milestone}. * *

- * These milestones are achieve in this order. + * These milestones are achieve in this order: + *

    + *
  1. STARTED + *
  2. PLUGINS_LISTED + *
  3. PLUGINS_PREPARED + *
  4. PLUGINS_STARTED + *
  5. EXTENSIONS_AUGMENTED + *
  6. JOB_LOADED + *
  7. COMPLETED + *
* * @author Kohsuke Kawaguchi */ diff --git a/core/src/main/java/hudson/init/Initializer.java b/core/src/main/java/hudson/init/Initializer.java index d693314b7c..d41f45da52 100644 --- a/core/src/main/java/hudson/init/Initializer.java +++ b/core/src/main/java/hudson/init/Initializer.java @@ -23,6 +23,7 @@ */ package hudson.init; +import hudson.Extension; import org.jvnet.hudson.annotation_indexer.Indexed; import org.jvnet.hudson.reactor.Task; @@ -36,7 +37,7 @@ import static hudson.init.InitMilestone.STARTED; import static hudson.init.InitMilestone.COMPLETED; /** - * Placed on static methods to indicate that this method is to be run during the Jenkins start up to perform + * Placed on methods to indicate that this method is to be run during the Jenkins start up to perform * some sort of initialization tasks. * *

Example

@@ -46,6 +47,11 @@ import static hudson.init.InitMilestone.COMPLETED; .... } * + * + *

+ * 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 */ diff --git a/core/src/main/java/hudson/init/TaskMethodFinder.java b/core/src/main/java/hudson/init/TaskMethodFinder.java index 8fc677f651..0e09bfe267 100644 --- a/core/src/main/java/hudson/init/TaskMethodFinder.java +++ b/core/src/main/java/hudson/init/TaskMethodFinder.java @@ -56,9 +56,6 @@ abstract class TaskMethodFinder extends TaskBuilder { for (Method e : Index.list(type, cl, Method.class)) { if (filter(e)) continue; // already reported once - if (!Modifier.isStatic(e.getModifiers())) - throw new IOException(e+" is not a static method"); - T i = e.getAnnotation(type); if (i==null) continue; // stale index @@ -103,7 +100,10 @@ abstract class TaskMethodFinder extends TaskBuilder { Object[] args = new Object[pt.length]; for (int i=0; i extends TaskBuilder { } /** - * Static method that runs the initialization, that this task wraps. + * Method that runs the initialization, that this task wraps. */ public Method getMethod() { return e; diff --git a/core/src/main/java/hudson/init/Terminator.java b/core/src/main/java/hudson/init/Terminator.java index 7cea40031c..3e1155babd 100644 --- a/core/src/main/java/hudson/init/Terminator.java +++ b/core/src/main/java/hudson/init/Terminator.java @@ -11,6 +11,8 @@ import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** + * Like {@link Initializer} but used during the shut down. + * * @author Kohsuke Kawaguchi */ @Indexed diff --git a/core/src/main/java/hudson/init/impl/InstallUncaughtExceptionHandler.java b/core/src/main/java/hudson/init/impl/InstallUncaughtExceptionHandler.java index e39edb8f7c..7a37561571 100644 --- a/core/src/main/java/hudson/init/impl/InstallUncaughtExceptionHandler.java +++ b/core/src/main/java/hudson/init/impl/InstallUncaughtExceptionHandler.java @@ -11,6 +11,9 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + import org.kohsuke.stapler.Stapler; /** @@ -26,16 +29,40 @@ public class InstallUncaughtExceptionHandler { try { WebApp.get(j.servletContext).getSomeStapler() .invoke(req,rsp, Jenkins.getInstance(), "/oops"); - } catch (ServletException x) { - if (!Stapler.isSocketException(x)) { - throw x; - } - } catch (IOException x) { + } catch (ServletException | IOException x) { if (!Stapler.isSocketException(x)) { throw x; } } } }); + try { + Thread.setDefaultUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler()); + DefaultUncaughtExceptionHandler.LOGGER.log(Level.FINE, "Successfully installed a global UncaughtExceptionHandler."); + } + catch (SecurityException ex) { + DefaultUncaughtExceptionHandler.LOGGER.log(Level.SEVERE, + "Failed to set the default UncaughtExceptionHandler. " + + "If any threads die due to unhandled coding errors then there will be no logging of this information. " + + "The lack of this diagnostic information will make it harder to track down issues which will reduce the supportability of Jenkins. " + + "It is highly recomended that you consult the documentation that comes with you servlet container on how to allow the " + + "`setDefaultUncaughtExceptionHandler` permission and enable it.", ex); + } + } + + /** An UncaughtExceptionHandler that just logs the exception */ + private static class DefaultUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { + + private static final Logger LOGGER = Logger.getLogger(InstallUncaughtExceptionHandler.class.getName()); + + @Override + public void uncaughtException(Thread t, Throwable ex) { + // if this was an OutOfMemoryError then all bets about logging are off - but in the absence of anything else... + LOGGER.log(Level.SEVERE, + "A thread (" + t.getName() + '/' + t.getId() + + ") died unexpectedly due to an uncaught exception, this may leave your Jenkins in a bad way and is usually indicative of a bug in the code.", + ex); + } + } } diff --git a/core/src/main/java/hudson/model/Action.java b/core/src/main/java/hudson/model/Action.java index f73bd34032..2e8d2e641f 100644 --- a/core/src/main/java/hudson/model/Action.java +++ b/core/src/main/java/hudson/model/Action.java @@ -25,6 +25,8 @@ package hudson.model; import hudson.Functions; +import javax.annotation.CheckForNull; + /** * Object that contributes additional information, behaviors, and UIs to {@link ModelObject} * (more specifically {@link Actionable} objects, which most interesting {@link ModelObject}s are.) @@ -90,15 +92,17 @@ public interface Action extends ModelObject { * @see Functions#isAnonymous() * @see Functions#getIconFilePath(Action) */ - String getIconFileName(); + @CheckForNull String getIconFileName(); /** * Gets the string to be displayed. * * The convention is to capitalize the first letter of each word, - * such as "Test Result". + * such as "Test Result". + * + * @return Can be null in case the action is hidden. */ - String getDisplayName(); + @CheckForNull String getDisplayName(); /** * Gets the URL path name. @@ -124,5 +128,5 @@ public interface Action extends ModelObject { * (when you do that, be sure to also return null from {@link #getIconFileName()}. * @see Functions#getActionUrl(String, Action) */ - String getUrlName(); + @CheckForNull String getUrlName(); } diff --git a/core/src/main/java/hudson/model/CauseAction.java b/core/src/main/java/hudson/model/CauseAction.java index 09e5b03274..b065715db8 100644 --- a/core/src/main/java/hudson/model/CauseAction.java +++ b/core/src/main/java/hudson/model/CauseAction.java @@ -82,14 +82,21 @@ public class CauseAction implements FoldableAction, RunAction2 { public CauseAction(CauseAction ca) { addCauses(ca.getCauses()); } - + + /** + * Lists all causes of this build. + * Note that the current implementation does not preserve insertion order of duplicates. + * @return an immutable list; + * 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) public List getCauses() { List r = new ArrayList<>(); for (Map.Entry entry : causeBag.entrySet()) { r.addAll(Collections.nCopies(entry.getValue(), entry.getKey())); } - return r; + return Collections.unmodifiableList(r); } /** diff --git a/core/src/main/java/hudson/model/ComputerSet.java b/core/src/main/java/hudson/model/ComputerSet.java index c5992c828f..7b6510ef4b 100644 --- a/core/src/main/java/hudson/model/ComputerSet.java +++ b/core/src/main/java/hudson/model/ComputerSet.java @@ -452,10 +452,8 @@ public final class ComputerSet extends AbstractModelObject implements Describabl NodeMonitor nm = d.clazz.newInstance(); nm.setIgnored(ignored); return nm; - } catch (InstantiationException e) { - LOGGER.log(Level.SEVERE, "Failed to instanciate "+d.clazz,e); - } catch (IllegalAccessException e) { - LOGGER.log(Level.SEVERE, "Failed to instanciate "+d.clazz,e); + } catch (InstantiationException | IllegalAccessException e) { + LOGGER.log(Level.SEVERE, "Failed to instantiate "+d.clazz,e); } return null; } diff --git a/core/src/main/java/hudson/model/Descriptor.java b/core/src/main/java/hudson/model/Descriptor.java index 2160d27b17..8337195690 100644 --- a/core/src/main/java/hudson/model/Descriptor.java +++ b/core/src/main/java/hudson/model/Descriptor.java @@ -36,6 +36,8 @@ import hudson.util.FormValidation.CheckMethod; import hudson.util.ReflectionUtils; import hudson.util.ReflectionUtils.Parameter; import hudson.views.ListViewColumn; +import jenkins.model.GlobalConfiguration; +import jenkins.model.GlobalConfigurationCategory; import jenkins.model.Jenkins; import net.sf.json.JSONArray; import net.sf.json.JSONObject; @@ -592,12 +594,8 @@ public abstract class Descriptor> implements Saveable { } } catch (NoSuchMethodException e) { throw new AssertionError(e); // impossible - } catch (InstantiationException e) { + } catch (InstantiationException | IllegalAccessException | RuntimeException e) { throw new Error("Failed to instantiate "+clazz+" from "+formData,e); - } catch (IllegalAccessException e) { - throw new Error("Failed to instantiate "+clazz+" from "+formData,e); - } catch (RuntimeException e) { - throw new RuntimeException("Failed to instantiate "+clazz+" from "+formData,e); } } @@ -807,7 +805,18 @@ public abstract class Descriptor> implements Saveable { public String getGlobalConfigPage() { return getViewPage(clazz, getPossibleViewNames("global"), null); } - + + /** + * Define the global configuration category the global config of this Descriptor is in. + * + * @return never null, always the same value for a given instance of {@link Descriptor}. + * + * @since TODO, used to be in {@link GlobalConfiguration} before that. + */ + public GlobalConfigurationCategory getCategory() { + return GlobalConfigurationCategory.get(GlobalConfigurationCategory.Unclassified.class); + } + private String getViewPage(Class clazz, String pageName, String defaultValue) { return getViewPage(clazz,Collections.singleton(pageName),defaultValue); } diff --git a/core/src/main/java/hudson/model/DownloadService.java b/core/src/main/java/hudson/model/DownloadService.java index 0bbf7a8754..c89556a2ea 100644 --- a/core/src/main/java/hudson/model/DownloadService.java +++ b/core/src/main/java/hudson/model/DownloadService.java @@ -395,10 +395,12 @@ public class DownloadService extends PageDecorator { @Restricted(NoExternalUse.class) public FormValidation updateNow() throws IOException { List jsonList = new ArrayList<>(); + boolean toolInstallerMetadataExists = false; for (String site : getUrls()) { String jsonString; try { 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.WARNING, "Could not load json from " + site, e ); continue; @@ -407,13 +409,17 @@ public class DownloadService extends PageDecorator { if (signatureCheck) { FormValidation e = new JSONSignatureValidator("downloadable '"+id+"'").verifySignature(o); if (e.kind!= Kind.OK) { + LOGGER.log(Level.WARNING, "signature check failed for " + site, e ); continue; } } jsonList.add(o); } - if (jsonList.size() == 0) { - return FormValidation.warning("None of the Update Sites passed the signature check"); + if (jsonList.size() == 0 && toolInstallerMetadataExists) { + return FormValidation.warning("None of the tool installer metadata passed the signature check"); + } else if (!toolInstallerMetadataExists) { + LOGGER.log(Level.WARNING, "No tool installer metadata found for " + id); + return FormValidation.ok(); } JSONObject reducedJson = reduce(jsonList); return load(reducedJson.toString(), System.currentTimeMillis()); diff --git a/core/src/main/java/hudson/model/Executor.java b/core/src/main/java/hudson/model/Executor.java index 06e9453fd0..7ad0fac361 100644 --- a/core/src/main/java/hudson/model/Executor.java +++ b/core/src/main/java/hudson/model/Executor.java @@ -433,10 +433,7 @@ public class Executor extends Thread implements ModelObject { } catch (InterruptedException e) { LOGGER.log(FINE, getName()+" interrupted",e); // die peacefully - } catch(Exception e) { - causeOfDeath = e; - LOGGER.log(SEVERE, "Unexpected executor death", e); - } catch (Error e) { + } catch(Exception | Error e) { causeOfDeath = e; LOGGER.log(SEVERE, "Unexpected executor death", e); } finally { diff --git a/core/src/main/java/hudson/model/FileParameterDefinition.java b/core/src/main/java/hudson/model/FileParameterDefinition.java index 529bd0c4b4..c57d2bafc6 100644 --- a/core/src/main/java/hudson/model/FileParameterDefinition.java +++ b/core/src/main/java/hudson/model/FileParameterDefinition.java @@ -75,13 +75,10 @@ public class FileParameterDefinition extends ParameterDefinition { FileItem src; try { src = req.getFileItem( getName() ); - } catch (ServletException e) { + } 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; - } catch (IOException e) { - // ditto above - return null; } if ( src == null ) { // the requested file parameter wasn't uploaded diff --git a/core/src/main/java/hudson/model/Fingerprint.java b/core/src/main/java/hudson/model/Fingerprint.java index 9c4a6cf2a3..e76f330a91 100644 --- a/core/src/main/java/hudson/model/Fingerprint.java +++ b/core/src/main/java/hudson/model/Fingerprint.java @@ -1469,7 +1469,19 @@ public class Fingerprint implements ModelObject, Saveable { return res[0]; } - private static final XStream XSTREAM = new XStream2(); + private static final XStream2 XSTREAM = new XStream2(); + + /** + * Provides the XStream instance this class is using for serialization. + * + * @return the XStream instance + * @since FIXME + */ + @Nonnull + public static XStream2 getXStream() { + return XSTREAM; + } + static { XSTREAM.alias("fingerprint",Fingerprint.class); XSTREAM.alias("range",Range.class); diff --git a/core/src/main/java/hudson/model/FreeStyleProject.java b/core/src/main/java/hudson/model/FreeStyleProject.java index 7b184d65a7..ed7b325238 100644 --- a/core/src/main/java/hudson/model/FreeStyleProject.java +++ b/core/src/main/java/hudson/model/FreeStyleProject.java @@ -26,6 +26,7 @@ package hudson.model; import hudson.Extension; import jenkins.model.Jenkins; import org.jenkinsci.Symbol; +import jenkins.model.item_category.StandaloneProjectsCategory; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; @@ -80,5 +81,21 @@ public class FreeStyleProject extends Project i public FreeStyleProject newInstance(ItemGroup parent, String name) { return new FreeStyleProject(parent,name); } + + @Override + public String getDescription() { + return Messages.FreeStyleProject_Description(); + } + + @Override + public String getCategoryId() { + return StandaloneProjectsCategory.ID; + } + + @Override + public String getIconFilePathPattern() { + return (Jenkins.RESOURCE_PATH + "/images/:size/freestyleproject.png").replaceFirst("^/", ""); + } + } } diff --git a/core/src/main/java/hudson/model/ItemGroupMixIn.java b/core/src/main/java/hudson/model/ItemGroupMixIn.java index 15c1283743..1670a5ac8b 100644 --- a/core/src/main/java/hudson/model/ItemGroupMixIn.java +++ b/core/src/main/java/hudson/model/ItemGroupMixIn.java @@ -137,7 +137,7 @@ public abstract class ItemGroupMixIn { }; /** - * Creates a {@link TopLevelItem} from the submission of the '/lib/hudson/newFromList/formList' + * 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 { @@ -170,12 +170,7 @@ public abstract class ItemGroupMixIn { String from = req.getParameter("from"); // resolve a name to Item - Item src = null; - if (!from.startsWith("/")) - src = parent.getItem(from); - if (src==null) - src = Jenkins.getInstance().getItemByFullName(from); - + Item src = Jenkins.getInstance().getItem(from, parent); if(src==null) { if(Util.fixEmpty(from)==null) throw new Failure("Specify which job to copy"); diff --git a/core/src/main/java/hudson/model/ManageJenkinsAction.java b/core/src/main/java/hudson/model/ManageJenkinsAction.java index 29c2b805e5..cd1b6cb8fc 100644 --- a/core/src/main/java/hudson/model/ManageJenkinsAction.java +++ b/core/src/main/java/hudson/model/ManageJenkinsAction.java @@ -36,7 +36,7 @@ import org.jenkinsci.Symbol; public class ManageJenkinsAction implements RootAction { public String getIconFileName() { if (Jenkins.getInstance().hasPermission(Jenkins.ADMINISTER)) - return "setting.png"; + return "gear2.png"; else return null; } diff --git a/core/src/main/java/hudson/model/ManagementLink.java b/core/src/main/java/hudson/model/ManagementLink.java index dca459ca70..041fda35d0 100644 --- a/core/src/main/java/hudson/model/ManagementLink.java +++ b/core/src/main/java/hudson/model/ManagementLink.java @@ -33,6 +33,9 @@ import jenkins.model.Jenkins; import java.util.List; import org.kohsuke.stapler.interceptor.RequirePOST; +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; + /** * Extension point to add icon to http://server/hudson/manage page. * @@ -59,7 +62,7 @@ public abstract class ManagementLink implements ExtensionPoint, Action { * This is useful for defining {@link ManagementLink} that only shows up under * certain circumstances. */ - public abstract String getIconFileName(); + public abstract @CheckForNull String getIconFileName(); /** * Returns a short description of what this link does. This text @@ -80,7 +83,7 @@ public abstract class ManagementLink implements ExtensionPoint, Action { * so relative paths are interpreted against the root {@link Jenkins} object. */ @Override - public abstract String getUrlName(); + public abstract @CheckForNull String getUrlName(); /** * Allows implementations to request that this link show a confirmation dialog, and use POST if confirmed. @@ -102,16 +105,16 @@ public abstract class ManagementLink implements ExtensionPoint, Action { public static final List LIST = ExtensionListView.createList(ManagementLink.class); /** - * All regsitered instances. + * All registered instances. */ - public static ExtensionList all() { + public static @Nonnull ExtensionList all() { return ExtensionList.lookup(ManagementLink.class); } /** * @return permission required for user to access this management link, in addition to {@link Jenkins#ADMINISTER} */ - public Permission getRequiredPermission() { + public @CheckForNull Permission getRequiredPermission() { return null; } diff --git a/core/src/main/java/hudson/model/TextParameterValue.java b/core/src/main/java/hudson/model/TextParameterValue.java index 6e5a50e161..1e2227e303 100644 --- a/core/src/main/java/hudson/model/TextParameterValue.java +++ b/core/src/main/java/hudson/model/TextParameterValue.java @@ -26,7 +26,7 @@ package hudson.model; import org.kohsuke.stapler.DataBoundConstructor; /** - * @author Rafa de la Torre + * @author Rafa de la Torre */ public class TextParameterValue extends StringParameterValue { diff --git a/core/src/main/java/hudson/model/TopLevelItemDescriptor.java b/core/src/main/java/hudson/model/TopLevelItemDescriptor.java index 272c609c2b..aa6a2835b1 100644 --- a/core/src/main/java/hudson/model/TopLevelItemDescriptor.java +++ b/core/src/main/java/hudson/model/TopLevelItemDescriptor.java @@ -25,8 +25,23 @@ package hudson.model; import hudson.ExtensionList; import jenkins.model.Jenkins; +import jenkins.model.item_category.ItemCategory; import org.acegisecurity.AccessDeniedException; +import org.apache.commons.jelly.Script; +import org.apache.commons.jelly.XMLOutput; +import org.apache.commons.lang.StringUtils; +import org.kohsuke.stapler.MetaClass; +import org.kohsuke.stapler.Stapler; import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.WebApp; +import org.kohsuke.stapler.jelly.DefaultScriptInvoker; +import org.kohsuke.stapler.jelly.JellyClassTearOff; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import java.io.StringWriter; +import java.util.logging.Level; +import java.util.logging.Logger; /** * {@link Descriptor} for {@link TopLevelItem}s. @@ -34,6 +49,9 @@ import org.kohsuke.stapler.StaplerRequest; * @author Kohsuke Kawaguchi */ public abstract class TopLevelItemDescriptor extends Descriptor { + + private static final Logger LOGGER = Logger.getLogger(TopLevelItemDescriptor.class.getName()); + protected TopLevelItemDescriptor(Class clazz) { super(clazz); } @@ -113,6 +131,87 @@ public abstract class TopLevelItemDescriptor extends Descriptor { return super.getDisplayName(); } + /** + * A description of this kind of item type. This description can contain HTML code but it is recommend to use text plain + * in order to avoid how it should be represented. + * + * This method should be called in a thread where Stapler is associated, but it will return an empty string. + * + * @return A string, by default the value from newInstanceDetail view is taken. + * + * @since TODO + */ + @Nonnull + public String getDescription() { + Stapler stapler = Stapler.getCurrent(); + if (stapler != null) { + try { + WebApp webapp = WebApp.getCurrent(); + MetaClass meta = webapp.getMetaClass(this); + Script s = meta.loadTearOff(JellyClassTearOff.class).findScript("newInstanceDetail"); + if (s == null) { + return ""; + } + DefaultScriptInvoker dsi = new DefaultScriptInvoker(); + StringWriter sw = new StringWriter(); + XMLOutput xml = dsi.createXMLOutput(sw, true); + dsi.invokeScript(Stapler.getCurrentRequest(), Stapler.getCurrentResponse(), s, this, xml); + return sw.toString(); + } catch (Exception e) { + LOGGER.log(Level.WARNING, null, e); + return ""; + } + } else { + return ""; + } + } + + /** + * Used to categorize this kind of item type. @see {@link ItemCategory} + * + * @return A string with the category identifier, {@link ItemCategory.UncategorizedCategory#getId()} by default. + * + * @since TODO + */ + @Nonnull + public String getCategoryId() { + return ItemCategory.UncategorizedCategory.ID; + } + + /** + * Represents a file path pattern to get the Item icon in different sizes. + * + * For example: plugin/plugin-shortname/images/:size/item.png, where {@code :size} represents the different + * icon sizes used commonly in Jenkins project: 16x16, 24x24, 32x32 or 48x48 + * + * @see {@link FreeStyleProject.DescriptorImpl#getIconFilePathPattern()} + * + * @return A string or null if it is not defined. + * + * @since TODO + */ + @CheckForNull + public String getIconFilePathPattern() { + return null; + } + + /** + * An icon file path associated to a specific size. + * + * @param size A string with values that represent the common sizes: 16x16, 24x24, 32x32 or 48x48 + * + * @return A string or null if it is not defined. + * + * @since TODO + */ + @CheckForNull + public String getIconFilePath(String size) { + if (!StringUtils.isBlank(getIconFilePathPattern())) { + return getIconFilePathPattern().replace(":size", size); + } + return null; + } + /** * @deprecated since 2007-01-19. * This is not a valid operation for {@link Item}s. diff --git a/core/src/main/java/hudson/model/UpdateCenter.java b/core/src/main/java/hudson/model/UpdateCenter.java index 5eae9d16d4..e5e157dde7 100644 --- a/core/src/main/java/hudson/model/UpdateCenter.java +++ b/core/src/main/java/hudson/model/UpdateCenter.java @@ -53,7 +53,6 @@ import hudson.util.IOUtils; import hudson.util.PersistedList; import hudson.util.XStream2; import jenkins.RestartRequiredException; -import jenkins.install.InstallState; import jenkins.install.InstallUtil; import jenkins.model.Jenkins; import jenkins.util.io.OnMaster; @@ -78,6 +77,8 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.net.HttpRetryException; +import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; @@ -135,6 +136,11 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas private static final String UPDATE_CENTER_URL = System.getProperty(UpdateCenter.class.getName()+".updateCenterUrl","http://updates.jenkins-ci.org/"); + /** + * Read timeout when downloading plugins, defaults to 1 minute + */ + private static final int PLUGIN_DOWNLOAD_READ_TIMEOUT = Integer.getInteger(UpdateCenter.class.getName()+".pluginDownloadReadTimeoutSeconds", 60) * 1000; + /** * {@linkplain UpdateSite#getId() ID} of the default update site. * @since 1.483 @@ -290,6 +296,7 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas */ @Restricted(DoNotUse.class) public HttpResponse doConnectionStatus(StaplerRequest request) { + Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); try { String siteId = request.getParameter("siteId"); if (siteId == null) { @@ -338,6 +345,7 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas */ @Restricted(DoNotUse.class) // WebOnly public HttpResponse doIncompleteInstallStatus() { + Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); try { Map jobs = InstallUtil.getPersistedInstallStatus(); if(jobs == null) { @@ -354,6 +362,7 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas * us to support install resume if Jenkins is restarted while plugins are * being installed. */ + @Restricted(NoExternalUse.class) public synchronized void persistInstallStatus() { List jobs = getJobs(); @@ -386,6 +395,7 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas */ @Restricted(DoNotUse.class) public HttpResponse doInstallStatus(StaplerRequest request) { + Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); try { String correlationId = request.getParameter("correlationId"); Map response = new HashMap<>(); @@ -1000,6 +1010,11 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas URLConnection con = null; try { con = connect(job,src); + //JENKINS-34174 - set timeout for downloads, may hang indefinitely + // particularly noticeable during 2.0 install when downloading + // many plugins + con.setReadTimeout(PLUGIN_DOWNLOAD_READ_TIMEOUT); + int total = con.getContentLength(); in = new CountingInputStream(con.getInputStream()); byte[] buf = new byte[8192]; @@ -1133,7 +1148,16 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas private void testConnection(URL url) throws IOException { try { - Util.copyStreamAndClose(ProxyConfiguration.open(url).getInputStream(),new NullOutputStream()); + URLConnection connection = (URLConnection) ProxyConfiguration.open(url); + + 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 { + Util.copyStreamAndClose(connection.getInputStream(),new NullOutputStream()); + } } catch (SSLHandshakeException e) { if (e.getMessage().contains("PKIX path building failed")) // fix up this crappy error message from JDK @@ -1316,22 +1340,29 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas return; } LOGGER.fine("Doing a connectivity check"); + Future internetCheck = null; try { - String connectionCheckUrl = site.getConnectionCheckUrl(); + final String connectionCheckUrl = site.getConnectionCheckUrl(); if (connectionCheckUrl!=null) { connectionStates.put(ConnectionStatus.INTERNET, ConnectionStatus.CHECKING); statuses.add(Messages.UpdateCenter_Status_CheckingInternet()); - try { - config.checkConnection(this, connectionCheckUrl); - } catch (Exception e) { - 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(connectionCheckUrl)); - return; + // Run the internet check in parallel + internetCheck = updateService.submit(new Runnable() { + @Override + public void run() { + try { + config.checkConnection(ConnectionCheckJob.this, connectionCheckUrl); + } catch (Exception e) { + 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(connectionCheckUrl)); + return; + } + } + connectionStates.put(ConnectionStatus.INTERNET, ConnectionStatus.OK); } - } - connectionStates.put(ConnectionStatus.INTERNET, ConnectionStatus.OK); + }); } connectionStates.put(ConnectionStatus.UPDATE_SITE, ConnectionStatus.CHECKING); @@ -1351,6 +1382,15 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas statuses.add(Functions.printThrowable(e)); error = e; } + + if(internetCheck != null) { + try { + // Wait for internet check to complete + internetCheck.get(); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Error completing internet connectivity check: " + e.getMessage(), e); + } + } } private void addStatus(UnknownHostException e) { @@ -1887,18 +1927,14 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas @Initializer(after=PLUGINS_STARTED, fatal=false) public static void init(Jenkins h) throws IOException { h.getUpdateCenter().load(); - if (Jenkins.getActiveInstance().getInstallState() == InstallState.NEW) { - LOGGER.log(INFO, "This is a new Jenkins instance. The Plugin Install Wizard will be launched."); - // Force update of the default site file (updates/default.json). - updateDefaultSite(); - } } - private static void updateDefaultSite() { + @Restricted(NoExternalUse.class) + public static void updateDefaultSite() { try { // Need to do the following because the plugin manager will attempt to access // $JENKINS_HOME/updates/default.json. Needs to be up to date. - Jenkins.getActiveInstance().getUpdateCenter().getSite(UpdateCenter.ID_DEFAULT).updateDirectlyNow(true); + Jenkins.getInstance().getUpdateCenter().getSite(UpdateCenter.ID_DEFAULT).updateDirectlyNow(true); } catch (Exception e) { LOGGER.log(WARNING, "Upgrading Jenkins. Failed to update default UpdateSite. Plugin upgrades may fail.", e); } diff --git a/core/src/main/java/hudson/model/UpdateSite.java b/core/src/main/java/hudson/model/UpdateSite.java index b6acc6202b..c8c8ff7c20 100644 --- a/core/src/main/java/hudson/model/UpdateSite.java +++ b/core/src/main/java/hudson/model/UpdateSite.java @@ -840,6 +840,7 @@ public class UpdateSite { * See {@link UpdateCenter#isRestartRequiredForCompletion()} * @param correlationId A correlation ID to be set on the job. */ + @Restricted(NoExternalUse.class) public Future deploy(boolean dynamicLoad, @CheckForNull UUID correlationId) { Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); UpdateCenter uc = Jenkins.getInstance().getUpdateCenter(); diff --git a/core/src/main/java/hudson/model/User.java b/core/src/main/java/hudson/model/User.java index 0ff29ea78d..e76608812e 100644 --- a/core/src/main/java/hudson/model/User.java +++ b/core/src/main/java/hudson/model/User.java @@ -74,6 +74,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -904,11 +905,11 @@ public class User extends AbstractModelObject implements AccessControlled, Descr public Object getDynamic(String token) { for(Action action: getTransientActions()){ - if(action.getUrlName().equals(token)) + if(Objects.equals(action.getUrlName(), token)) return action; } for(Action action: getPropertyActions()){ - if(action.getUrlName().equals(token)) + if(Objects.equals(action.getUrlName(), token)) return action; } return null; diff --git a/core/src/main/java/hudson/model/View.java b/core/src/main/java/hudson/model/View.java index 0cfa562922..abb96724db 100644 --- a/core/src/main/java/hudson/model/View.java +++ b/core/src/main/java/hudson/model/View.java @@ -35,6 +35,7 @@ import hudson.Indenter; import hudson.Util; import hudson.model.Descriptor.FormException; import hudson.model.labels.LabelAtomPropertyDescriptor; +import hudson.model.listeners.ItemListener; import hudson.scm.ChangeLogSet; import hudson.scm.ChangeLogSet.Entry; import hudson.search.CollectionSearchIndex; @@ -50,12 +51,16 @@ import hudson.util.AlternativeUiTextProvider.Message; import hudson.util.DescribableList; import hudson.util.DescriptorList; import hudson.util.FormApply; +import hudson.util.FormValidation; import hudson.util.RunList; import hudson.util.XStream2; import hudson.views.ListViewColumn; import hudson.widgets.Widget; import jenkins.model.Jenkins; import jenkins.model.ModelObjectWithChildren; +import jenkins.model.item_category.Categories; +import jenkins.model.item_category.Category; +import jenkins.model.item_category.ItemCategory; import jenkins.util.ProgressiveRendering; import jenkins.util.xml.XMLUtils; @@ -63,6 +68,7 @@ import net.sf.json.JSON; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.apache.tools.ant.filters.StringInputStream; +import org.kohsuke.accmod.restrictions.DoNotUse; import org.kohsuke.stapler.HttpResponse; import org.kohsuke.stapler.HttpResponses; import org.kohsuke.stapler.Stapler; @@ -84,6 +90,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.Serializable; import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; @@ -105,6 +112,7 @@ import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; import static jenkins.model.Jenkins.*; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; +import org.kohsuke.stapler.QueryParameter; import org.xml.sax.SAXException; /** @@ -544,7 +552,7 @@ public abstract class View extends AbstractModelObject implements AccessControll for (Action a : getActions()) { String url = a.getUrlName(); if (url==null) continue; - if(a.getUrlName().equals(token)) + if (url.equals(token)) return a; } return null; @@ -917,7 +925,7 @@ public abstract class View extends AbstractModelObject implements AccessControll SearchIndexBuilder sib = super.makeSearchIndex(); sib.add(new CollectionSearchIndex() {// for jobs in the view protected TopLevelItem get(String key) { return getItem(key); } - protected Collection all() { return getItems(); } + protected Collection all() { return getItems(); } @Override protected String getName(TopLevelItem o) { // return the name instead of the display for suggestion searching @@ -1000,6 +1008,70 @@ public abstract class View extends AbstractModelObject implements AccessControll */ public abstract Item doCreateItem( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException; + /** + * Makes sure that the given name is good as a job name. + * For use from {@code newJob}. + */ + @Restricted(DoNotUse.class) // called from newJob view + public FormValidation doCheckJobName(@QueryParameter String value) { + // this method can be used to check if a file exists anywhere in the file system, + // so it should be protected. + getOwner().checkPermission(Item.CREATE); + + if (Util.fixEmpty(value) == null) { + return FormValidation.ok(); + } + + try { + Jenkins.checkGoodName(value); + value = value.trim(); // why trim *after* checkGoodName? not sure, but ItemGroupMixIn.createTopLevelItem does the same + Jenkins.getInstance().getProjectNamingStrategy().checkName(value); + } catch (Failure e) { + return FormValidation.error(e.getMessage()); + } + + if (getOwnerItemGroup().getItem(value) != null) { + return FormValidation.error(Messages.Hudson_JobAlreadyExists(value)); + } + + // looks good + return FormValidation.ok(); + } + + /** + * An API REST method to get the allowed {$link TopLevelItem}s and its categories. + * + * @return A {@link Categories} entity that is shown as JSON file. + */ + @Restricted(DoNotUse.class) + public Categories doItemCategories(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { + getOwner().checkPermission(Item.CREATE); + Categories categories = new Categories(); + int order = 0; + for (TopLevelItemDescriptor descriptor : DescriptorVisibilityFilter.apply(getOwnerItemGroup(), Items.all(Jenkins.getAuthentication(), getOwnerItemGroup()))) { + ItemCategory ic = ItemCategory.getCategory(descriptor); + Map metadata = new HashMap(); + + // Information about Item. + metadata.put("class", descriptor.getId()); + metadata.put("order", ++order); + metadata.put("displayName", descriptor.getDisplayName()); + metadata.put("description", descriptor.getDescription()); + metadata.put("iconFilePathPattern", descriptor.getIconFilePathPattern()); + + Category category = categories.getItem(ic.getId()); + if (category != null) { + category.getItems().add(metadata); + } else { + List> temp = new ArrayList>(); + temp.add(metadata); + category = new Category(ic.getId(), ic.getDisplayName(), ic.getDescription(), ic.getOrder(), ic.getMinToShow(), temp); + categories.getItems().add(category); + } + } + return categories; + } + public void doRssAll( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { rss(req, rsp, " all builds", getBuilds()); } diff --git a/core/src/main/java/hudson/model/ViewDescriptor.java b/core/src/main/java/hudson/model/ViewDescriptor.java index 2f304fa90f..dde3c0b9ed 100644 --- a/core/src/main/java/hudson/model/ViewDescriptor.java +++ b/core/src/main/java/hudson/model/ViewDescriptor.java @@ -26,12 +26,14 @@ package hudson.model; import hudson.views.ListViewColumn; import hudson.views.ListViewColumnDescriptor; import hudson.views.ViewJobFilter; +import java.util.Iterator; +import java.util.List; +import jenkins.model.DirectlyModifiableTopLevelItemGroup; +import jenkins.model.Jenkins; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.DoNotUse; -import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.AncestorInPath; - -import java.util.List; +import org.kohsuke.stapler.QueryParameter; /** * {@link Descriptor} for {@link View}. @@ -76,8 +78,23 @@ public abstract class ViewDescriptor extends Descriptor { * Auto-completion for the "copy from" field in the new job page. */ @Restricted(DoNotUse.class) - public AutoCompletionCandidates doAutoCompleteCopyNewItemFrom(@QueryParameter final String value, @AncestorInPath ItemGroup container) { - return AutoCompletionCandidates.ofJobNames(TopLevelItem.class, value, container); + public AutoCompletionCandidates doAutoCompleteCopyNewItemFrom(@QueryParameter final String value, @AncestorInPath ItemGroup container) { + // TODO do we need a permissions check here? + AutoCompletionCandidates candidates = AutoCompletionCandidates.ofJobNames(TopLevelItem.class, value, container); + if (container instanceof DirectlyModifiableTopLevelItemGroup) { + DirectlyModifiableTopLevelItemGroup modifiableContainer = (DirectlyModifiableTopLevelItemGroup) container; + Iterator it = candidates.getValues().iterator(); + while (it.hasNext()) { + TopLevelItem item = Jenkins.getInstance().getItem(it.next(), container, TopLevelItem.class); + if (item == null) { + continue; // ? + } + if (!modifiableContainer.canAdd(item)) { + it.remove(); + } + } + } + return candidates; } /** diff --git a/core/src/main/java/hudson/os/solaris/ZFSInstaller.java b/core/src/main/java/hudson/os/solaris/ZFSInstaller.java index 94ff9638d8..3468fa1834 100644 --- a/core/src/main/java/hudson/os/solaris/ZFSInstaller.java +++ b/core/src/main/java/hudson/os/solaris/ZFSInstaller.java @@ -271,9 +271,7 @@ public class ZFSInstaller extends AdministrativeMonitor implements Serializable JavaVMArguments args = JavaVMArguments.current(); args.setSystemProperty(ZFSInstaller.class.getName()+".migrate",datasetName); Daemon.selfExec(args); - } catch (InterruptedException e) { - LOGGER.log(Level.SEVERE, "Restart failed",e); - } catch (IOException e) { + } catch (InterruptedException | IOException e) { LOGGER.log(Level.SEVERE, "Restart failed",e); } } diff --git a/core/src/main/java/hudson/search/SearchResult.java b/core/src/main/java/hudson/search/SearchResult.java index 927fced648..2d6cdb1d65 100644 --- a/core/src/main/java/hudson/search/SearchResult.java +++ b/core/src/main/java/hudson/search/SearchResult.java @@ -3,7 +3,7 @@ package hudson.search; import java.util.List; /** - * @author Nicolas De Loof + * @author Nicolas De Loof */ public interface SearchResult extends List { diff --git a/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java b/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java index 9288ba018f..8149145824 100644 --- a/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java +++ b/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java @@ -29,8 +29,6 @@ import hudson.ExtensionList; import hudson.Util; import hudson.diagnosis.OldDataMonitor; import hudson.model.Descriptor; -import jenkins.install.InstallState; -import jenkins.install.SetupWizard; import jenkins.model.Jenkins; import hudson.model.ManagementLink; import hudson.model.ModelObject; @@ -262,16 +260,26 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea } /** - * Creates an user account. Used by admins. + * Creates a user account. Used by admins. * * This version behaves differently from {@link #doCreateAccount(StaplerRequest, StaplerResponse)} in that * this is someone creating another user. */ public void doCreateAccountByAdmin(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { + createAccountByAdmin(req, rsp, "addUser.jelly", "."); // send the user back to the listing page on success + } + + /** + * Creates a user account. Requires {@link Jenkins#ADMINISTER} + */ + @Restricted(NoExternalUse.class) + public User createAccountByAdmin(StaplerRequest req, StaplerResponse rsp, String addUserView, String successView) throws IOException, ServletException { checkPermission(Jenkins.ADMINISTER); - if(createAccount(req, rsp, false, "addUser.jelly")!=null) { - rsp.sendRedirect("."); // send the user back to the listing page + User u = createAccount(req, rsp, false, addUserView); + if(u != null) { + rsp.sendRedirect(successView); } + return u; } /** @@ -281,36 +289,14 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea * This can be run by anyone, but only to create the very first user account. */ public void doCreateFirstAccount(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { - boolean inSetup = !Jenkins.getInstance().getInstallState().isSetupComplete(); - if(!inSetup && hasSomeUser()) { + if(hasSomeUser()) { rsp.sendError(SC_UNAUTHORIZED,"First user was already created"); return; } - - User admin = null; - try { - String view = "firstUser.jelly"; - if(inSetup) { - admin = getUser(SetupWizard.initialSetupAdminUserName); - if(admin != null) { - admin.delete(); // assume the new user may well be 'admin' - } - view = "setupWizardFirstUser.jelly"; - } - - User u = createAccount(req, rsp, false, view); - if (u!=null) { - tryToMakeAdmin(u); - if(admin != null) { - admin = null; - } - Jenkins.getInstance().setInstallState(InstallState.CREATE_ADMIN_USER.getNextState()); - loginAndTakeBack(req, rsp, u); - } - } finally { - if(admin != null) { - admin.save(); // recreate this initial user if something failed - } + User u = createAccount(req, rsp, false, "firstUser.jelly"); + if (u!=null) { + tryToMakeAdmin(u); + loginAndTakeBack(req, rsp, u); } } diff --git a/core/src/main/java/hudson/security/csrf/CrumbFilter.java b/core/src/main/java/hudson/security/csrf/CrumbFilter.java index 9080a54692..557e96f766 100644 --- a/core/src/main/java/hudson/security/csrf/CrumbFilter.java +++ b/core/src/main/java/hudson/security/csrf/CrumbFilter.java @@ -62,17 +62,11 @@ public class CrumbFilter implements Filter { String crumbFieldName = crumbIssuer.getDescriptor().getCrumbRequestField(); String crumbSalt = crumbIssuer.getDescriptor().getCrumbSalt(); - String crumb = httpRequest.getHeader(crumbFieldName); boolean valid = false; + String crumb = extractCrumbFromRequest(httpRequest, crumbFieldName); if (crumb == null) { - Enumeration paramNames = request.getParameterNames(); - while (paramNames.hasMoreElements()) { - String paramName = (String) paramNames.nextElement(); - if (crumbFieldName.equals(paramName)) { - crumb = request.getParameter(paramName); - break; - } - } + // compatibility for clients that hard-code the default crumb name up to Jenkins 1.TODO + extractCrumbFromRequest(httpRequest, ".crumb"); } if (crumb != null) { if (crumbIssuer.validateCrumb(httpRequest, crumbSalt, crumb)) { @@ -93,6 +87,21 @@ public class CrumbFilter implements Filter { } } + private String extractCrumbFromRequest(HttpServletRequest httpRequest, String crumbFieldName) { + String crumb = httpRequest.getHeader(crumbFieldName); + if (crumb == null) { + Enumeration paramNames = httpRequest.getParameterNames(); + while (paramNames.hasMoreElements()) { + String paramName = (String) paramNames.nextElement(); + if (crumbFieldName.equals(paramName)) { + crumb = httpRequest.getParameter(paramName); + break; + } + } + } + return crumb; + } + protected static boolean isMultipart(HttpServletRequest request) { if (request == null) { return false; diff --git a/core/src/main/java/hudson/security/csrf/CrumbIssuer.java b/core/src/main/java/hudson/security/csrf/CrumbIssuer.java index 6daacd364d..3d80b1a5b6 100644 --- a/core/src/main/java/hudson/security/csrf/CrumbIssuer.java +++ b/core/src/main/java/hudson/security/csrf/CrumbIssuer.java @@ -44,6 +44,9 @@ public abstract class CrumbIssuer implements Describable, Extension private static final String CRUMB_ATTRIBUTE = CrumbIssuer.class.getName() + "_crumb"; + @Restricted(NoExternalUse.class) + public static final String DEFAULT_CRUMB_NAME = "Jenkins-Crumb"; + /** * Get the name of the request parameter the crumb will be stored in. Exposed * here for the remote API. @@ -199,7 +202,7 @@ public abstract class CrumbIssuer implements Describable, Extension } else if ("concat(//crumbRequestField,\":\",//crumb)".equals(xpath)) { // new FullDuplexHttpStream; Main text = ci.getCrumbRequestField() + ':' + ci.getCrumb(); } else if ("concat(//crumbRequestField,'=',//crumb)".equals(xpath)) { // NetBeans - if (ci.getCrumbRequestField().startsWith(".")) { + if (ci.getCrumbRequestField().startsWith(".") || ci.getCrumbRequestField().contains("-")) { text = ci.getCrumbRequestField() + '=' + ci.getCrumb(); } else { text = null; diff --git a/core/src/main/java/hudson/security/csrf/CrumbIssuerDescriptor.java b/core/src/main/java/hudson/security/csrf/CrumbIssuerDescriptor.java index 013405b66a..84d9fb5c16 100644 --- a/core/src/main/java/hudson/security/csrf/CrumbIssuerDescriptor.java +++ b/core/src/main/java/hudson/security/csrf/CrumbIssuerDescriptor.java @@ -64,7 +64,7 @@ public abstract class CrumbIssuerDescriptor extends Descr */ public void setCrumbRequestField(String requestField) { if (Util.fixEmptyAndTrim(requestField) == null) { - crumbRequestField = ".crumb"; + crumbRequestField = CrumbIssuer.DEFAULT_CRUMB_NAME; } else { crumbRequestField = requestField; } diff --git a/core/src/main/java/hudson/security/csrf/DefaultCrumbIssuer.java b/core/src/main/java/hudson/security/csrf/DefaultCrumbIssuer.java index d4a53b02a2..32d10dee68 100644 --- a/core/src/main/java/hudson/security/csrf/DefaultCrumbIssuer.java +++ b/core/src/main/java/hudson/security/csrf/DefaultCrumbIssuer.java @@ -125,7 +125,7 @@ public class DefaultCrumbIssuer extends CrumbIssuer { private final static HexStringConfidentialKey CRUMB_SALT = new HexStringConfidentialKey(Jenkins.class,"crumbSalt",16); public DescriptorImpl() { - super(CRUMB_SALT.get(), System.getProperty("hudson.security.csrf.requestfield", ".crumb")); + super(CRUMB_SALT.get(), System.getProperty("hudson.security.csrf.requestfield", CrumbIssuer.DEFAULT_CRUMB_NAME)); load(); } diff --git a/core/src/main/java/hudson/slaves/NodeProvisioner.java b/core/src/main/java/hudson/slaves/NodeProvisioner.java index 87da4f5742..86e810688d 100644 --- a/core/src/main/java/hudson/slaves/NodeProvisioner.java +++ b/core/src/main/java/hudson/slaves/NodeProvisioner.java @@ -556,10 +556,9 @@ public class NodeProvisioner { if (node != null) { additionalPlannedCapacity += node.getNumExecutors(); } - } catch (InterruptedException e) { - // should never happen as we were told the future was done - } catch (ExecutionException e) { - // ignore, this will be caught by others later + } catch (InterruptedException | ExecutionException e) { + // InterruptedException: should never happen as we were told the future was done + // ExecutionException: ignore, this will be caught by others later } } else { additionalPlannedCapacity += f.numExecutors; diff --git a/core/src/main/java/hudson/slaves/SimpleScheduledRetentionStrategy.java b/core/src/main/java/hudson/slaves/SimpleScheduledRetentionStrategy.java index 073f67937c..df9ff8ce07 100644 --- a/core/src/main/java/hudson/slaves/SimpleScheduledRetentionStrategy.java +++ b/core/src/main/java/hudson/slaves/SimpleScheduledRetentionStrategy.java @@ -187,8 +187,7 @@ public class SimpleScheduledRetentionStrategy extends RetentionStrategy jsonList) { - if (isDefualtSchema(jsonList)) { + if (isDefaultSchema(jsonList)) { return delegate.reduce(jsonList); } else { //if it's not default schema fall back to the super class implementation @@ -153,7 +153,7 @@ public abstract class DownloadFromUrlInstaller extends ToolInstaller { * @param jsonList the list of Update centers json files * @return true if the schema is the default one (id, name, url), false otherwise */ - private boolean isDefualtSchema(List jsonList) { + private boolean isDefaultSchema(List jsonList) { JSONObject jsonToolInstallerList = jsonList.get(0); ToolInstallerList toolInstallerList = (ToolInstallerList) JSONObject.toBean(jsonToolInstallerList, ToolInstallerList.class); diff --git a/core/src/main/java/hudson/tools/ToolDescriptor.java b/core/src/main/java/hudson/tools/ToolDescriptor.java index 567c298a0d..641400f454 100644 --- a/core/src/main/java/hudson/tools/ToolDescriptor.java +++ b/core/src/main/java/hudson/tools/ToolDescriptor.java @@ -34,7 +34,10 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Collections; import java.util.List; + +import jenkins.model.GlobalConfigurationCategory; import jenkins.model.Jenkins; +import jenkins.tools.ToolConfigurationCategory; import net.sf.json.JSONObject; import org.jvnet.tiger_types.Types; import org.kohsuke.stapler.QueryParameter; @@ -89,6 +92,12 @@ public abstract class ToolDescriptor extends Descrip return PropertyDescriptor.for_(ToolProperty.all(),clazz); } + + @Override + public GlobalConfigurationCategory getCategory() { + return GlobalConfigurationCategory.get(ToolConfigurationCategory.class); + } + /** * Optional list of installers to be configured by default for new tools of this type. * If there are popular versions of the tool available using generic installation techniques, diff --git a/core/src/main/java/hudson/util/HttpResponses.java b/core/src/main/java/hudson/util/HttpResponses.java index 1fb7cf6084..511a3f20e0 100644 --- a/core/src/main/java/hudson/util/HttpResponses.java +++ b/core/src/main/java/hudson/util/HttpResponses.java @@ -51,6 +51,8 @@ public class HttpResponses extends org.kohsuke.stapler.HttpResponses { /** * Create an empty "ok" response. + * + * @since 2.0 */ public static HttpResponse okJSON() { return new JSONObjectResponse(); @@ -59,6 +61,8 @@ public class HttpResponses extends org.kohsuke.stapler.HttpResponses { /** * Create a response containing the supplied "data". * @param data The data. + * + * @since 2.0 */ public static HttpResponse okJSON(@Nonnull JSONObject data) { return new JSONObjectResponse(data); @@ -67,6 +71,8 @@ public class HttpResponses extends org.kohsuke.stapler.HttpResponses { /** * Create a response containing the supplied "data". * @param data The data. + * + * @since 2.0 */ public static HttpResponse okJSON(@Nonnull JSONArray data) { return new JSONObjectResponse(data); @@ -75,6 +81,8 @@ public class HttpResponses extends org.kohsuke.stapler.HttpResponses { /** * Create a response containing the supplied "data". * @param data The data. + * + * @since 2.0 */ public static HttpResponse okJSON(@Nonnull Map data) { return new JSONObjectResponse(data); @@ -84,6 +92,8 @@ public class HttpResponses extends org.kohsuke.stapler.HttpResponses { * Set the response as an error response. * @param message The error "message" set on the response. * @return {@link this} object. + * + * @since 2.0 */ public static HttpResponse errorJSON(@Nonnull String message) { return new JSONObjectResponse().error(message); diff --git a/core/src/main/java/hudson/util/PluginServletFilter.java b/core/src/main/java/hudson/util/PluginServletFilter.java index 06fd67a925..9b311aa790 100644 --- a/core/src/main/java/hudson/util/PluginServletFilter.java +++ b/core/src/main/java/hudson/util/PluginServletFilter.java @@ -25,6 +25,7 @@ package hudson.util; import hudson.ExtensionPoint; import hudson.security.SecurityRealm; +import java.util.ArrayList; import jenkins.model.Jenkins; import javax.annotation.CheckForNull; @@ -148,18 +149,26 @@ public class PluginServletFilter implements Filter, ExtensionPoint { public static void cleanUp() { PluginServletFilter instance = getInstance(Jenkins.getInstance().servletContext); if (instance != null) { - for (Iterator iterator = instance.list.iterator(); iterator.hasNext(); ) { - Filter f = iterator.next(); + // While we could rely on the current implementation of list being a CopyOnWriteArrayList + // safer to just take an explicit copy of the list and operate on the copy + for (Filter f: new ArrayList<>(instance.list)) { + instance.list.remove(f); + // remove from the list even if destroy() fails as a failed destroy is still a destroy try { f.destroy(); } catch (RuntimeException e) { - LOGGER.log(Level.WARNING, "Filter " + f + " propagated an exception from its destroy method", e); + LOGGER.log(Level.WARNING, "Filter " + f + " propagated an exception from its destroy method", + e); } catch (Error e) { throw e; // we are not supposed to catch errors, don't log as could be an OOM } catch (Throwable e) { LOGGER.log(Level.SEVERE, "Filter " + f + " propagated an exception from its destroy method", e); } - iterator.remove(); + } + // if some fool adds a filter while we are terminating, we should just log the fact + if (!instance.list.isEmpty()) { + LOGGER.log(Level.SEVERE, "The following filters appear to have been added during clean up: {0}", + instance.list); } } } diff --git a/core/src/main/java/hudson/util/ProcessKillingVeto.java b/core/src/main/java/hudson/util/ProcessKillingVeto.java index 0235494032..3ae76c375d 100644 --- a/core/src/main/java/hudson/util/ProcessKillingVeto.java +++ b/core/src/main/java/hudson/util/ProcessKillingVeto.java @@ -44,7 +44,7 @@ import jenkins.model.Jenkins; * * @since TODO * - * @author Daniel Weber + * @author Daniel Weber */ public abstract class ProcessKillingVeto implements ExtensionPoint { diff --git a/core/src/main/java/jenkins/ClassLoaderReflectionToolkit.java b/core/src/main/java/jenkins/ClassLoaderReflectionToolkit.java index 49b2b76908..cfa342e513 100644 --- a/core/src/main/java/jenkins/ClassLoaderReflectionToolkit.java +++ b/core/src/main/java/jenkins/ClassLoaderReflectionToolkit.java @@ -34,7 +34,7 @@ public class ClassLoaderReflectionToolkit { gCLL = ClassLoader.class.getDeclaredMethod("getClassLoadingLock", String.class); gCLL.setAccessible(true); } catch (NoSuchMethodException x) { - // OK, Java 6 + throw new AssertionError(x); } GET_CLASS_LOADING_LOCK = gCLL; } @@ -59,12 +59,7 @@ public class ClassLoaderReflectionToolkit { } private static Object getClassLoadingLock(ClassLoader cl, String name) { - if (GET_CLASS_LOADING_LOCK != null) { - return invoke(GET_CLASS_LOADING_LOCK, RuntimeException.class, cl, name); - } else { - // Java 6 expects you to always synchronize on this. - return cl; - } + return invoke(GET_CLASS_LOADING_LOCK, RuntimeException.class, cl, name); } /** diff --git a/core/src/main/java/jenkins/I18n.java b/core/src/main/java/jenkins/I18n.java index 299b7328e3..d0f36ae3a4 100644 --- a/core/src/main/java/jenkins/I18n.java +++ b/core/src/main/java/jenkins/I18n.java @@ -37,7 +37,7 @@ import java.util.Locale; /** * Internationalization REST (ish) API. * @author tom.fennelly@gmail.com - * @since FIXME + * @since 2.0 */ @Extension @Restricted(NoExternalUse.class) diff --git a/core/src/main/java/jenkins/install/InstallState.java b/core/src/main/java/jenkins/install/InstallState.java index c634180bc8..42d223815f 100644 --- a/core/src/main/java/jenkins/install/InstallState.java +++ b/core/src/main/java/jenkins/install/InstallState.java @@ -23,6 +23,8 @@ */ package jenkins.install; +import javax.annotation.CheckForNull; + import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; @@ -33,6 +35,10 @@ import org.kohsuke.accmod.restrictions.NoExternalUse; */ @Restricted(NoExternalUse.class) public enum InstallState { + /** + * Need InstallState != NEW for tests by default + */ + UNKNOWN(true, null), /** * The initial set up has been completed */ @@ -90,6 +96,7 @@ public enum InstallState { /** * Gets the next state */ + @CheckForNull public InstallState getNextState() { return nextState; } diff --git a/core/src/main/java/jenkins/install/InstallUtil.java b/core/src/main/java/jenkins/install/InstallUtil.java index 475d1a3e01..0b7a2d84f5 100644 --- a/core/src/main/java/jenkins/install/InstallUtil.java +++ b/core/src/main/java/jenkins/install/InstallUtil.java @@ -45,6 +45,10 @@ import com.thoughtworks.xstream.XStream; import hudson.Functions; import hudson.model.UpdateCenter.DownloadJob.InstallationStatus; import hudson.model.UpdateCenter.DownloadJob.Installing; +import hudson.security.AuthorizationStrategy; +import hudson.security.FullControlOnceLoggedInAuthorizationStrategy; +import hudson.security.HudsonPrivateSecurityRealm; +import hudson.security.SecurityRealm; import hudson.model.UpdateCenter.InstallationJob; import hudson.model.UpdateCenter.UpdateCenterJob; import hudson.util.VersionNumber; @@ -69,8 +73,23 @@ public class InstallUtil { * @return The type of "startup" currently under way in Jenkins. */ public static InstallState getInstallState() { + // Support a simple state override. Useful for testing. + String stateOverride = System.getenv("jenkins.install.state"); + if (stateOverride != null) { + try { + return InstallState.valueOf(stateOverride.toUpperCase()); + } catch (RuntimeException e) { + throw new IllegalStateException("Unknown install state override specified on the commandline: '" + stateOverride + "'."); + } + } + + // Support a 3-state flag for running or disabling the setup wizard + String shouldRunFlag = System.getProperty("jenkins.install.runSetupWizard"); + boolean shouldRun = "true".equalsIgnoreCase(shouldRunFlag); + boolean shouldNotRun = "false".equalsIgnoreCase(shouldRunFlag); + // install wizard will always run if environment specified - if (!Boolean.getBoolean("jenkins.install.runSetupWizard")) { + if (!shouldRun) { if (Functions.getIsUnitTest()) { return InstallState.TEST; } @@ -85,10 +104,25 @@ public class InstallUtil { // Neither the top level config or the lastExecVersionFile have a version // stored in them, which means it's a new install. if (lastRunVersion.compareTo(NEW_INSTALL_VERSION) == 0) { + Jenkins j = Jenkins.getInstance(); + + // Allow for skipping + if(shouldNotRun) { + try { + SetupWizard.completeSetup(j); + UpgradeWizard.completeUpgrade(j); + return j.getInstallState(); + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + // Edge case: used Jenkins 1 but did not save the system config page, // the version is not persisted and returns 1.0, so try to check if // they actually did anything - if (!Jenkins.getInstance().getItemMap().isEmpty()) { + if (!j.getItemMap().isEmpty() || !mayBeJenkins2SecurityDefaults(j)) { return InstallState.UPGRADE; } return InstallState.NEW; @@ -107,6 +141,29 @@ public class InstallUtil { } } + /** + * This could be an upgrade, detect a non-default security realm for the stupid case + * where someone installed 1.x and did not save global config or create any items... + */ + private static boolean mayBeJenkins2SecurityDefaults(Jenkins j) { + if(j.getSecurityRealm() == SecurityRealm.NO_AUTHENTICATION) { // called before security set up first + return true; + } + if(j.getSecurityRealm() instanceof HudsonPrivateSecurityRealm) { // might be called after a restart, setup isn't complete + HudsonPrivateSecurityRealm securityRealm = (HudsonPrivateSecurityRealm)j.getSecurityRealm(); + if(securityRealm.getAllUsers().size() == 1 && securityRealm.getUser(SetupWizard.initialSetupAdminUserName) != null) { + AuthorizationStrategy authStrategy = j.getAuthorizationStrategy(); + if(authStrategy instanceof FullControlOnceLoggedInAuthorizationStrategy) { + // must have been using 2.0+ to set this, as it wasn't present in 1.x and the default is true, to _allow_ anon read + if(!((FullControlOnceLoggedInAuthorizationStrategy)authStrategy).isAllowAnonymousRead()) { + return true; + } + } + } + } + return false; + } + /** * Save the current Jenkins instance version as the last executed version. *

@@ -173,15 +230,15 @@ public class InstallUtil { } static File getConfigFile() { - return new File(Jenkins.getActiveInstance().getRootDir(), "config.xml"); + return new File(Jenkins.getInstance().getRootDir(), "config.xml"); } static File getLastExecVersionFile() { - return new File(Jenkins.getActiveInstance().getRootDir(), ".last_exec_version"); + return new File(Jenkins.getInstance().getRootDir(), "jenkins.install.InstallUtil.lastExecVersion"); } static File getInstallingPluginsFile() { - return new File(Jenkins.getActiveInstance().getRootDir(), ".installing_plugins"); + return new File(Jenkins.getInstance().getRootDir(), "jenkins.install.InstallUtil.installingPlugins"); } private static String getCurrentExecVersion() { diff --git a/core/src/main/java/jenkins/install/SetupWizard.java b/core/src/main/java/jenkins/install/SetupWizard.java index ea9a2e885f..b2faacbeb4 100644 --- a/core/src/main/java/jenkins/install/SetupWizard.java +++ b/core/src/main/java/jenkins/install/SetupWizard.java @@ -1,10 +1,9 @@ package jenkins.install; import java.io.IOException; -import java.util.Iterator; import java.util.Locale; -import java.util.Map; import java.util.UUID; +import java.util.logging.Level; import java.util.logging.Logger; import javax.servlet.Filter; @@ -16,37 +15,28 @@ import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; -import hudson.util.VersionNumber; +import org.acegisecurity.Authentication; +import org.acegisecurity.context.SecurityContextHolder; +import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; import org.kohsuke.stapler.HttpResponse; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import hudson.BulkChange; import hudson.FilePath; +import hudson.model.UpdateCenter; +import hudson.model.User; import hudson.security.FullControlOnceLoggedInAuthorizationStrategy; import hudson.security.HudsonPrivateSecurityRealm; import hudson.security.SecurityRealm; import hudson.security.csrf.DefaultCrumbIssuer; import hudson.util.HttpResponses; import hudson.util.PluginServletFilter; +import hudson.util.VersionNumber; import jenkins.model.Jenkins; import jenkins.security.s2m.AdminWhitelistRule; -import org.kohsuke.accmod.Restricted; -import org.kohsuke.accmod.restrictions.NoExternalUse; -import org.kohsuke.stapler.HttpResponse; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import java.io.IOException; -import java.util.Locale; -import java.util.UUID; -import java.util.logging.Logger; /** * A Jenkins instance used during first-run to provide a limited set of services while @@ -54,6 +44,7 @@ import java.util.logging.Logger; * * @since 2.0 */ +@Restricted(NoExternalUse.class) public class SetupWizard { /** * The security token parameter name @@ -66,6 +57,9 @@ public class SetupWizard { public SetupWizard(Jenkins j) throws IOException, InterruptedException { this.jenkins = j; + + UpgradeWizard.completeUpgrade(j); + // Create an admin user by default with a // difficult password FilePath iapf = getInitialAdminPasswordFile(); @@ -82,8 +76,10 @@ public class SetupWizard { // JENKINS-33599 - write to a file in the jenkins home directory // most native packages of Jenkins creates a machine user account 'jenkins' to run Jenkins, // and use group 'jenkins' for admins. So we allo groups to read this file - iapf.write(randomUUID, "UTF-8"); + iapf.touch(System.currentTimeMillis()); iapf.chmod(0640); + iapf.write(randomUUID + System.lineSeparator(), "UTF-8"); + // Lock Jenkins down: FullControlOnceLoggedInAuthorizationStrategy authStrategy = new FullControlOnceLoggedInAuthorizationStrategy(); @@ -106,36 +102,99 @@ public class SetupWizard { bc.abort(); } } - - String setupKey = iapf.readToString().trim(); - - LOGGER.info("\n\n*************************************************************\n" - + "*************************************************************\n" - + "*************************************************************\n" - + "\n" - + "Jenkins initial setup is required. An admin user has been created and" - + "a password generated. \n" - + "Please use the following password to proceed to installation: \n" - + "\n" - + "" + setupKey + "\n" - + "\n" - + "This may also be found at: " + iapf.getRemote() + "\n" - + "\n" - + "*************************************************************\n" - + "*************************************************************\n" - + "*************************************************************\n"); + + if(iapf.exists()) { + String setupKey = iapf.readToString().trim(); + String ls = System.lineSeparator(); + LOGGER.info(ls + ls + "*************************************************************" + ls + + "*************************************************************" + ls + + "*************************************************************" + ls + + ls + + "Jenkins initial setup is required. An admin user has been created and " + + "a password generated." + ls + + "Please use the following password to proceed to installation:" + ls + + ls + + setupKey + ls + + ls + + "This may also be found at: " + iapf.getRemote() + ls + + ls + + "*************************************************************" + ls + + "*************************************************************" + ls + + "*************************************************************" + ls); + } try { PluginServletFilter.addFilter(FORCE_SETUP_WIZARD_FILTER); } catch (ServletException e) { throw new AssertionError(e); } + + try { + // Make sure plugin metadata is up to date + UpdateCenter.updateDefaultSite(); + } catch (Exception e) { + LOGGER.log(Level.WARNING, e.getMessage(), e); + } + } + + /** + * Indicates a generated password should be used - e.g. this is a new install, no security realm set up + */ + public boolean useGeneratedPassword() { + try { + return getInitialAdminPasswordFile().exists(); + } catch (Exception e) { + // ignore + } + return false; + } + + /** + * Called during the initial setup to create an admin user + */ + public void doCreateAdminUser(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { + Jenkins j = Jenkins.getInstance(); + j.checkPermission(Jenkins.ADMINISTER); + + // This will be set up by default. if not, something changed, ok to fail + HudsonPrivateSecurityRealm securityRealm = (HudsonPrivateSecurityRealm)j.getSecurityRealm(); + + User admin = securityRealm.getUser(SetupWizard.initialSetupAdminUserName); + try { + if(admin != null) { + admin.delete(); // assume the new user may well be 'admin' + } + + User u = securityRealm.createAccountByAdmin(req, rsp, "/jenkins/install/SetupWizard/setupWizardFirstUser.jelly", req.getContextPath() + "/"); + if (u != null) { + if(admin != null) { + admin = null; + } + + // Success! Delete the temporary password file: + try { + getInitialAdminPasswordFile().delete(); + } catch (InterruptedException e) { + throw new IOException(e); + } + + j.setInstallState(InstallState.CREATE_ADMIN_USER.getNextState()); + + // ... and then login + Authentication a = new UsernamePasswordAuthenticationToken(u.getId(),req.getParameter("password1")); + a = securityRealm.getSecurityComponents().manager.authenticate(a); + SecurityContextHolder.getContext().setAuthentication(a); + } + } finally { + if(admin != null) { + admin.save(); // recreate this initial user if something failed + } + } } /** * Gets the file used to store the initial admin password */ - @Restricted(NoExternalUse.class) // use by Jelly public FilePath getInitialAdminPasswordFile() { return jenkins.getRootPath().child("secrets/initialAdminPassword"); } @@ -144,17 +203,16 @@ public class SetupWizard { * Remove the setupWizard filter, ensure all updates are written to disk, etc */ public HttpResponse doCompleteInstall() throws IOException, ServletException { + completeSetup(jenkins); + PluginServletFilter.removeFilter(FORCE_SETUP_WIZARD_FILTER); + return HttpResponses.okJSON(); + } + + static void completeSetup(Jenkins jenkins) { jenkins.setInstallState(InstallState.INITIAL_SETUP_COMPLETED); InstallUtil.saveLastExecVersion(); - PluginServletFilter.removeFilter(FORCE_SETUP_WIZARD_FILTER); // Also, clean up the setup wizard if it's completed jenkins.setSetupWizard(null); - - UpgradeWizard uw = jenkins.getInjector().getInstance(UpgradeWizard.class); - if (uw!=null) - uw.setCurrentLevel(new VersionNumber("2.0")); - - return HttpResponses.okJSON(); } /** @@ -167,13 +225,9 @@ public class SetupWizard { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - // As an extra measure of security, the install wizard generates a security token, and - // requires the user to enter it before proceeding through the installation. Once set - // we'll set a cookie so the subsequent operations succeed + // Force root requests to the setup wizard if (request instanceof HttpServletRequest) { HttpServletRequest req = (HttpServletRequest)request; - //if (!Pattern.compile(".*[.](css|ttf|gif|woff|eot|png|js)").matcher(req.getRequestURI()).matches()) { - // Allow js & css requests through if((req.getContextPath() + "/").equals(req.getRequestURI())) { chain.doFilter(new HttpServletRequestWrapper(req) { public String getRequestURI() { diff --git a/core/src/main/java/jenkins/install/UpgradeWizard.java b/core/src/main/java/jenkins/install/UpgradeWizard.java index dd15d04ac9..b2f47b3b04 100644 --- a/core/src/main/java/jenkins/install/UpgradeWizard.java +++ b/core/src/main/java/jenkins/install/UpgradeWizard.java @@ -10,6 +10,7 @@ import org.apache.commons.io.FileUtils; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; import org.kohsuke.stapler.HttpResponse; +import org.kohsuke.stapler.WebApp; import org.kohsuke.stapler.interceptor.RequirePOST; import javax.inject.Inject; @@ -46,7 +47,7 @@ public class UpgradeWizard extends PageDecorator { * This file records the vesrion number that the installation has upgraded to. */ /*package*/ File getStateFile() { - return new File(Jenkins.getInstance().getRootDir(),"upgraded"); + return new File(Jenkins.getInstance().getRootDir(),"jenkins.install.UpgradeWizard.state"); } public UpgradeWizard() throws IOException { @@ -70,10 +71,17 @@ public class UpgradeWizard extends PageDecorator { } /*package*/ - public void setCurrentLevel(VersionNumber v) throws IOException { + void setCurrentLevel(VersionNumber v) throws IOException { FileUtils.writeStringToFile(getStateFile(), v.toString()); updateUpToDate(); } + + static void completeUpgrade(Jenkins jenkins) throws IOException { + // this was determined to be a new install, don't run the update wizard here + UpgradeWizard uw = jenkins.getInjector().getInstance(UpgradeWizard.class); + if (uw!=null) + uw.setCurrentLevel(new VersionNumber("2.0")); + } /** * Do we need to show the upgrade wizard prompt? @@ -86,6 +94,11 @@ public class UpgradeWizard extends PageDecorator { if (!jenkins.hasPermission(Jenkins.ADMINISTER)) return false; + // only show when Jenkins is fully up & running + WebApp wa = WebApp.getCurrent(); + if (wa==null || !(wa.getApp() instanceof Jenkins)) + return false; + return System.currentTimeMillis() > getStateFile().lastModified(); } diff --git a/core/src/main/java/jenkins/management/ConfigureLink.java b/core/src/main/java/jenkins/management/ConfigureLink.java index 21ec958821..a10df71b22 100644 --- a/core/src/main/java/jenkins/management/ConfigureLink.java +++ b/core/src/main/java/jenkins/management/ConfigureLink.java @@ -36,7 +36,7 @@ public class ConfigureLink extends ManagementLink { @Override public String getIconFileName() { - return "setting.png"; + return "gear2.png"; } public String getDisplayName() { diff --git a/core/src/main/java/jenkins/model/AssetManager.java b/core/src/main/java/jenkins/model/AssetManager.java index f8c8aff33f..f6308e631d 100644 --- a/core/src/main/java/jenkins/model/AssetManager.java +++ b/core/src/main/java/jenkins/model/AssetManager.java @@ -21,6 +21,8 @@ import java.util.Enumeration; * resource from the classpath below {@code /assets}. * * @author Kohsuke Kawaguchi + * + * @since 2.0 */ @Extension @Symbol("assetManager") public class AssetManager implements UnprotectedRootAction { diff --git a/core/src/main/java/jenkins/model/GlobalConfiguration.java b/core/src/main/java/jenkins/model/GlobalConfiguration.java index 15cc69f831..31c8e08ff3 100644 --- a/core/src/main/java/jenkins/model/GlobalConfiguration.java +++ b/core/src/main/java/jenkins/model/GlobalConfiguration.java @@ -42,15 +42,6 @@ public abstract class GlobalConfiguration extends Descriptor d : Functions.getSortedDescriptorsForGlobalConfigUnclassified()) result &= configureDescriptor(req,json,d); @@ -3602,20 +3607,6 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve // looks good } - /** - * Makes sure that the given name is good as a job name. - * @return trimmed name if valid; throws Failure if not - */ - private String checkJobName(String name) throws Failure { - checkGoodName(name); - name = name.trim(); - projectNamingStrategy.checkName(name); - if(getItem(name)!=null) - throw new Failure(Messages.Hudson_JobAlreadyExists(name)); - // looks good - return name; - } - private static String toPrintableName(String name) { StringBuilder printableName = new StringBuilder(); for( int i=0; i * Parses the version into {@link VersionNumber}, or null if it's not parseable as a version number * (such as when Jenkins is run with "mvn hudson-dev:run") - * @since FIXME + * @since 2.0 */ + @Restricted(NoExternalUse.class) public @CheckForNull static VersionNumber getStoredVersion() { return toVersion(Jenkins.getActiveInstance().version); } @@ -4818,16 +4799,14 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve // double check that initialization order didn't do any harm assert PERMISSIONS != null; assert ADMINISTER != null; - } catch (RuntimeException e) { + + } catch (RuntimeException | Error e) { // when loaded on an agent and this fails, subsequent NoClassDefFoundError will fail to chain the cause. // see http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8051847 // As we don't know where the first exception will go, let's also send this to logging so that // we have a known place to look at. LOGGER.log(SEVERE, "Failed to load Jenkins.class", e); throw e; - } catch (Error e) { - LOGGER.log(SEVERE, "Failed to load Jenkins.class", e); - throw e; } } diff --git a/core/src/main/java/jenkins/model/ParameterizedJobMixIn.java b/core/src/main/java/jenkins/model/ParameterizedJobMixIn.java index 07d1e61e6b..40e904eecd 100644 --- a/core/src/main/java/jenkins/model/ParameterizedJobMixIn.java +++ b/core/src/main/java/jenkins/model/ParameterizedJobMixIn.java @@ -177,6 +177,10 @@ public abstract class ParameterizedJobMixIn & Param delay = new TimeDuration(asJob().getQuietPeriod()); } + if (!asJob().isBuildable()) { + throw HttpResponses.error(SC_INTERNAL_SERVER_ERROR, new IOException(asJob().getFullName() + " is not buildable")); + } + // if a build is parameterized, let that take over ParametersDefinitionProperty pp = asJob().getProperty(ParametersDefinitionProperty.class); if (pp != null && !req.getMethod().equals("POST")) { @@ -192,9 +196,6 @@ public abstract class ParameterizedJobMixIn & Param return; } - if (!asJob().isBuildable()) { - throw HttpResponses.error(SC_INTERNAL_SERVER_ERROR, new IOException(asJob().getFullName() + " is not buildable")); - } Queue.Item item = Jenkins.getInstance().getQueue().schedule2(asJob(), delay.getTime(), getBuildCause(asJob(), req)).getItem(); if (item != null) { diff --git a/core/src/main/java/jenkins/model/RunIdMigrator.java b/core/src/main/java/jenkins/model/RunIdMigrator.java index 94d378633a..5675d8ab4a 100644 --- a/core/src/main/java/jenkins/model/RunIdMigrator.java +++ b/core/src/main/java/jenkins/model/RunIdMigrator.java @@ -38,6 +38,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URISyntaxException; import java.net.URL; +import java.nio.file.Files; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -277,30 +278,10 @@ public final class RunIdMigrator { * TODO candidate for moving to {@link Util} */ static void move(File src, File dest) throws IOException { - Class pathC; try { - pathC = Class.forName("java.nio.file.Path"); - } catch (ClassNotFoundException x) { - // Java 6, do our best - if (dest.exists()) { - throw new IOException(dest + " already exists"); - } - if (src.renameTo(dest)) { - return; - } - throw new IOException("could not move " + src + " to " + dest); - } - try { - Method toPath = File.class.getMethod("toPath"); - Class copyOptionAC = Class.forName("[Ljava.nio.file.CopyOption;"); - Class.forName("java.nio.file.Files").getMethod("move", pathC, pathC, copyOptionAC).invoke(null, toPath.invoke(src), toPath.invoke(dest), Array.newInstance(copyOptionAC.getComponentType(), 0)); - } catch (InvocationTargetException x) { - Throwable cause = x.getCause(); - if (cause instanceof IOException) { - throw (IOException) cause; - } else { - throw new IOException(cause); - } + Files.move(src.toPath(), dest.toPath()); + } catch (IOException x) { + throw x; } catch (Exception x) { throw new IOException(x); } diff --git a/core/src/main/java/jenkins/model/Uptime.java b/core/src/main/java/jenkins/model/Uptime.java index 81cce79374..190c678ff7 100644 --- a/core/src/main/java/jenkins/model/Uptime.java +++ b/core/src/main/java/jenkins/model/Uptime.java @@ -27,7 +27,7 @@ public class Uptime { } @Initializer(after=InitMilestone.JOB_LOADED) - public static void init() { - ExtensionList.lookup(Uptime.class).get(0).startTime = System.currentTimeMillis(); + public void init() { + startTime = System.currentTimeMillis(); } } diff --git a/core/src/main/java/jenkins/model/item_category/Categories.java b/core/src/main/java/jenkins/model/item_category/Categories.java new file mode 100644 index 0000000000..fe188dafbe --- /dev/null +++ b/core/src/main/java/jenkins/model/item_category/Categories.java @@ -0,0 +1,81 @@ +/* + * 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 + * 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. + */ + +package jenkins.model.item_category; + +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; +import org.kohsuke.stapler.HttpResponse; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.export.Exported; +import org.kohsuke.stapler.export.ExportedBean; +import org.kohsuke.stapler.export.Flavor; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import javax.servlet.ServletException; +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * It is a logic representation of a set of {@link Category}. + * + * This class is not thread-safe. + * + * @since 2.0 + */ +@ExportedBean +@Restricted(NoExternalUse.class) +public class Categories implements HttpResponse, Serializable { + + private List items; + + public Categories() { + items = new ArrayList(); + } + + @Exported(name = "categories") + public List getItems() { + return items; + } + + @Override + public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException { + rsp.serveExposedBean(req, this, Flavor.JSON); + } + + @CheckForNull + public Category getItem(@Nonnull String id) { + for (Category category : items) { + if (category.getId().equals(id)) { + return category; + } + } + return null; + } + +} diff --git a/core/src/main/java/jenkins/model/item_category/Category.java b/core/src/main/java/jenkins/model/item_category/Category.java new file mode 100644 index 0000000000..391d7ab8e3 --- /dev/null +++ b/core/src/main/java/jenkins/model/item_category/Category.java @@ -0,0 +1,97 @@ +/* + * The MIT License + * + * Copyright 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 + * 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. + */ + +package jenkins.model.item_category; + +import hudson.model.TopLevelItem; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; +import org.kohsuke.stapler.export.Exported; +import org.kohsuke.stapler.export.ExportedBean; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * Represents an {@link ItemCategory} and its {@link TopLevelItem}s. + * + * This class is not thread-safe. + */ +@ExportedBean +@Restricted(NoExternalUse.class) +public class Category implements Serializable { + + private String id; + + private String name; + + private String description; + + private int order; + + private int minToShow; + + private List> items; + + public Category(String id, String name, String description, int order, int minToShow, List> items) { + this.id= id; + this.name = name; + this.description = description; + this.order = order; + this.minToShow = minToShow; + this.items = items; + } + + @Exported + public String getId() { + return id; + } + + @Exported + public String getName() { + return name; + } + + @Exported + public String getDescription() { + return description; + } + + @Exported + public int getOrder() { + return order; + } + + @Exported + public int getMinToShow() { + return minToShow; + } + + @Exported + public List> getItems() { + return items; + } + +} diff --git a/core/src/main/java/jenkins/model/item_category/ItemCategory.java b/core/src/main/java/jenkins/model/item_category/ItemCategory.java new file mode 100644 index 0000000000..7078a86377 --- /dev/null +++ b/core/src/main/java/jenkins/model/item_category/ItemCategory.java @@ -0,0 +1,133 @@ +/* + * 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 + * 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. + */ + +package jenkins.model.item_category; + +import hudson.Extension; +import hudson.ExtensionList; +import hudson.ExtensionPoint; +import hudson.model.TopLevelItemDescriptor; + +import javax.annotation.Nonnull; + +/** + * A category for {@link hudson.model.Item}s. + * + * @since 2.0 + */ +public abstract class ItemCategory implements ExtensionPoint { + + public static int MIN_TOSHOW = 1; + + /** + * Helpful to set the order. + */ + private int order = 1; + + /** + * Identifier, e.g. "standaloneprojects", etc. + * + * @return the identifier + */ + public abstract String getId(); + + /** + * The description in plain text + * + * @return the description + */ + public abstract String getDescription(); + + /** + * A human readable name. + * + * @return the display name + */ + public abstract String getDisplayName(); + + /** + * Minimum number of items required to show the category. + * + * @return the minimum items required + */ + public abstract int getMinToShow(); + + private void setOrder(int order) { + this.order = order; + } + + public int getOrder() { + return order; + } + + /** + * A {@link ItemCategory} associated to this {@link TopLevelItemDescriptor}. + * + * @return A {@link ItemCategory}, if not found, {@link ItemCategory.UncategorizedCategory} is returned + */ + @Nonnull + public static ItemCategory getCategory(TopLevelItemDescriptor descriptor) { + int order = 0; + ExtensionList categories = ExtensionList.lookup(ItemCategory.class); + for (ItemCategory category : categories) { + if (category.getId().equals(descriptor.getCategoryId())) { + category.setOrder(++order); + return category; + } + order++; + } + return new UncategorizedCategory(); + } + + /** + * The default {@link ItemCategory}, if an item doesn't belong anywhere else, this is where it goes by default. + */ + @Extension(ordinal = Integer.MIN_VALUE) + public static final class UncategorizedCategory extends ItemCategory { + + public static final String ID = "uncategorized"; + + @Override + public String getId() { + return ID; + } + + @Override + public String getDescription() { + return Messages.Uncategorized_Description(); + } + + @Override + public String getDisplayName() { + return Messages.Uncategorized_DisplayName(); + } + + @Override + public int getMinToShow() { + return ItemCategory.MIN_TOSHOW; + } + + } + +} diff --git a/core/src/main/java/jenkins/model/item_category/NestedProjectsCategory.java b/core/src/main/java/jenkins/model/item_category/NestedProjectsCategory.java new file mode 100644 index 0000000000..b4501d01e4 --- /dev/null +++ b/core/src/main/java/jenkins/model/item_category/NestedProjectsCategory.java @@ -0,0 +1,67 @@ +/* + * 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 + * 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. + */ + +package jenkins.model.item_category; + +import hudson.Extension; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.DoNotUse; + +/** + * Designed for project hierarchies with folders. + * + * This category should be moved to cloudbees-folder-plugin short-term. + * Really when upgrades its baseline to 2.0. + * + * @since 2.0 + */ +@Restricted(DoNotUse.class) +@Extension(ordinal = -100) +public class NestedProjectsCategory extends ItemCategory { + + /** + * TODO Make public when be moved to cloudbees-folder-plugin. + */ + private static final String ID = "nested-projects"; + + @Override + public String getId() { + return ID; + } + + @Override + public String getDescription() { + return Messages.NestedProjects_Description(); + } + + @Override + public String getDisplayName() { + return Messages.NestedProjects_DisplayName(); + } + + @Override + public int getMinToShow() { + return ItemCategory.MIN_TOSHOW; + } +} diff --git a/core/src/main/java/jenkins/model/item_category/StandaloneProjectsCategory.java b/core/src/main/java/jenkins/model/item_category/StandaloneProjectsCategory.java new file mode 100644 index 0000000000..d1e5479bff --- /dev/null +++ b/core/src/main/java/jenkins/model/item_category/StandaloneProjectsCategory.java @@ -0,0 +1,56 @@ +/* + * 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 + * 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. + */ + +package jenkins.model.item_category; + +import hudson.Extension; + +/** + * Designed for projects with a self-contained configuration and history. + */ +@Extension(ordinal = -100) +public class StandaloneProjectsCategory extends ItemCategory { + + public static final String ID = "standalone-projects"; + + @Override + public String getId() { + return ID; + } + + @Override + public String getDescription() { + return Messages.StandaloneProjects_Description(); + } + + @Override + public String getDisplayName() { + return Messages.StandaloneProjects_DisplayName(); + } + + @Override + public int getMinToShow() { + return ItemCategory.MIN_TOSHOW; + } +} diff --git a/core/src/main/java/jenkins/mvn/GlobalMavenConfig.java b/core/src/main/java/jenkins/mvn/GlobalMavenConfig.java index 8599b980f9..c10b3db2d5 100644 --- a/core/src/main/java/jenkins/mvn/GlobalMavenConfig.java +++ b/core/src/main/java/jenkins/mvn/GlobalMavenConfig.java @@ -2,6 +2,8 @@ package jenkins.mvn; import hudson.Extension; import jenkins.model.GlobalConfiguration; +import jenkins.model.GlobalConfigurationCategory; +import jenkins.tools.ToolConfigurationCategory; import net.sf.json.JSONObject; import org.jenkinsci.Symbol; @@ -17,6 +19,11 @@ public class GlobalMavenConfig extends GlobalConfiguration { load(); } + @Override + public ToolConfigurationCategory getCategory() { + return GlobalConfigurationCategory.get(ToolConfigurationCategory.class); + } + @Override public boolean configure(StaplerRequest req, JSONObject json) throws FormException { req.bindJSON(this, json); diff --git a/core/src/main/java/jenkins/security/RekeySecretAdminMonitor.java b/core/src/main/java/jenkins/security/RekeySecretAdminMonitor.java index 05a22b94d9..7b48e94a0c 100644 --- a/core/src/main/java/jenkins/security/RekeySecretAdminMonitor.java +++ b/core/src/main/java/jenkins/security/RekeySecretAdminMonitor.java @@ -114,13 +114,11 @@ public class RekeySecretAdminMonitor extends AsynchronousAdministrativeMonitor i @Initializer(fatal=false,after=InitMilestone.PLUGINS_STARTED,before=InitMilestone.EXTENSIONS_AUGMENTED) // as early as possible, but this needs to be late enough that the ConfidentialStore is available - public static void scanOnReboot() throws InterruptedException, IOException, GeneralSecurityException { - RekeySecretAdminMonitor m = new RekeySecretAdminMonitor(); // throw-away instance - - FileBoolean flag = m.scanOnBoot; + public void scanOnReboot() throws InterruptedException, IOException, GeneralSecurityException { + FileBoolean flag = scanOnBoot; if (flag.isOn()) { flag.off(); - m.start(false).join(); + start(false).join(); // block the boot until the rewrite process is complete // don't let the failure in RekeyThread block Jenkins boot. } diff --git a/core/src/main/java/jenkins/slaves/NioChannelSelector.java b/core/src/main/java/jenkins/slaves/NioChannelSelector.java index 3aea28a1e3..24b9de1c7f 100644 --- a/core/src/main/java/jenkins/slaves/NioChannelSelector.java +++ b/core/src/main/java/jenkins/slaves/NioChannelSelector.java @@ -1,6 +1,7 @@ package jenkins.slaves; import hudson.Extension; +import hudson.init.Terminator; import hudson.model.Computer; import org.jenkinsci.remoting.nio.NioChannelHub; @@ -34,6 +35,14 @@ public class NioChannelSelector { return hub; } + @Terminator + public void cleanUp() throws IOException { + if (hub!=null) { + hub.close(); + hub = null; + } + } + /** * Escape hatch to disable use of NIO. */ diff --git a/core/src/main/java/jenkins/tools/GlobalToolConfiguration.java b/core/src/main/java/jenkins/tools/GlobalToolConfiguration.java new file mode 100644 index 0000000000..209c4a1b72 --- /dev/null +++ b/core/src/main/java/jenkins/tools/GlobalToolConfiguration.java @@ -0,0 +1,109 @@ +/* + * 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 + * 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. + */ +package jenkins.tools; + +import com.google.common.base.Predicate; +import hudson.Extension; +import hudson.Functions; +import hudson.model.Descriptor; +import hudson.model.ManagementLink; +import hudson.security.Permission; +import hudson.util.FormApply; +import jenkins.model.GlobalConfigurationCategory; +import jenkins.model.Jenkins; +import net.sf.json.JSONObject; + +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; + +import javax.servlet.ServletException; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +@Extension(ordinal = Integer.MAX_VALUE - 220) +@Restricted(NoExternalUse.class) +public class GlobalToolConfiguration extends ManagementLink { + + @Override + public String getIconFileName() { + return "setting.png"; + } + + @Override + public String getDisplayName() { + return jenkins.management.Messages.ConfigureTools_DisplayName(); + } + + @Override + public String getDescription() { + return jenkins.management.Messages.ConfigureTools_Description(); + } + + @Override + public String getUrlName() { + return "configureTools"; + } + + @Override + public Permission getRequiredPermission() { + return Jenkins.ADMINISTER; + } + + public synchronized void doConfigure(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { + boolean result = configure(req, req.getSubmittedForm()); + LOGGER.log(Level.FINE, "tools saved: "+result); + FormApply.success(req.getContextPath() + "/manage").generateResponse(req, rsp, null); + } + + private boolean configure(StaplerRequest req, JSONObject json) throws hudson.model.Descriptor.FormException, IOException { + Jenkins j = Jenkins.getInstance(); + j.checkPermission(Jenkins.ADMINISTER); + + boolean result = true; + for(Descriptor d : Functions.getSortedDescriptorsForGlobalConfig(FILTER)){ + result &= configureDescriptor(req, json, d); + } + j.save(); + + return result; + } + + private boolean configureDescriptor(StaplerRequest req, JSONObject json, Descriptor d) throws Descriptor.FormException { + 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); + } + + public static Predicate FILTER = new Predicate() { + public boolean apply(GlobalConfigurationCategory input) { + return input instanceof ToolConfigurationCategory; + } + }; + + private static final Logger LOGGER = Logger.getLogger(GlobalToolConfiguration.class.getName()); +} diff --git a/core/src/main/java/jenkins/tools/ToolConfigurationCategory.java b/core/src/main/java/jenkins/tools/ToolConfigurationCategory.java new file mode 100644 index 0000000000..e785369556 --- /dev/null +++ b/core/src/main/java/jenkins/tools/ToolConfigurationCategory.java @@ -0,0 +1,21 @@ +package jenkins.tools; + +import hudson.Extension; +import jenkins.model.GlobalConfigurationCategory; + +/** + * Global configuration of tool locations and installers. + * + * @since 2.0 + */ +@Extension +public class ToolConfigurationCategory extends GlobalConfigurationCategory { + @Override + public String getShortDescription() { + return jenkins.management.Messages.ConfigureTools_Description(); + } + + public String getDisplayName() { + return jenkins.management.Messages.ConfigureTools_DisplayName(); + } +} diff --git a/core/src/main/java/jenkins/triggers/ReverseBuildTrigger.java b/core/src/main/java/jenkins/triggers/ReverseBuildTrigger.java index c4a1d5f57f..b15de6ad64 100644 --- a/core/src/main/java/jenkins/triggers/ReverseBuildTrigger.java +++ b/core/src/main/java/jenkins/triggers/ReverseBuildTrigger.java @@ -25,6 +25,7 @@ package jenkins.triggers; import hudson.Extension; +import hudson.ExtensionList; import hudson.Util; import hudson.console.ModelHyperlinkNote; import hudson.model.AbstractBuild; @@ -87,7 +88,6 @@ import javax.annotation.Nonnull; public final class ReverseBuildTrigger extends Trigger implements DependencyDeclarer { private static final Logger LOGGER = Logger.getLogger(ReverseBuildTrigger.class.getName()); - private static final Map> upstream2Trigger = new WeakHashMap<>(); private String upstreamProjects; private final Result threshold; @@ -150,34 +150,12 @@ public final class ReverseBuildTrigger extends Trigger implements Dependenc @Override public void start(@Nonnull Job project, boolean newInstance) { super.start(project, newInstance); - SecurityContext orig = ACL.impersonate(ACL.SYSTEM); - try { - for (Job upstream : Items.fromNameList(project.getParent(), upstreamProjects, Job.class)) { - if (upstream instanceof AbstractProject && project instanceof AbstractProject) { - continue; // handled specially - } - synchronized (upstream2Trigger) { - Collection triggers = upstream2Trigger.get(upstream); - if (triggers == null) { - triggers = new LinkedList<>(); - upstream2Trigger.put(upstream, triggers); - } - triggers.remove(this); - triggers.add(this); - } - } - } finally { - SecurityContextHolder.setContext(orig); - } + RunListenerImpl.get().invalidateCache(); } @Override public void stop() { super.stop(); - synchronized (upstream2Trigger) { - for (Collection triggers : upstream2Trigger.values()) { - triggers.remove(this); - } - } + RunListenerImpl.get().invalidateCache(); } @Extension @Symbol("upstream") @@ -223,9 +201,53 @@ public final class ReverseBuildTrigger extends Trigger implements Dependenc } @Extension public static final class RunListenerImpl extends RunListener { + + static RunListenerImpl get() { + return ExtensionList.lookup(RunListener.class).get(RunListenerImpl.class); + } + + private Map> upstream2Trigger; + + synchronized void invalidateCache() { + upstream2Trigger = null; + } + + private Map> calculateCache() { + final Map> result = new WeakHashMap<>(); + ACL.impersonate(ACL.SYSTEM, new Runnable() { + @Override + public void run() { + for (Job downstream : Jenkins.getInstance().getAllItems(Job.class)) { + ReverseBuildTrigger trigger = ParameterizedJobMixIn.getTrigger(downstream, ReverseBuildTrigger.class); + if (trigger == null) { + continue; + } + List upstreams = Items.fromNameList(downstream.getParent(), trigger.upstreamProjects, Job.class); + LOGGER.log(Level.FINE, "from {0} see upstreams {1}", new Object[] {downstream, upstreams}); + for (Job upstream : upstreams) { + if (upstream instanceof AbstractProject && downstream instanceof AbstractProject) { + continue; // handled specially + } + Collection triggers = result.get(upstream); + if (triggers == null) { + triggers = new LinkedList<>(); + result.put(upstream, triggers); + } + triggers.remove(trigger); + triggers.add(trigger); + } + } + } + }); + return result; + } + @Override public void onCompleted(@Nonnull Run r, @Nonnull TaskListener listener) { Collection triggers; - synchronized (upstream2Trigger) { + synchronized (this) { + if (upstream2Trigger == null) { + upstream2Trigger = calculateCache(); + } Collection _triggers = upstream2Trigger.get(r.getParent()); if (_triggers == null || _triggers.isEmpty()) { return; @@ -250,21 +272,26 @@ public final class ReverseBuildTrigger extends Trigger implements Dependenc } @Extension public static class ItemListenerImpl extends ItemListener { - @Override public void onLocationChanged(Item item, String oldFullName, String newFullName) { - for (Job p : Jenkins.getInstance().getAllItems(Job.class)) { - ReverseBuildTrigger t = ParameterizedJobMixIn.getTrigger(p, ReverseBuildTrigger.class); - if (t != null) { - String revised = Items.computeRelativeNamesAfterRenaming(oldFullName, newFullName, t.upstreamProjects, p.getParent()); - if (!revised.equals(t.upstreamProjects)) { - t.upstreamProjects = revised; - try { - p.save(); - } catch (IOException e) { - LOGGER.log(Level.WARNING, "Failed to persist project setting during rename from " + oldFullName + " to " + newFullName, e); + @Override public void onLocationChanged(Item item, final String oldFullName, final String newFullName) { + ACL.impersonate(ACL.SYSTEM, new Runnable() { + @Override + public void run() { + for (Job p : Jenkins.getInstance().getAllItems(Job.class)) { + ReverseBuildTrigger t = ParameterizedJobMixIn.getTrigger(p, ReverseBuildTrigger.class); + if (t != null) { + String revised = Items.computeRelativeNamesAfterRenaming(oldFullName, newFullName, t.upstreamProjects, p.getParent()); + if (!revised.equals(t.upstreamProjects)) { + t.upstreamProjects = revised; + try { + p.save(); + } catch (IOException e) { + LOGGER.log(Level.WARNING, "Failed to persist project setting during rename from " + oldFullName + " to " + newFullName, e); + } + } } } } - } + }); } } } diff --git a/core/src/main/java/jenkins/util/ResourceBundleUtil.java b/core/src/main/java/jenkins/util/ResourceBundleUtil.java index 1649c6c77c..f87aedac60 100644 --- a/core/src/main/java/jenkins/util/ResourceBundleUtil.java +++ b/core/src/main/java/jenkins/util/ResourceBundleUtil.java @@ -37,7 +37,7 @@ import java.util.concurrent.ConcurrentHashMap; /** * Simple {@link java.util.ResourceBundle} utility class. * @author tom.fennelly@gmail.com - * @since FIXME + * @since 2.0 */ public class ResourceBundleUtil { diff --git a/core/src/main/java/jenkins/util/xml/XMLUtils.java b/core/src/main/java/jenkins/util/xml/XMLUtils.java index bf96669052..a376ef25bc 100644 --- a/core/src/main/java/jenkins/util/xml/XMLUtils.java +++ b/core/src/main/java/jenkins/util/xml/XMLUtils.java @@ -107,7 +107,7 @@ public final class XMLUtils { * @return The XML {@link Document}. * @throws SAXException Error parsing the XML stream data e.g. badly formed XML. * @throws IOException Error reading from the steam. - * @since FIXME + * @since 2.0 */ public static @Nonnull Document parse(@Nonnull Reader stream) throws SAXException, IOException { DocumentBuilder docBuilder; @@ -129,7 +129,7 @@ public final class XMLUtils { * @return The parsed document. * @throws SAXException Error parsing the XML file data e.g. badly formed XML. * @throws IOException Error reading from the file. - * @since FIXME + * @since 2.0 */ public static @Nonnull Document parse(@Nonnull File file, @Nonnull String encoding) throws SAXException, IOException { if (!file.exists() || !file.isFile()) { @@ -161,7 +161,7 @@ public final class XMLUtils { * @throws IOException Error reading from the file. * @throws SAXException Error parsing the XML file data e.g. badly formed XML. * @throws XPathExpressionException Invalid XPath expression. - * @since FIXME + * @since 2.0 */ public static @Nonnull String getValue(@Nonnull String xpath, @Nonnull File file) throws IOException, SAXException, XPathExpressionException { return getValue(xpath, file, Charset.defaultCharset().toString()); @@ -177,7 +177,7 @@ public final class XMLUtils { * @throws IOException Error reading from the file. * @throws SAXException Error parsing the XML file data e.g. badly formed XML. * @throws XPathExpressionException Invalid XPath expression. - * @since FIXME + * @since 2.0 */ public static @Nonnull String getValue(@Nonnull String xpath, @Nonnull File file, @Nonnull String fileDataEncoding) throws IOException, SAXException, XPathExpressionException { Document document = parse(file, fileDataEncoding); @@ -191,7 +191,7 @@ public final class XMLUtils { * @return The data value. An empty {@link String} is returned when the expression does not evaluate * to anything in the document. * @throws XPathExpressionException Invalid XPath expression. - * @since FIXME + * @since 2.0 */ public static String getValue(String xpath, Document document) throws XPathExpressionException { XPath xPathProcessor = XPathFactory.newInstance().newXPath(); diff --git a/core/src/main/resources/hudson/TcpSlaveAgentListener/index.jelly b/core/src/main/resources/hudson/TcpSlaveAgentListener/index.jelly index 5b70213d5f..99585e9896 100644 --- a/core/src/main/resources/hudson/TcpSlaveAgentListener/index.jelly +++ b/core/src/main/resources/hudson/TcpSlaveAgentListener/index.jelly @@ -28,8 +28,8 @@ THE SOFTWARE. Publicize the TCP port number for JNLP agents so that they know where to conenct. Keep the legacy header for better backward compatibility --> - - + + diff --git a/core/src/main/resources/hudson/logging/LogRecorder/sidepanel.jelly b/core/src/main/resources/hudson/logging/LogRecorder/sidepanel.jelly index b9c8884ff2..686f05cf7e 100644 --- a/core/src/main/resources/hudson/logging/LogRecorder/sidepanel.jelly +++ b/core/src/main/resources/hudson/logging/LogRecorder/sidepanel.jelly @@ -32,7 +32,7 @@ THE SOFTWARE. - + diff --git a/core/src/main/resources/hudson/logging/LogRecorderManager/index.jelly b/core/src/main/resources/hudson/logging/LogRecorderManager/index.jelly index 7b6e2d677e..e188caed69 100644 --- a/core/src/main/resources/hudson/logging/LogRecorderManager/index.jelly +++ b/core/src/main/resources/hudson/logging/LogRecorderManager/index.jelly @@ -59,7 +59,7 @@ THE SOFTWARE. - + diff --git a/core/src/main/resources/hudson/logging/LogRecorderManager/sidepanel.jelly b/core/src/main/resources/hudson/logging/LogRecorderManager/sidepanel.jelly index d3d6da9935..c27d64b58a 100644 --- a/core/src/main/resources/hudson/logging/LogRecorderManager/sidepanel.jelly +++ b/core/src/main/resources/hudson/logging/LogRecorderManager/sidepanel.jelly @@ -31,7 +31,7 @@ THE SOFTWARE. - + diff --git a/core/src/main/resources/hudson/model/AbstractItem/help-slaveAffinity.html b/core/src/main/resources/hudson/model/AbstractItem/help-slaveAffinity.html index bac70c76f2..61dd733294 100644 --- a/core/src/main/resources/hudson/model/AbstractItem/help-slaveAffinity.html +++ b/core/src/main/resources/hudson/model/AbstractItem/help-slaveAffinity.html @@ -1,17 +1,15 @@

- Sometimes a project can only be successfully built on a particular agent - (or master). If so, this option forces Jenkins to always build this project - on a specific computer. - - If there is a group of machines that the job can be built on, you can specify - that label as the node to tie on, which will cause Jenkins to build the - project on any of the machines with that label. - + By default, builds of this project may be executed on any build agents that + are available and configured to accept new builds.

- Otherwise, uncheck the box so that Jenkins can schedule builds on available - nodes, which results in faster turn-around time. - + When this option is checked, you have the possibility to ensure that builds of + this project only occur on a certain agent, or set of agents.

- This option is also useful when you'd like to make sure that a project can - be built on a particular node. -

\ No newline at end of file + For example, if your project should only be built on a certain operating + system, or on machines that have a certain set of tools installed, or even one + specific machine, you can restrict this project to only execute on agents that + that meet those criteria. +

+ The help text for the Label Expression field, shown when this option is + checked, provides more detailed information on how to specify agent criteria. + diff --git a/core/src/main/resources/hudson/model/AbstractProject/configure-common.jelly b/core/src/main/resources/hudson/model/AbstractProject/configure-common.jelly index 62b5bd176a..806067f210 100644 --- a/core/src/main/resources/hudson/model/AbstractProject/configure-common.jelly +++ b/core/src/main/resources/hudson/model/AbstractProject/configure-common.jelly @@ -48,19 +48,17 @@ THE SOFTWARE. - - - - - - - - - - - - - + + + + + + + + + + + diff --git a/core/src/main/resources/hudson/model/AbstractProject/help-concurrentBuild.html b/core/src/main/resources/hudson/model/AbstractProject/help-concurrentBuild.html index 6c5752360a..7d2116b37a 100644 --- a/core/src/main/resources/hudson/model/AbstractProject/help-concurrentBuild.html +++ b/core/src/main/resources/hudson/model/AbstractProject/help-concurrentBuild.html @@ -1,24 +1,39 @@ +

- If this option is checked, Jenkins will schedule and execute multiple builds concurrently (provided - that you have sufficient executors and incoming build requests.) This is useful on builds and test jobs that - take a long time, as each build will only contain a smaller number of changes, and the total turn-around - time decreases due to the shorter time a build request spends waiting for the previous build to complete. - It is also very useful with parameterized builds, whose individual executions are independent from each other. - -

- For other kinds of jobs, allowing concurrent executions of multiple builds may be problematic, - for example if it assumes a monopoly on a certain resource, like database, or for jobs where you use Jenkins - as a cron replacement. - -

- If you use a custom workspace and enable this option, all your builds will run on the same workspace, - thus unless a care is taken by your side, it'll likely to collide with each other. - Otherwise, even when they are run on the same node, Jenkins will use different workspaces to keep - them isolated. - -

- When Jenkins creates different workspaces for isolation, Jenkins appends "@num" to the - workspace directory name, e.g. "@2". The separator "@" can be configured by setting the system property - "hudson.slaves.WorkspaceList" to the desired separator string on the Jenkins command line. - E.g. "-Dhudson.slaves.WorkspaceList=-" will use a dash as separator. + When this option is checked, multiple builds of this project may be executed + in parallel. +

+ By default, only a single build of a project is executed at a time — any + other requests to start building that project will remain in the build queue + until the first build is complete.
+ This is a safe default, as projects can often require exclusive access to + certain resources, such as a database, or a piece of hardware. +

+ But with this option enabled, if there are enough build executors available + that can handle this project, then multiple builds of this project will take + place in parallel. If there are not enough available executors at any point, + any further build requests will be held in the build queue as normal. +

+ Enabling concurrent builds is useful for projects that execute lengthy test + suites, as it allows each build to contain a smaller number of changes, while + the total turnaround time decreases as subsequent builds do not need to wait + for previous test runs to complete.
+ This feature is also useful for parameterised projects, whose individual build + executions — depending on the parameters used — can be + completely independent from one another. +

+ Each concurrently executed build occurs in its own build workspace, isolated + from any other builds. By default, Jenkins appends "@<num>" to + the workspace directory name, e.g. "@2".
+ The separator "@" can be changed by setting the + hudson.slaves.WorkspaceList Java system property when starting + Jenkins. For example, "hudson.slaves.WorkspaceList=-" would change + the separator to a hyphen.
+ For more information on setting system properties, see the wiki page. +

+ However, if you enable the Use custom workspace option, all builds will + be executed in the same workspace. Therefore caution is required, as multiple + builds may end up altering the same directory at the same time.

diff --git a/core/src/main/resources/hudson/model/AbstractProject/help-label.html b/core/src/main/resources/hudson/model/AbstractProject/help-label.html index 5932919ea2..df1b6a104a 100644 --- a/core/src/main/resources/hudson/model/AbstractProject/help-label.html +++ b/core/src/main/resources/hudson/model/AbstractProject/help-label.html @@ -1,52 +1,128 @@
- If you want to always run this project on a specific agent, just specify its name. - This works well when you have a small number of nodes. + Defines a logical expression which determines which agents may execute builds + of this project. This expression, when tested against the name and labels of + each available agent, will be either true or false. If the + expression evaluates to true, then that agent will be allowed to + execute builds of this project. +

+ If this project should always be built on a specific agent, or on the Jenkins + master, then you can just enter the agent's name, or master, + respectively. +

+ However, you should generally avoid using the Name of an agent here, + preferring to target the Labels of an agent. As documented on the + configuration page for each agent, and the Configure System page for + the master, labels can be used to represent which operating system the agent + is running on, its CPU architecture, or any number of other characteristics. +
+ Using labels removes the need to re-configure the label expression entered + here each time that you add, remove, or rename agents. +

+ A label expression can be as simple as entering a single label or + agent name, for example android-builder, or + linux-machine-42.
+ You can also make use of various operators to create more complex + expressions. -

- As the size of the cluster grows, it becomes useful not to tie projects to specific agents, - as it hurts resource utilization when agents may come and go. For such situation, assign labels - to agents to classify their capabilities and characteristics, and specify a boolean expression - over those labels to decide where to run. +

Supported operators

+ The following operators are supported, in descending order of precedence: +
+
(expression)
+
+ parentheses — used to explicitly define the associativity of an expression +
-

Valid Operators

-

- The following operators are supported, in the order of precedence. -

-
(expr)
-
parenthesis
+
!expression
+
+ NOT — negation; the result of expression must not be true +
-
!expr
-
negation
+
a && b
+
+ AND — both of the expressions a and b must be + true +
-
expr&&expr
-
- and -
+
a || b
+
+ OR — either of the expressions a or b may be + true +
-
expr||expr
-
- or -
+
a -> b
+
+ "implies" operator — equivalent to !a || b.
+ For example, windows -> x64 could be thought of as "if a Windows + agent is used, then that agent must be 64-bit", while still + allowing this project to be executed on any agents that do not have + the windows label, regardless of whether they have also have an + x64 label +
-
a -> b
-
- "implies" operator. Equivalent to !a|b. - For example, windows->x64 could be thought of as "if run on a Windows agent, - that agent must be 64bit." It still allows Jenkins to run this build on linux. -
+
a <-> b
+
+ "if and only if" operator — equivalent to a && b || + !a && !b
+ For example, windows <-> dc2 could be thought of as "if a + Windows agent is used, then that agent must be in datacenter 2, but + if a non-Windows agent is used, then it must not be in datacenter + 2" +
+
-
a <-> b
-
- "if and only if" operator. Equivalent to a&&b || !a&&!b. - For example, windows<->sfbay could be thought of as "if run on a Windows agent, - that agent must be in the SF bay area, but if not on Windows, it must not be in the bay area." -
-
-

- All operators are left-associative (i.e., a->b->c <-> (a->b)->c ) - An expression can contain whitespace for better readability, and it'll be ignored. +

Notes

+ -

- Label names or agent names can be quoted if they contain unsafe characters. For example, - "jenkins-solaris (Solaris)" || "Windows 2008" +

Examples

+
+
master
+
Builds of this project may be executed only on the Jenkins master
+ +
linux-machine-42
+
+ Builds of this project may be executed only on the agent with the name + linux-machine-42 (or on any machine that happens to have a label + called linux-machine-42) +
+ +
windows && jdk9
+
+ Builds of this project may be executed only on any Windows agent that has + version 9 of the Java Development Kit installed (assuming that agents + with JDK 9 installed have been given a jdk9 label) +
+ +
postgres && !vm && (linux || freebsd)
+
+ Builds of this project may be executed only any on Linux or FreeBSD agent, + so long as they are not a virtual machine, and they have PostgreSQL + installed (assuming that each agent has the appropriate labels — in + particular, each agent running in a virtual machine must have the + vm label in order for this example to work as expected) +
+ +
diff --git a/core/src/main/resources/hudson/model/AllView/noJob.jelly b/core/src/main/resources/hudson/model/AllView/noJob.jelly index 5a74697978..0c9e0c26a9 100644 --- a/core/src/main/resources/hudson/model/AllView/noJob.jelly +++ b/core/src/main/resources/hudson/model/AllView/noJob.jelly @@ -32,7 +32,7 @@ THE SOFTWARE. - +
${%newJob}
diff --git a/core/src/main/resources/hudson/model/ComputerSet/index.jelly b/core/src/main/resources/hudson/model/ComputerSet/index.jelly index 421865bd2c..22a8f39e34 100644 --- a/core/src/main/resources/hudson/model/ComputerSet/index.jelly +++ b/core/src/main/resources/hudson/model/ComputerSet/index.jelly @@ -68,7 +68,7 @@ THE SOFTWARE. - + diff --git a/core/src/main/resources/hudson/model/ComputerSet/sidepanel.jelly b/core/src/main/resources/hudson/model/ComputerSet/sidepanel.jelly index 831ca12d7e..59973506f5 100644 --- a/core/src/main/resources/hudson/model/ComputerSet/sidepanel.jelly +++ b/core/src/main/resources/hudson/model/ComputerSet/sidepanel.jelly @@ -32,9 +32,9 @@ THE SOFTWARE. - + - + diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail.jelly b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail.jelly index 583f693ef4..f720e3e513 100644 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail.jelly +++ b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail.jelly @@ -24,5 +24,5 @@ THE SOFTWARE.
- ${%body} + ${it.description}
\ No newline at end of file diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail.properties deleted file mode 100644 index bc37f9ffb7..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail.properties +++ /dev/null @@ -1,26 +0,0 @@ -# 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 -# 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. - -body=\ - This is the central feature of Jenkins. Jenkins will build your project, \ - combining any SCM with any build system, and this can be even used \ - for something other than software build. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ar.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ar.properties deleted file mode 100644 index 8d8fada25e..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ar.properties +++ /dev/null @@ -1,3 +0,0 @@ -# This file is under the MIT License by authors - -body=\u0647\u0630\u0647 \u0647\u064A \u0627\u0644\u0645\u064A\u0632\u0629 \u0627\u0644\u0631\u0626\u064A\u0633\u064A\u0629 \u0641\u064A \u062C\u0646\u0643\u0646\u0632. \u062C\u0646\u0643\u0646\u0632 \u0633\u064A\u0628\u0646\u064A \u0644\u0643 \u0645\u0634\u0631\u0648\u0639\u0643\u060C \u064A\u0633\u062A\u062E\u062F\u0645 \u0623\u062F\u0648\u0627\u062A \u0645\u0631\u0627\u0642\u0628\u0629 \u0627\u0644\u0645\u0635\u062F\u0631 \u0627\u0644\u0628\u0631\u0645\u062C\u064A\u060C \u0648\u064A\u0645\u0643\u0646 \u062D\u062A\u0649 \u0627\u0633\u062A\u062E\u062F\u0627\u0645\u0647\u0627 \uFEF7\u0634\u064A\u0627\u0621 \u063A\u064A\u0631 \u0628\u0646\u0627\u0621 \u0627\u0644\u0645\u0634\u0631\u0648\u0639. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_bg.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_bg.properties deleted file mode 100644 index 6ea50ab22d..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_bg.properties +++ /dev/null @@ -1,3 +0,0 @@ -# This file is under the MIT License by authors - -body=\u0422\u043E\u0432\u0430 \u0435 \u043E\u0441\u043D\u043E\u0432\u043D\u0430 \u0444\u0443\u043D\u043A\u0446\u0438\u043E\u043D\u0430\u043B\u043D\u043E\u0441\u0442 \u0432 Jenkins. Jenkins \u043C\u043E\u0436\u0435 \u0434\u0430 \u0431\u0438\u043B\u0434\u043D\u0435 \u0432\u0430\u0448 \u043F\u0440\u043E\u0435\u043A\u0442 \u043A\u043E\u043C\u0431\u0438\u043D\u0438\u0440\u0430\u0439\u043A\u0438 \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u0435\u043D \u0441\u043E\u0440\u0441 \u043A\u043E\u043D\u0442\u0440\u043E\u043B \u0441 \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u043D\u0430 \u0431\u0438\u043B\u0434 \u0441\u0438\u0441\u0442\u0435\u043C\u0430, \u043A\u0430\u0442\u043E \u043C\u043E\u0436\u0435\u0442\u0435 \u0434\u043E\u0440\u0438 \u0434\u0430 \u0433\u043E \u043F\u043E\u043B\u0437\u0432\u0430\u0442\u0435 \u0438 \u0437\u0430 \u0434\u0440\u0443\u0433\u0438 \u0446\u0435\u043B\u0438 \u0440\u0430\u0437\u043B\u0438\u0447\u043D\u0438 \u043E\u0442 \u0431\u0438\u043B\u0434\u0432\u0430\u043D\u0435 \u043D\u0430 \u0441\u043E\u0444\u0442\u0443\u0435\u0440. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ca.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ca.properties deleted file mode 100644 index 0b991b6b82..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ca.properties +++ /dev/null @@ -1,3 +0,0 @@ -# This file is under the MIT License by authors - -body=Aquesta \u00E9s la funcionalitat principal de Jenkins. Jenkins far\u00E0 un build del vostre projecte combinant qualsevol SCM amb qualsevol sistema de build. Aix\u00F2 tamb\u00E9 es pot usar per tasques que no siguin un build de software diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_cs.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_cs.properties deleted file mode 100644 index 15a4df88a9..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_cs.properties +++ /dev/null @@ -1,3 +0,0 @@ -# This file is under the MIT License by authors - -body=Toto je hlavn\u00ED funkce Jenkins. Jenkins sestav\u00ED v\u00E1\u0161 projekt, spoj\u00ED jak\u00FDkoli syst\u00E9m pro spr\u00E1vu verz\u00ED se syst\u00E9mem pro sestaven\u00ED. Nemus\u00ED b\u00FDt pou\u017Eit jen pro sestaven\u00ED softwaru. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_da.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_da.properties deleted file mode 100644 index b4febcef13..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_da.properties +++ /dev/null @@ -1,23 +0,0 @@ -# The MIT License -# -# Copyright (c) 2004-2010, Sun Microsystems, Inc. Kohsuke Kawaguchi. Knud Poulsen. -# -# 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. - -body=Dette er den centrale feature i Jenkins. Jenkins vil bygge dit projekt i enhver kombination af kildekodestyring (SCM) med ethvert byggesystem og dette kan bruges til meget andet end at bygge software. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_de.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_de.properties deleted file mode 100644 index 7ba8a96e3c..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_de.properties +++ /dev/null @@ -1,27 +0,0 @@ -# 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 -# 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. - -body=\ - Dieses Profil ist das meistgenutzte in Jenkins. Jenkins baut Ihr Projekt, wobei Sie \ - universell jedes SCM System mit jedem Build-Verfahren kombinieren können. Dieses Profil \ - ist nicht nur auf das Bauen von Software beschränkt, sondern kann darüber hinaus \ - auch für weitere Anwendungsgebiete verwendet werden. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_es.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_es.properties deleted file mode 100644 index ec45052877..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_es.properties +++ /dev/null @@ -1,27 +0,0 @@ -# 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 -# 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. - -body=\ - Esta es la característica principal de Jenkins, la de ejecutar el proyecto combinando cualquier tipo \ - de repositorio de software (SCM) con cualquier modo de construccion o ejecución (make, ant, mvn, rake, script ...). \ - Por tanto se podrá tanto compilar y empaquetar software, como ejecutar cualquier proceso que requiera monitorización. - diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_et.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_et.properties deleted file mode 100644 index c3c69a972c..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_et.properties +++ /dev/null @@ -1,3 +0,0 @@ -# This file is under the MIT License by authors - -body=See on Jenkinsi p\u00F5hifunktsioon! Jenkins ehitab su projekti, kombineerides sinu versioonihalduse mistahes ehitusprotsessiga. Sa v\u00F5id seda kasutada ka muudeks asjadeks kui tarkvara ehitamine. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_fi.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_fi.properties deleted file mode 100644 index aca64302b7..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_fi.properties +++ /dev/null @@ -1,3 +0,0 @@ -# This file is under the MIT License by authors - -body=T\u00E4m\u00E4 on Jenkins t\u00E4rkein ominaisuus. Jenkins rakentaa projektisi k\u00E4ytt\u00E4en versionhallintaa ja buildij\u00E4rjestelmi\u00E4. Voit k\u00E4ytt\u00E4\u00E4 t\u00E4t\u00E4 my\u00F6s muuhun kuin ohjelmien k\u00E4\u00E4nt\u00E4miseen. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_fr.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_fr.properties deleted file mode 100644 index 441d616f50..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_fr.properties +++ /dev/null @@ -1,23 +0,0 @@ -# The MIT License -# -# Copyright (c) 2004-2009, 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 -# 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. - -body=Ceci est la fonction principale de Jenkins qui sert \u00E0 builder (construire) votre projet.
Vous pouvez int\u00E9grer tous les outils de gestion de version avec tous les syst\u00E8mes de build.
Il est m\u00EAme possible d''utiliser Jenkins pour tout autre chose qu''un build logiciel. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_hi_IN.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_hi_IN.properties deleted file mode 100644 index f83456bd02..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_hi_IN.properties +++ /dev/null @@ -1,3 +0,0 @@ -# This file is under the MIT License by authors - -body=\u092F\u0939 \u091C\u0947\u0928\u0915\u0940\u0902\u0938 \u0915\u0940 \u0915\u0947\u0902\u0926\u094D\u0930\u0940\u092F \u0935\u093F\u0936\u0947\u0937\u0924\u093E \u0939\u0948\u0964 \u091C\u0947\u0928\u0915\u0940\u0902\u0938, \u0915\u093F\u0938\u0940 \u092D\u0940 \u0928\u093F\u0930\u094D\u092E\u093E\u0923 \u092A\u094D\u0930\u0923\u093E\u0932\u0940 \u0915\u0947 \u0938\u093E\u0925 \u0915\u093F\u0938\u0940 \u092D\u0940 \u0938\u0949\u092B\u094D\u091F\u0935\u0947\u092F\u0930 \u0935\u093F\u0928\u094D\u092F\u093E\u0938 \u092A\u094D\u0930\u092C\u0902\u0927\u0928 \u0915\u093E \u0938\u0902\u092F\u094B\u091C\u0928 \u0915\u0930\u0915\u0947 \u0906\u092A\u0915\u0940 \u092A\u0930\u093F\u092F\u094B\u091C\u0928\u093E \u0915\u093E \u0928\u093F\u0930\u094D\u092E\u093E\u0923 \u0915\u0930\u0947\u0917\u093E, \u0914\u0930 \u0907\u0938\u0915\u093E \u092A\u094D\u0930\u092F\u094B\u0917 \u0938\u0949\u092B\u094D\u091F\u0935\u0947\u092F\u0930 \u0915\u093E \u0928\u093F\u0930\u094D\u092E\u093E\u0923 \u0915\u0930\u0928\u0947 \u0915\u0947 \u0905\u0932\u093E\u0935\u093E \u0905\u0928\u094D\u092F \u0915\u093E\u0930\u094D\u092F\u094B\u0902 \u0915\u0947 \u0932\u093F\u090F \u092D\u0940 \u0915\u093F\u092F\u093E \u091C\u093E \u0938\u0915\u0924\u093E \u0939\u0948. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_id.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_id.properties deleted file mode 100644 index 0bd7d5726c..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_id.properties +++ /dev/null @@ -1,3 +0,0 @@ -# This file is under the MIT License by authors - -body=Ini adalah fitur sentral dari Jenkins. Jenkins akan membangun proyek anda, mengkombinasikan SCM apa pun dengan sistem pembangunan, dan ini akan digunakan untuk sesuatu selain pembangunan piranti lunak. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ja.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ja.properties deleted file mode 100644 index 35598f0d33..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ja.properties +++ /dev/null @@ -1,26 +0,0 @@ -# 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 -# 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. - -body=\ - \u3082\u3063\u3068\u3082\u6c4e\u7528\u6027\u306e\u9ad8\u3044Jenkins\u306e\u4e2d\u6838\u6a5f\u80fd\u3067\u3059\u3002\u4efb\u610f\u306eSCM\u304b\u3089\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9\u3092\u30c1\u30a7\u30c3\u30af\u30a2\u30a6\u30c8\u3057\u3001\ - \u4efb\u610f\u306e\u30d3\u30eb\u30c9\u30b7\u30b9\u30c6\u30e0\u3067\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u304c\u30d3\u30eb\u30c9\u3067\u304d\u307e\u3059\u3002\u5f80\u3005\u306b\u3057\u3066\u3001\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u306e\u30d3\u30eb\u30c9\u4ee5\u5916\u306b\u3082\ - \u69d8\u3005\u306a\u4ed5\u4e8b\u306e\u81ea\u52d5\u5316\u306b\u5229\u7528\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ko.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ko.properties deleted file mode 100644 index e75ffeb39a..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ko.properties +++ /dev/null @@ -1,23 +0,0 @@ -# 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. - -body=\uC774\uAC83\uC740 Jenkins\uC758 \uC8FC\uC694 \uAE30\uB2A5\uC785\uB2C8\uB2E4. Jenkins\uC740 \uC5B4\uB290 \uBE4C\uB4DC \uC2DC\uC2A4\uD15C\uACFC \uC5B4\uB5A4 SCM(\uD615\uC0C1\uAD00\uB9AC)\uC73C\uB85C \uBB36\uC778 \uB2F9\uC2E0\uC758 \uD504\uB85C\uC81D\uD2B8\uB97C \uBE4C\uB4DC\uD560 \uAC83\uC774\uACE0, \uC18C\uD504\uD2B8\uC6E8\uC5B4 \uBE4C\uB4DC\uBCF4\uB2E4 \uB2E4\uB978 \uC5B4\uB5A4 \uAC83\uC5D0 \uC790\uC8FC \uC0AC\uC6A9\uB420 \uC218 \uC788\uC2B5\uB2C8\uB2E4. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_lt.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_lt.properties deleted file mode 100644 index 60ae6f7c9d..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_lt.properties +++ /dev/null @@ -1,3 +0,0 @@ -# This file is under the MIT License by authors - -body=Pagrindin\u0117 Jenkins funkcija. Jenkins sukonstruos j\u016Bs\u0173 projekt\u0105, sujungdamas betkok\u012F SCM su betkokia konstravimo sistema. \u0160is darbo tipas gali b\u016Bt pritaikytas ne tik program\u0173 konstravimui. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_nb_NO.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_nb_NO.properties deleted file mode 100644 index 1d8c467e71..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_nb_NO.properties +++ /dev/null @@ -1,23 +0,0 @@ -# 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. - -body=Dette er en sentral egenskap ved Jenkins. Jenkins bygger dine prosjekter, kombinerer SCM (Source Control Management - Kildekodekontrollsystem ) med forskjellige byggsystemer og denne kan ogs\u00E5 brukes til mer enn bare \u00E5 bygge applikasjoner. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_nl.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_nl.properties deleted file mode 100644 index 7d46644c79..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_nl.properties +++ /dev/null @@ -1,23 +0,0 @@ -# The MIT License -# -# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, id:sorokh -# -# 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. - -body=Dit is de basisfunctionaliteit van Jenkins. Bij dit type project kun je gebruik maken van een willekeurige combinatie van versiebeheer- en bouwsysteem. Je zou Jenkins zelfs kunnen gebruiken voor andere zaken dan het bouwen van software. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_pl.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_pl.properties deleted file mode 100644 index 2e8e7fa70d..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_pl.properties +++ /dev/null @@ -1,23 +0,0 @@ -# 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. - -body=To jest podstawowa funkcja Jenkinsa. Jenkins stworzy projekt \u0142\u0105cz\u0105cy dowolny SCM z dowolnym systemem buduj\u0105cym, mo\u017Ce to by\u0107 r\u00F3wnie\u017C wykorzystane do czego\u015B innego ni\u017C budowanie oprogramowania. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_pt_BR.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_pt_BR.properties deleted file mode 100644 index c02b59dfae..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_pt_BR.properties +++ /dev/null @@ -1,24 +0,0 @@ -# The MIT License -# -# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Reginaldo L. Russinholi, Cleiber Silva, Fernando Boaglio -# -# 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. - -body=Esta \u00e9 a central de funcionalidades do Jenkins. Ele construir\u00e1 seu projeto,e voc\u00ea pode combinar qualquer SCM com qualquer sistema de builds, e ele at\u00e9 mesmo pode ser usado para outras jobs diferentes de builds de software. - diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_pt_PT.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_pt_PT.properties deleted file mode 100644 index 769ad93de7..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_pt_PT.properties +++ /dev/null @@ -1,3 +0,0 @@ -# This file is under the MIT License by authors - -body=Isto \u00E9 uma caracter\u00EDstica central do Jenkins. Jenkins vai construir o seu projecto, combinando qualquer SCM com qualquer sistema de compila\u00E7\u00E3o e isto pode ser usado mesmo em qualquer outra compila\u00E7\u00E3o de software. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ro.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ro.properties deleted file mode 100644 index b9a2e8fb70..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ro.properties +++ /dev/null @@ -1,3 +0,0 @@ -# This file is under the MIT License by authors - -body=Aceasta este func\u021Bionalitatea principal\u0103 a lui Jenkins. Jenkins va construi proiectul dvs, combin\u00E2nd orice SCM cu orice sistem de build-uri, \u0219i aceasta poate fi folosit\u0103 chiar \u0219i la altceva dec\u00E2t build-uri de aplica\u021Bii. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ru.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ru.properties deleted file mode 100644 index 18216dc92a..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_ru.properties +++ /dev/null @@ -1,25 +0,0 @@ -# The MIT License -# -# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Mike Salnikov -# -# 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. - -body=\u042d\u0442\u043e - \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0438 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u0438\u043f \u0437\u0430\u0434\u0430\u0447 \u0432 Jenkins. \ - Jenkins \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0432\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442, \u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u0443\u044f \u043b\u044e\u0431\u0443\u044e SCM \u0441 \u043b\u044e\u0431\u043e\u0439 \u0441\u0431\u043e\u0440\u043e\u0447\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439. \ - \u0414\u0430\u043d\u043d\u044b\u0439 \u0442\u0438\u043f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u0447, \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0445 \u043e\u0442 \u0441\u0431\u043e\u0440\u043a\u0438 \u041f\u041e. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_sv_SE.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_sv_SE.properties deleted file mode 100644 index a1827f1712..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_sv_SE.properties +++ /dev/null @@ -1,23 +0,0 @@ -# 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. - -body=Detta \u00E4r en central del i Jenkins. Jenkins kommer att bygga ditt projekt med valfri versionshanterare och med vilket byggsystem som helst, och detta kan \u00E4ven anv\u00E4ndas f\u00F6r n\u00E5got annat \u00E4n mjukvarubyggen. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_tr.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_tr.properties deleted file mode 100644 index ad96ac4f59..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_tr.properties +++ /dev/null @@ -1,26 +0,0 @@ -# The MIT License -# -# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Oguz Dag -# -# 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. - -body=\ - Jenkins''\u0131n merkezi \u00f6zelli\u011fi, projelerinizi yap\u0131land\u0131rman\u0131za yard\u0131m etmesidir. Bu proje t\u00fcr\u00fcn\u00fc kullanarak, \ - herhangi bir yap\u0131land\u0131rma sistemini herhangi bir Kaynak Kodu Y\u00f6netimi arac\u0131 ile birle\u015ftirebilirsiniz,\ - ve hatta yaz\u0131l\u0131m yap\u0131land\u0131rman\u0131n d\u0131\u015f\u0131nda ba\u015fka t\u00fcr projeler i\u00e7in dahi kullanabilirsiniz. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_uk.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_uk.properties deleted file mode 100644 index 96cf935804..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_uk.properties +++ /dev/null @@ -1,3 +0,0 @@ -# This file is under the MIT License by authors - -body=\u0426\u0435 - \u043E\u0441\u043D\u043E\u0432\u043D\u0430 \u0432\u0456\u0434\u043C\u0456\u043D\u043D\u0456\u0441\u0442\u044C Jenkins. Jenkins \u043F\u043E\u0431\u0443\u0434\u0443\u0454 \u0432\u0430\u0448 \u043F\u0440\u043E\u0435\u043A\u0442, \u043A\u043E\u043C\u0431\u0456\u043D\u0443\u044E\u0447\u0438 \u0431\u0443\u0434\u044C-\u044F\u043A\u0456 \u0441\u0438\u0441\u0442\u0435\u043C\u0438 \u0443\u043F\u0440\u0430\u0432\u043B\u0456\u043D\u043D\u044F \u043A\u043E\u0434\u043E\u043C \u0437 \u0431\u0443\u0434\u044C-\u044F\u043A\u0438\u043C\u0438 \u0441\u0438\u0441\u0442\u0435\u043C\u0430\u043C\u0438 \u0437\u0431\u0456\u0440\u043A\u0438, \u0449\u043E \u043C\u043E\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u043D\u043E \u043D\u0430\u0432\u0456\u0442\u044C \u0434\u043B\u044F \u0446\u0456\u043B\u0435\u0439 \u0432\u0456\u0434\u043C\u0456\u043D\u043D\u0438\u0445 \u0432\u0456\u0434 \u0437\u0431\u0456\u0440\u043A\u0438 \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043D\u043E\u0433\u043E \u0437\u0430\u0431\u0435\u0437\u043F\u0435\u0447\u0435\u043D\u043D\u044F. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_zh_CN.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_zh_CN.properties deleted file mode 100644 index 745188fb5c..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_zh_CN.properties +++ /dev/null @@ -1,23 +0,0 @@ -# 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 -# 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. - -body=\u8FD9\u662FJenkins\u7684\u4E3B\u8981\u529F\u80FD.Jenkins\u5C06\u4F1A\u7ED3\u5408\u4EFB\u4F55SCM\u548C\u4EFB\u4F55\u6784\u5EFA\u7CFB\u7EDF\u6765\u6784\u5EFA\u4F60\u7684\u9879\u76EE, \u751A\u81F3\u53EF\u4EE5\u6784\u5EFA\u8F6F\u4EF6\u4EE5\u5916\u7684\u7CFB\u7EDF. diff --git a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_zh_TW.properties b/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_zh_TW.properties deleted file mode 100644 index 9f8acc78f3..0000000000 --- a/core/src/main/resources/hudson/model/FreeStyleProject/newJobDetail_zh_TW.properties +++ /dev/null @@ -1,27 +0,0 @@ -# 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. - -body=\ - \u9019\u662f Jenkins \u7684\u4e3b\u8981\u529f\u80fd\u3002\ - Jenkins \u80fd\u642d\u914d\u5404\u5f0f\u7a0b\u5f0f\u78bc\u7ba1\u7406\u3001\u5efa\u7f6e\u7cfb\u7d71\u4f86\u5efa\u7f6e\u60a8\u7684\u5c08\u6848\uff0c\ - \u751a\u81f3\u9084\u80fd\u505a\u8edf\u9ad4\u5efa\u7f6e\u4ee5\u5916\u7684\u5176\u4ed6\u4e8b\u60c5\u3002 diff --git a/core/src/main/resources/hudson/model/Job/configure.properties b/core/src/main/resources/hudson/model/Job/configure.properties index 1eef961fb3..ba7d95bb98 100644 --- a/core/src/main/resources/hudson/model/Job/configure.properties +++ b/core/src/main/resources/hudson/model/Job/configure.properties @@ -21,5 +21,5 @@ # THE SOFTWARE. name={0} name -Save=Save All -Apply=Apply All \ No newline at end of file +Save=Save +Apply=Apply \ No newline at end of file diff --git a/core/src/main/resources/hudson/model/Label/sidepanel.jelly b/core/src/main/resources/hudson/model/Label/sidepanel.jelly index 734a5c53dd..7d662a0a45 100644 --- a/core/src/main/resources/hudson/model/Label/sidepanel.jelly +++ b/core/src/main/resources/hudson/model/Label/sidepanel.jelly @@ -34,7 +34,7 @@ THE SOFTWARE. - + diff --git a/core/src/main/resources/hudson/model/Messages.properties b/core/src/main/resources/hudson/model/Messages.properties index c952af5760..32730a733d 100644 --- a/core/src/main/resources/hudson/model/Messages.properties +++ b/core/src/main/resources/hudson/model/Messages.properties @@ -121,6 +121,9 @@ Descriptor.From=(from {0}) Executor.NotAvailable=N/A FreeStyleProject.DisplayName=Freestyle project +FreeStyleProject.Description=\ + This is the central feature of Jenkins. Jenkins will build your project, combining any SCM with any build system, \ + and this can be even used for something other than software build. HealthReport.EmptyString= @@ -319,9 +322,9 @@ Permalink.LastFailedBuild=Last failed build Permalink.LastCompletedBuild=Last completed build ParameterAction.DisplayName=Parameters -ParametersDefinitionProperty.DisplayName=This build is parameterized +ParametersDefinitionProperty.DisplayName=This project is parameterized StringParameterDefinition.DisplayName=String Parameter -TextParameterDefinition.DisplayName=Text Parameter +TextParameterDefinition.DisplayName=Multi-line String Parameter FileParameterDefinition.DisplayName=File Parameter BooleanParameterDefinition.DisplayName=Boolean Parameter ChoiceParameterDefinition.DisplayName=Choice Parameter @@ -333,8 +336,8 @@ Node.BecauseNodeIsReserved={0} is reserved for jobs with matching label expressi Node.BecauseNodeIsNotAcceptingTasks={0} is not accepting tasks Node.LabelMissing={0} doesn\u2019t have label {1} Node.LackingBuildPermission={0} doesn\u2019t have a permission to run on {1} -Node.Mode.NORMAL=Utilize this node as much as possible -Node.Mode.EXCLUSIVE=Only build jobs with label restrictions matching this node +Node.Mode.NORMAL=Use this node as much as possible +Node.Mode.EXCLUSIVE=Only build jobs with label expressions matching this node ListView.DisplayName=List View diff --git a/core/src/main/resources/hudson/model/Messages_ar.properties b/core/src/main/resources/hudson/model/Messages_ar.properties new file mode 100644 index 0000000000..6ff7b6edcf --- /dev/null +++ b/core/src/main/resources/hudson/model/Messages_ar.properties @@ -0,0 +1 @@ +FreeStyleProject.Description=\u0647\u0630\u0647 \u0647\u064A \u0627\u0644\u0645\u064A\u0632\u0629 \u0627\u0644\u0631\u0626\u064A\u0633\u064A\u0629 \u0641\u064A \u062C\u0646\u0643\u0646\u0632. \u062C\u0646\u0643\u0646\u0632 \u0633\u064A\u0628\u0646\u064A \u0644\u0643 \u0645\u0634\u0631\u0648\u0639\u0643\u060C \u064A\u0633\u062A\u062E\u062F\u0645 \u0623\u062F\u0648\u0627\u062A \u0645\u0631\u0627\u0642\u0628\u0629 \u0627\u0644\u0645\u0635\u062F\u0631 \u0627\u0644\u0628\u0631\u0645\u062C\u064A\u060C \u0648\u064A\u0645\u0643\u0646 \u062D\u062A\u0649 \u0627\u0633\u062A\u062E\u062F\u0627\u0645\u0647\u0627 \uFEF7\u0634\u064A\u0627\u0621 \u063A\u064A\u0631 \u0628\u0646\u0627\u0621 \u0627\u0644\u0645\u0634\u0631\u0648\u0639. \ No newline at end of file diff --git a/core/src/main/resources/hudson/model/Messages_bg.properties b/core/src/main/resources/hudson/model/Messages_bg.properties index 160995ca8b..7bfa610ffd 100644 --- a/core/src/main/resources/hudson/model/Messages_bg.properties +++ b/core/src/main/resources/hudson/model/Messages_bg.properties @@ -171,6 +171,8 @@ Executor.NotAvailable=\ FreeStyleProject.DisplayName=\ \u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 +FreeStyleProject.Description=\ + \u0422\u043E\u0432\u0430 \u0435 \u043E\u0441\u043D\u043E\u0432\u043D\u0430 \u0444\u0443\u043D\u043A\u0446\u0438\u043E\u043D\u0430\u043B\u043D\u043E\u0441\u0442 \u0432 Jenkins. Jenkins \u043C\u043E\u0436\u0435 \u0434\u0430 \u0431\u0438\u043B\u0434\u043D\u0435 \u0432\u0430\u0448 \u043F\u0440\u043E\u0435\u043A\u0442 \u043A\u043E\u043C\u0431\u0438\u043D\u0438\u0440\u0430\u0439\u043A\u0438 \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u0435\u043D \u0441\u043E\u0440\u0441 \u043A\u043E\u043D\u0442\u0440\u043E\u043B \u0441 \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u043D\u0430 \u0431\u0438\u043B\u0434 \u0441\u0438\u0441\u0442\u0435\u043C\u0430, \u043A\u0430\u0442\u043E \u043C\u043E\u0436\u0435\u0442\u0435 \u0434\u043E\u0440\u0438 \u0434\u0430 \u0433\u043E \u043F\u043E\u043B\u0437\u0432\u0430\u0442\u0435 \u0438 \u0437\u0430 \u0434\u0440\u0443\u0433\u0438 \u0446\u0435\u043B\u0438 \u0440\u0430\u0437\u043B\u0438\u0447\u043D\u0438 \u043E\u0442 \u0431\u0438\u043B\u0434\u0432\u0430\u043D\u0435 \u043D\u0430 \u0441\u043E\u0444\u0442\u0443\u0435\u0440. HealthReport.EmptyString= diff --git a/core/src/main/resources/hudson/model/Messages_ca.properties b/core/src/main/resources/hudson/model/Messages_ca.properties index 2237bbee1d..0a5f3a512e 100644 --- a/core/src/main/resources/hudson/model/Messages_ca.properties +++ b/core/src/main/resources/hudson/model/Messages_ca.properties @@ -1 +1,3 @@ ManageJenkinsAction.DisplayName=Configuraci\u00F3 de Jenkins + +FreeStyleProject.Description=Aquesta \u00E9s la funcionalitat principal de Jenkins. Jenkins far\u00E0 un build del vostre projecte combinant qualsevol SCM amb qualsevol sistema de build. Aix\u00F2 tamb\u00E9 es pot usar per tasques que no siguin un build de software diff --git a/core/src/main/resources/hudson/model/Messages_cs.properties b/core/src/main/resources/hudson/model/Messages_cs.properties index c294dbd242..11de8e6c7a 100644 --- a/core/src/main/resources/hudson/model/Messages_cs.properties +++ b/core/src/main/resources/hudson/model/Messages_cs.properties @@ -1 +1,3 @@ ManageJenkinsAction.DisplayName=Administrace + +FreeStyleProject.Description=Toto je hlavn\u00ED funkce Jenkins. Jenkins sestav\u00ED v\u00E1\u0161 projekt, spoj\u00ED jak\u00FDkoli syst\u00E9m pro spr\u00E1vu verz\u00ED se syst\u00E9mem pro sestaven\u00ED. Nemus\u00ED b\u00FDt pou\u017Eit jen pro sestaven\u00ED softwaru. \ No newline at end of file diff --git a/core/src/main/resources/hudson/model/Messages_da.properties b/core/src/main/resources/hudson/model/Messages_da.properties index 7787a8a44c..427ba244f1 100644 --- a/core/src/main/resources/hudson/model/Messages_da.properties +++ b/core/src/main/resources/hudson/model/Messages_da.properties @@ -59,7 +59,10 @@ Run.DeletePermission.Description=Denne tilladelse g\u00f8r det muligt for bruger Run.Summary.BrokenForALongTime=fejlet l\u00e6nge CLI.safe-restart.shortDescription=Sikker genstart af Jenkins CLI.quiet-down.shortDescription=Forbereder nedlukning, starter ingen nye byg. + FreeStyleProject.DisplayName=Byg et free-style projekt +FreeStyleProject.Description=Dette er den centrale feature i Jenkins. Jenkins vil bygge dit projekt i enhver kombination af kildekodestyring (SCM) med ethvert byggesystem og dette kan bruges til meget andet end at bygge software. + ProxyView.DisplayName=Inkluder en global visning Run.Permissions.Title=K\u00f8r Hudson.DisplayName=Jenkins diff --git a/core/src/main/resources/hudson/model/Messages_de.properties b/core/src/main/resources/hudson/model/Messages_de.properties index e7e002b2ff..21e7988d2c 100644 --- a/core/src/main/resources/hudson/model/Messages_de.properties +++ b/core/src/main/resources/hudson/model/Messages_de.properties @@ -92,6 +92,7 @@ Executor.NotAvailable=nicht verf\u00fcgbar FreeStyleProject.DisplayName="Free Style"-Softwareprojekt bauen +FreeStyleProject.Description=Dieses Profil ist das meistgenutzte in Jenkins. Jenkins baut Ihr Projekt, wobei Sie universell jedes SCM System mit jedem Build-Verfahren kombinieren k\u00F6nnen. Dieses Profil ist nicht nur auf das Bauen von Software beschr\u00E4nkt, sondern kann dar\u00FCber hinaus auch f\u00FCr weitere Anwendungsgebiete verwendet werden. HealthReport.EmptyString= diff --git a/core/src/main/resources/hudson/model/Messages_en_GB.properties b/core/src/main/resources/hudson/model/Messages_en_GB.properties index 9e18978be2..b9d3954d76 100644 --- a/core/src/main/resources/hudson/model/Messages_en_GB.properties +++ b/core/src/main/resources/hudson/model/Messages_en_GB.properties @@ -1 +1 @@ -ParametersDefinitionProperty.DisplayName=This build is parameterised +ParametersDefinitionProperty.DisplayName=This project is parameterised diff --git a/core/src/main/resources/hudson/model/Messages_es.properties b/core/src/main/resources/hudson/model/Messages_es.properties index 0fcdb186d2..29feb6dbeb 100644 --- a/core/src/main/resources/hudson/model/Messages_es.properties +++ b/core/src/main/resources/hudson/model/Messages_es.properties @@ -74,7 +74,7 @@ Executor.NotAvailable=N/D FreeStyleProject.DisplayName=Crear un proyecto de estilo libre - +FreeStyleProject.Description=Esta es la caracter\u00EDstica principal de Jenkins, la de ejecutar el proyecto combinando cualquier tipo de repositorio de software (SCM) con cualquier modo de construcci\u00F3n o ejecuci\u00F3n (make, ant, mvn, rake, script ...). Por tanto se podr\u00E1 tanto compilar y empaquetar software, como ejecutar cualquier proceso que requiera monitorizaci\u00F3n. Hudson.BadPortNumber=N\u00famero err\u00f3neo de puerto {0} Hudson.Computer.Caption=Principal diff --git a/core/src/main/resources/hudson/model/Messages_et.properties b/core/src/main/resources/hudson/model/Messages_et.properties new file mode 100644 index 0000000000..ff3d7fc8bd --- /dev/null +++ b/core/src/main/resources/hudson/model/Messages_et.properties @@ -0,0 +1 @@ +FreeStyleProject.Description=See on Jenkinsi p\u00F5hifunktsioon! Jenkins ehitab su projekti, kombineerides sinu versioonihalduse mistahes ehitusprotsessiga. Sa v\u00F5id seda kasutada ka muudeks asjadeks kui tarkvara ehitamine. \ No newline at end of file diff --git a/core/src/main/resources/hudson/model/Messages_fi.properties b/core/src/main/resources/hudson/model/Messages_fi.properties index b8537b4403..cc62c20834 100644 --- a/core/src/main/resources/hudson/model/Messages_fi.properties +++ b/core/src/main/resources/hudson/model/Messages_fi.properties @@ -1 +1,3 @@ ManageJenkinsAction.DisplayName=Hallitse Jenkinsia + +FreeStyleProject.Description=T\u00E4m\u00E4 on Jenkins t\u00E4rkein ominaisuus. Jenkins rakentaa projektisi k\u00E4ytt\u00E4en versionhallintaa ja buildij\u00E4rjestelmi\u00E4. Voit k\u00E4ytt\u00E4\u00E4 t\u00E4t\u00E4 my\u00F6s muuhun kuin ohjelmien k\u00E4\u00E4nt\u00E4miseen. \ No newline at end of file diff --git a/core/src/main/resources/hudson/model/Messages_fr.properties b/core/src/main/resources/hudson/model/Messages_fr.properties index a5935b27ff..f9d5295135 100644 --- a/core/src/main/resources/hudson/model/Messages_fr.properties +++ b/core/src/main/resources/hudson/model/Messages_fr.properties @@ -55,6 +55,7 @@ Executor.NotAvailable=N/A FreeStyleProject.DisplayName=Construire un projet free-style +FreeStyleProject.Description=Ceci est la fonction principale de Jenkins qui sert \u00E0 builder (construire) votre projet.
Vous pouvez int\u00E9grer tous les outils de gestion de version avec tous les syst\u00E8mes de build.
Il est m\u00EAme possible d''utiliser Jenkins pour tout autre chose qu''un build logiciel. Hudson.BadPortNumber=Num\u00e9ro de port incorrect {0} Hudson.Computer.Caption=Ma\u00eetre diff --git a/core/src/main/resources/hudson/model/Messages_hi_IN.properties b/core/src/main/resources/hudson/model/Messages_hi_IN.properties new file mode 100644 index 0000000000..58a16a05dd --- /dev/null +++ b/core/src/main/resources/hudson/model/Messages_hi_IN.properties @@ -0,0 +1 @@ +FreeStyleProject.Description=\u092F\u0939 \u091C\u0947\u0928\u0915\u0940\u0902\u0938 \u0915\u0940 \u0915\u0947\u0902\u0926\u094D\u0930\u0940\u092F \u0935\u093F\u0936\u0947\u0937\u0924\u093E \u0939\u0948\u0964 \u091C\u0947\u0928\u0915\u0940\u0902\u0938, \u0915\u093F\u0938\u0940 \u092D\u0940 \u0928\u093F\u0930\u094D\u092E\u093E\u0923 \u092A\u094D\u0930\u0923\u093E\u0932\u0940 \u0915\u0947 \u0938\u093E\u0925 \u0915\u093F\u0938\u0940 \u092D\u0940 \u0938\u0949\u092B\u094D\u091F\u0935\u0947\u092F\u0930 \u0935\u093F\u0928\u094D\u092F\u093E\u0938 \u092A\u094D\u0930\u092C\u0902\u0927\u0928 \u0915\u093E \u0938\u0902\u092F\u094B\u091C\u0928 \u0915\u0930\u0915\u0947 \u0906\u092A\u0915\u0940 \u092A\u0930\u093F\u092F\u094B\u091C\u0928\u093E \u0915\u093E \u0928\u093F\u0930\u094D\u092E\u093E\u0923 \u0915\u0930\u0947\u0917\u093E, \u0914\u0930 \u0907\u0938\u0915\u093E \u092A\u094D\u0930\u092F\u094B\u0917 \u0938\u0949\u092B\u094D\u091F\u0935\u0947\u092F\u0930 \u0915\u093E \u0928\u093F\u0930\u094D\u092E\u093E\u0923 \u0915\u0930\u0928\u0947 \u0915\u0947 \u0905\u0932\u093E\u0935\u093E \u0905\u0928\u094D\u092F \u0915\u093E\u0930\u094D\u092F\u094B\u0902 \u0915\u0947 \u0932\u093F\u090F \u092D\u0940 \u0915\u093F\u092F\u093E \u091C\u093E \u0938\u0915\u0924\u093E \u0939\u0948. diff --git a/core/src/main/resources/hudson/model/Messages_id.properties b/core/src/main/resources/hudson/model/Messages_id.properties new file mode 100644 index 0000000000..fbb242f35c --- /dev/null +++ b/core/src/main/resources/hudson/model/Messages_id.properties @@ -0,0 +1 @@ +FreeStyleProject.Description=Ini adalah fitur sentral dari Jenkins. Jenkins akan membangun proyek anda, mengkombinasikan SCM apa pun dengan sistem pembangunan, dan ini akan digunakan untuk sesuatu selain pembangunan piranti lunak. diff --git a/core/src/main/resources/hudson/model/Messages_it.properties b/core/src/main/resources/hudson/model/Messages_it.properties index 539734bc50..6beced04f0 100644 --- a/core/src/main/resources/hudson/model/Messages_it.properties +++ b/core/src/main/resources/hudson/model/Messages_it.properties @@ -84,6 +84,7 @@ Executor.NotAvailable=N/A FreeStyleProject.DisplayName=Configura una build di tipo generico +FreeStyleProject.Description=Questa \u00E8 la funzione principale di Jenkins. Jenkins effettuer\u00E0 una compilazione del progetto, combinando qualsiasi SCM con qualsiasi sistema di compilazione e si pu\u00F2 usare anche per qualcosa di altro che non sia un programma di compilazione. HealthReport.EmptyString= @@ -242,7 +243,7 @@ Permalink.LastFailedBuild=Last failed build ParameterAction.DisplayName=Parameters StringParameterDefinition.DisplayName=String Parameter -TextParameterDefinition.DisplayName=Text Parameter +TextParameterDefinition.DisplayName=Multi-line String Parameter FileParameterDefinition.DisplayName=File Parameter BooleanParameterDefinition.DisplayName=Boolean Value ChoiceParameterDefinition.DisplayName=Choice diff --git a/core/src/main/resources/hudson/model/Messages_ja.properties b/core/src/main/resources/hudson/model/Messages_ja.properties index aa0f5a1a1e..f36f34306a 100644 --- a/core/src/main/resources/hudson/model/Messages_ja.properties +++ b/core/src/main/resources/hudson/model/Messages_ja.properties @@ -83,6 +83,10 @@ Executor.NotAvailable=N/A FreeStyleProject.DisplayName=\u30d5\u30ea\u30fc\u30b9\u30bf\u30a4\u30eb\u30fb\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u30d3\u30eb\u30c9 +FreeStyleProject.Description=\ + \u3082\u3063\u3068\u3082\u6c4e\u7528\u6027\u306e\u9ad8\u3044Jenkins\u306e\u4e2d\u6838\u6a5f\u80fd\u3067\u3059\u3002\u4efb\u610f\u306eSCM\u304b\u3089\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9\u3092\u30c1\u30a7\u30c3\u30af\u30a2\u30a6\u30c8\u3057\u3001\ + \u4efb\u610f\u306e\u30d3\u30eb\u30c9\u30b7\u30b9\u30c6\u30e0\u3067\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u304c\u30d3\u30eb\u30c9\u3067\u304d\u307e\u3059\u3002\u5f80\u3005\u306b\u3057\u3066\u3001\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u306e\u30d3\u30eb\u30c9\u4ee5\u5916\u306b\u3082\ + \u69d8\u3005\u306a\u4ed5\u4e8b\u306e\u81ea\u52d5\u5316\u306b\u5229\u7528\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 HealthReport.EmptyString= diff --git a/core/src/main/resources/hudson/model/Messages_ko.properties b/core/src/main/resources/hudson/model/Messages_ko.properties index 70020b26be..02b6a1d0ae 100644 --- a/core/src/main/resources/hudson/model/Messages_ko.properties +++ b/core/src/main/resources/hudson/model/Messages_ko.properties @@ -1,2 +1,4 @@ ManageJenkinsAction.DisplayName=Jenkins \uAD00\uB9AC ParametersDefinitionProperty.DisplayName=\uC774 \uBE4C\uB4DC\uB294 \uB9E4\uAC1C\uBCC0\uC218\uAC00 \uC788\uC2B5\uB2C8\uB2E4 + +FreeStyleProject.Description=\uC774\uAC83\uC740 Jenkins\uC758 \uC8FC\uC694 \uAE30\uB2A5\uC785\uB2C8\uB2E4. Jenkins\uC740 \uC5B4\uB290 \uBE4C\uB4DC \uC2DC\uC2A4\uD15C\uACFC \uC5B4\uB5A4 SCM(\uD615\uC0C1\uAD00\uB9AC)\uC73C\uB85C \uBB36\uC778 \uB2F9\uC2E0\uC758 \uD504\uB85C\uC81D\uD2B8\uB97C \uBE4C\uB4DC\uD560 \uAC83\uC774\uACE0, \uC18C\uD504\uD2B8\uC6E8\uC5B4 \uBE4C\uB4DC\uBCF4\uB2E4 \uB2E4\uB978 \uC5B4\uB5A4 \uAC83\uC5D0 \uC790\uC8FC \uC0AC\uC6A9\uB420 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \ No newline at end of file diff --git a/core/src/main/resources/hudson/model/Messages_lt.properties b/core/src/main/resources/hudson/model/Messages_lt.properties index 4dac83724a..f29e8e9d88 100644 --- a/core/src/main/resources/hudson/model/Messages_lt.properties +++ b/core/src/main/resources/hudson/model/Messages_lt.properties @@ -1 +1,3 @@ ParametersDefinitionProperty.DisplayName=\u0160is darbas yra parametrizuotas + +FreeStyleProject.Description=Pagrindin\u0117 Jenkins funkcija. Jenkins sukonstruos j\u016Bs\u0173 projekt\u0105, sujungdamas betkok\u012F SCM su betkokia konstravimo sistema. \u0160is darbo tipas gali b\u016Bt pritaikytas ne tik program\u0173 konstravimui. \ No newline at end of file diff --git a/core/src/main/resources/hudson/model/Messages_nb_NO.properties b/core/src/main/resources/hudson/model/Messages_nb_NO.properties index fe7187183a..d1098629e6 100644 --- a/core/src/main/resources/hudson/model/Messages_nb_NO.properties +++ b/core/src/main/resources/hudson/model/Messages_nb_NO.properties @@ -1,2 +1,4 @@ ManageJenkinsAction.DisplayName=Konfigurer Jenkins ParametersDefinitionProperty.DisplayName=Denne build har parametre + +FreeStyleProject.Description=Dette er en sentral egenskap ved Jenkins. Jenkins bygger dine prosjekter, kombinerer SCM (Source Control Management - Kildekodekontrollsystem ) med forskjellige byggsystemer og denne kan ogs\u00E5 brukes til mer enn bare \u00E5 bygge applikasjoner. diff --git a/core/src/main/resources/hudson/model/Messages_nl.properties b/core/src/main/resources/hudson/model/Messages_nl.properties index d86d111c92..3db4e11f0b 100644 --- a/core/src/main/resources/hudson/model/Messages_nl.properties +++ b/core/src/main/resources/hudson/model/Messages_nl.properties @@ -49,6 +49,7 @@ Executor.NotAvailable=Niet beschikbaar FreeStyleProject.DisplayName=Bouw een vrije stijl type software project +FreeStyleProject.Description=Dit is de basisfunctionaliteit van Jenkins. Bij dit type project kun je gebruik maken van een willekeurige combinatie van versiebeheer- en bouwsysteem. Je zou Jenkins zelfs kunnen gebruiken voor andere zaken dan het bouwen van software. Hudson.BadPortNumber=Verkeerd poortnummer {0} Hudson.Computer.Caption=Hoofdnode diff --git a/core/src/main/resources/hudson/model/Messages_pl.properties b/core/src/main/resources/hudson/model/Messages_pl.properties index 87f49975e9..1ffaf84e4e 100644 --- a/core/src/main/resources/hudson/model/Messages_pl.properties +++ b/core/src/main/resources/hudson/model/Messages_pl.properties @@ -46,3 +46,4 @@ UpdateCenter.Status.Success=Zako\u0144czono pomy\u015Blnie MyViewsProperty.DisplayName=Moje widoki MyViewsProperty.GlobalAction.DisplayName=Moje widoki +FreeStyleProject.Description=To jest podstawowa funkcja Jenkinsa. Jenkins stworzy projekt \u0142\u0105cz\u0105cy dowolny SCM z dowolnym systemem buduj\u0105cym, mo\u017Ce to by\u0107 r\u00F3wnie\u017C wykorzystane do czego\u015B innego ni\u017C budowanie oprogramowania. \ No newline at end of file diff --git a/core/src/main/resources/hudson/model/Messages_pt_BR.properties b/core/src/main/resources/hudson/model/Messages_pt_BR.properties index 6ab7c43fd6..0a3f406e25 100644 --- a/core/src/main/resources/hudson/model/Messages_pt_BR.properties +++ b/core/src/main/resources/hudson/model/Messages_pt_BR.properties @@ -49,6 +49,7 @@ Executor.NotAvailable=N/D FreeStyleProject.DisplayName=Construir um projeto de software free-style +FreeStyleProject.Description=Esta \u00e9 a central de funcionalidades do Jenkins. Ele construir\u00e1 seu projeto,e voc\u00ea pode combinar qualquer SCM com qualquer sistema de builds, e ele at\u00e9 mesmo pode ser usado para outras jobs diferentes de builds de software. Hudson.BadPortNumber=N\u00famero de porta ruim {0} Hudson.Computer.Caption=Master diff --git a/core/src/main/resources/hudson/model/Messages_pt_PT.properties b/core/src/main/resources/hudson/model/Messages_pt_PT.properties index e022d96cef..be8cf4950c 100644 --- a/core/src/main/resources/hudson/model/Messages_pt_PT.properties +++ b/core/src/main/resources/hudson/model/Messages_pt_PT.properties @@ -1 +1,3 @@ ManageJenkinsAction.DisplayName=Gerir o Jenkins + +FreeStyleProject.Description=Isto \u00E9 uma caracter\u00EDstica central do Jenkins. Jenkins vai construir o seu projecto, combinando qualquer SCM com qualquer sistema de compila\u00E7\u00E3o e isto pode ser usado mesmo em qualquer outra compila\u00E7\u00E3o de software. diff --git a/core/src/main/resources/hudson/model/Messages_ro.properties b/core/src/main/resources/hudson/model/Messages_ro.properties index 106056997c..8a8fa99a17 100644 --- a/core/src/main/resources/hudson/model/Messages_ro.properties +++ b/core/src/main/resources/hudson/model/Messages_ro.properties @@ -1 +1,3 @@ ParametersDefinitionProperty.DisplayName=Acest build este parametrizat + +FreeStyleProject.Description=Aceasta este func\u021Bionalitatea principal\u0103 a lui Jenkins. Jenkins va construi proiectul dvs, combin\u00E2nd orice SCM cu orice sistem de build-uri, \u0219i aceasta poate fi folosit\u0103 chiar \u0219i la altceva dec\u00E2t build-uri de aplica\u021Bii. diff --git a/core/src/main/resources/hudson/model/Messages_ru.properties b/core/src/main/resources/hudson/model/Messages_ru.properties index 63e6effcec..2b0130c8fd 100644 --- a/core/src/main/resources/hudson/model/Messages_ru.properties +++ b/core/src/main/resources/hudson/model/Messages_ru.properties @@ -49,6 +49,10 @@ Executor.NotAvailable=\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u04 FreeStyleProject.DisplayName=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u0441\u043e \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 +FreeStyleProject.Description=\ + \u042d\u0442\u043e - \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0438 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u0438\u043f \u0437\u0430\u0434\u0430\u0447 \u0432 Jenkins. \ + Jenkins \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0432\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442, \u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u0443\u044f \u043b\u044e\u0431\u0443\u044e SCM \u0441 \u043b\u044e\u0431\u043e\u0439 \u0441\u0431\u043e\u0440\u043e\u0447\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439. \ + \u0414\u0430\u043d\u043d\u044b\u0439 \u0442\u0438\u043f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u0447, \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0445 \u043e\u0442 \u0441\u0431\u043e\u0440\u043a\u0438 \u041f\u041e. Hudson.BadPortNumber=\u041d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u043f\u043e\u0440\u0442\u0430: {0} Hudson.Computer.Caption=\u041c\u0430\u0441\u0442\u0435\u0440 diff --git a/core/src/main/resources/hudson/model/Messages_sv_SE.properties b/core/src/main/resources/hudson/model/Messages_sv_SE.properties index 278c419304..6376d4e09d 100644 --- a/core/src/main/resources/hudson/model/Messages_sv_SE.properties +++ b/core/src/main/resources/hudson/model/Messages_sv_SE.properties @@ -5,3 +5,5 @@ Job.Pronoun=Projekt ManageJenkinsAction.DisplayName=Hantera Jenkins ParametersDefinitionProperty.DisplayName=Detta bygge \u00E4r parametriserat + +FreeStyleProject.Description=Detta \u00E4r en central del i Jenkins. Jenkins kommer att bygga ditt projekt med valfri versionshanterare och med vilket byggsystem som helst, och detta kan \u00E4ven anv\u00E4ndas f\u00F6r n\u00E5got annat \u00E4n mjukvarubyggen. diff --git a/core/src/main/resources/hudson/model/Messages_tr.properties b/core/src/main/resources/hudson/model/Messages_tr.properties index 72f96af1fa..ee48426b3b 100644 --- a/core/src/main/resources/hudson/model/Messages_tr.properties +++ b/core/src/main/resources/hudson/model/Messages_tr.properties @@ -50,6 +50,11 @@ Executor.NotAvailable=Mevcut De\u011fil FreeStyleProject.DisplayName=Serbest-stil yaz\u0131l\u0131m projesi yap\u0131land\u0131r +FreeStyleProject.Description=\ + Jenkins''\u0131n merkezi \u00f6zelli\u011fi, projelerinizi yap\u0131land\u0131rman\u0131za yard\u0131m etmesidir. Bu proje t\u00fcr\u00fcn\u00fc kullanarak, \ + herhangi bir yap\u0131land\u0131rma sistemini herhangi bir Kaynak Kodu Y\u00f6netimi arac\u0131 ile birle\u015ftirebilirsiniz,\ + ve hatta yaz\u0131l\u0131m yap\u0131land\u0131rman\u0131n d\u0131\u015f\u0131nda ba\u015fka t\u00fcr projeler i\u00e7in dahi kullanabilirsiniz. + Hudson.BadPortNumber=Yanl\u0131\u015f Port Numaras\u0131 {0} Hudson.Computer.Caption=Master diff --git a/core/src/main/resources/hudson/model/Messages_uk.properties b/core/src/main/resources/hudson/model/Messages_uk.properties index e48bfb0375..59c4b0bc96 100644 --- a/core/src/main/resources/hudson/model/Messages_uk.properties +++ b/core/src/main/resources/hudson/model/Messages_uk.properties @@ -1 +1,3 @@ ParametersDefinitionProperty.DisplayName=\u0426\u044F \u0431\u0443\u0434\u043E\u0432\u0430 \u043C\u0430\u0454 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u0438 + +FreeStyleProject.Description=\u0426\u0435 - \u043E\u0441\u043D\u043E\u0432\u043D\u0430 \u0432\u0456\u0434\u043C\u0456\u043D\u043D\u0456\u0441\u0442\u044C Jenkins. Jenkins \u043F\u043E\u0431\u0443\u0434\u0443\u0454 \u0432\u0430\u0448 \u043F\u0440\u043E\u0435\u043A\u0442, \u043A\u043E\u043C\u0431\u0456\u043D\u0443\u044E\u0447\u0438 \u0431\u0443\u0434\u044C-\u044F\u043A\u0456 \u0441\u0438\u0441\u0442\u0435\u043C\u0438 \u0443\u043F\u0440\u0430\u0432\u043B\u0456\u043D\u043D\u044F \u043A\u043E\u0434\u043E\u043C \u0437 \u0431\u0443\u0434\u044C-\u044F\u043A\u0438\u043C\u0438 \u0441\u0438\u0441\u0442\u0435\u043C\u0430\u043C\u0438 \u0437\u0431\u0456\u0440\u043A\u0438, \u0449\u043E \u043C\u043E\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u043D\u043E \u043D\u0430\u0432\u0456\u0442\u044C \u0434\u043B\u044F \u0446\u0456\u043B\u0435\u0439 \u0432\u0456\u0434\u043C\u0456\u043D\u043D\u0438\u0445 \u0432\u0456\u0434 \u0437\u0431\u0456\u0440\u043A\u0438 \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043D\u043E\u0433\u043E \u0437\u0430\u0431\u0435\u0437\u043F\u0435\u0447\u0435\u043D\u043D\u044F. \ No newline at end of file diff --git a/core/src/main/resources/hudson/model/Messages_zh_CN.properties b/core/src/main/resources/hudson/model/Messages_zh_CN.properties index 19b53a673c..15d419d1f9 100644 --- a/core/src/main/resources/hudson/model/Messages_zh_CN.properties +++ b/core/src/main/resources/hudson/model/Messages_zh_CN.properties @@ -73,6 +73,7 @@ Executor.NotAvailable=N/A FreeStyleProject.DisplayName=\u6784\u5efa\u4e00\u4e2a\u81ea\u7531\u98ce\u683c\u7684\u8f6f\u4ef6\u9879\u76ee +FreeStyleProject.Description=\u8FD9\u662FJenkins\u7684\u4E3B\u8981\u529F\u80FD.Jenkins\u5C06\u4F1A\u7ED3\u5408\u4EFB\u4F55SCM\u548C\u4EFB\u4F55\u6784\u5EFA\u7CFB\u7EDF\u6765\u6784\u5EFA\u4F60\u7684\u9879\u76EE, \u751A\u81F3\u53EF\u4EE5\u6784\u5EFA\u8F6F\u4EF6\u4EE5\u5916\u7684\u7CFB\u7EDF. HealthReport.EmptyString= diff --git a/core/src/main/resources/hudson/model/Messages_zh_TW.properties b/core/src/main/resources/hudson/model/Messages_zh_TW.properties index 1ad674b42e..9109aa1f54 100644 --- a/core/src/main/resources/hudson/model/Messages_zh_TW.properties +++ b/core/src/main/resources/hudson/model/Messages_zh_TW.properties @@ -94,6 +94,11 @@ Executor.NotAvailable=N/A FreeStyleProject.DisplayName=\u5efa\u7f6e Free-Style \u8edf\u9ad4\u5c08\u6848 +FreeStyleProject.Description=\ + \u9019\u662f Jenkins \u7684\u4e3b\u8981\u529f\u80fd\u3002\ + Jenkins \u80fd\u642d\u914d\u5404\u5f0f\u7a0b\u5f0f\u78bc\u7ba1\u7406\u3001\u5efa\u7f6e\u7cfb\u7d71\u4f86\u5efa\u7f6e\u60a8\u7684\u5c08\u6848\uff0c\ + \u751a\u81f3\u9084\u80fd\u505a\u8edf\u9ad4\u5efa\u7f6e\u4ee5\u5916\u7684\u5176\u4ed6\u4e8b\u60c5\u3002 + Hudson.BadPortNumber=\u9023\u63a5\u57e0\u865f {0} \u7121\u6548 Hudson.Computer.Caption=Master diff --git a/core/src/main/resources/hudson/model/Node/help-labelString.html b/core/src/main/resources/hudson/model/Node/help-labelString.html index b0b96bc81d..a7cfc252c1 100644 --- a/core/src/main/resources/hudson/model/Node/help-labelString.html +++ b/core/src/main/resources/hudson/model/Node/help-labelString.html @@ -1,11 +1,23 @@
- Labels (AKA tags) are used for grouping multiple agents into one logical group. - Use spaces between each label. For instance 'regression java6' will assign a - node the labels 'regression' and 'java6'. - + Labels (or tags) are used to group multiple agents into one logical group.

- For example, if you have multiple Windows agents and you have jobs that require - Windows, then you can configure all your Windows agents to have the label 'windows', - then tie the job to the 'windows' label. This allows your job to run on any - of your Windows agents but not on anywhere else. -

\ No newline at end of file + For example, if you have multiple Windows agents and you have a job that + must run on Windows, then you could configure all your Windows agents to have + the label windows, and then tie that job to this label. +
+ This would ensure that your job runs on one of your Windows agents, but not on + any agents without this label. +

+ Labels do not necessarily have to represent the operating system on the agent; + you can also use labels to note the CPU architecture, or that a certain tool + is installed on the agent. +

+ Multiple labels must be separated by a space. For example, + windows docker would assign two labels to the agent: windows + and docker. +

+ Labels may contain any non-space characters, but you should avoid special + characters such as any of these: !&|<>(), as other Jenkins + features allow for defining label expressions, where these characters may be + used. + diff --git a/core/src/main/resources/hudson/model/Node/help-name.html b/core/src/main/resources/hudson/model/Node/help-name.html index dd9c242a06..aa412606d4 100644 --- a/core/src/main/resources/hudson/model/Node/help-name.html +++ b/core/src/main/resources/hudson/model/Node/help-name.html @@ -1,7 +1,10 @@

- Name that uniquely identifies a agent within this Jenkins installation. - + Name that uniquely identifies an agent within this Jenkins installation.

- This value could be any string, and doesn't have to be the same as the agent host name, - but it's often convenient to make them the same. + This does not have to be the same as the agent hostname (where applicable), + but it is often convenient to make them the same. +

+ The name may not contain any characters from this list: + ?*/\%!@#$^&|<>[]:; +

diff --git a/core/src/main/resources/hudson/model/Node/help-numExecutors.html b/core/src/main/resources/hudson/model/Node/help-numExecutors.html index 4d362213ba..6e23a37a77 100644 --- a/core/src/main/resources/hudson/model/Node/help-numExecutors.html +++ b/core/src/main/resources/hudson/model/Node/help-numExecutors.html @@ -1,15 +1,18 @@
- This controls the number of concurrent builds that Jenkins can perform. So the value - affects the overall system load Jenkins may incur. - A good value to start with would be the number of processors on your system. - + The maximum number of concurrent builds that Jenkins may perform on this + agent.

- Increasing this value beyond that would cause each build to take longer, but it could increase - the overall throughput, because it allows CPU to build one project while another build is waiting - for I/O. - + A good value to start with would be the number of CPU cores on the machine. + Setting a higher value would cause each build to take longer, but could + increase the overall throughput. For example, one build might be CPU-bound, + while a second build running at the same time might be I/O-bound — so + the second build could take advantage of the spare I/O capacity at that + moment.

- When using Jenkins in the master/agent mode, setting this value to 0 would prevent the master - from doing any building on its own. Agents may not have zero executors, but may be - temporarily disabled using the button on the agent's status page. + Agents must have at least one executor. To temporarily prevent any builds from + being executed on an agent, use the Mark this node temporarily offline + button on the agent's page. +

+ This does not apply to the Jenkins master — setting the number of + executors to zero will prevent any builds from being executed on the master.

diff --git a/core/src/main/resources/hudson/model/ParametersDefinitionProperty/help.html b/core/src/main/resources/hudson/model/ParametersDefinitionProperty/help.html index a89669c4c5..496799b63e 100644 --- a/core/src/main/resources/hudson/model/ParametersDefinitionProperty/help.html +++ b/core/src/main/resources/hudson/model/ParametersDefinitionProperty/help.html @@ -1,14 +1,36 @@
- When you are using Jenkins for various automations, it's sometimes convenient - to be able to "parameterize" a build, by requiring a set of user inputs to - be made available to the build process. For example, you might be setting up - an on-demand test job, where the user can submit a zip file of the binaries to be tested. - -

- This section configures what parameters your build takes. Parameters are distinguished - by their names, and so you can have multiple parameters provided that they have different names. - -

- See the Wiki topic - for more discussions about this feature. + Parameters allow you to prompt users for one or more inputs that will be + passed into a build. For example, you might have a project that runs tests on + demand by allowing users to upload a zip file with binaries to be tested. + This could be done by adding a File Parameter here. +
+ Or you might have a project that releases some software, and you want users to + enter release notes that will be uploaded along with the software. This could + be done by adding a Multi-line String Parameter here. +

+ Each parameter has a Name and some sort of Value, depending on + the parameter type. These name-value pairs will be exported as environment + variables when the build starts, allowing subsequent parts of the build + configuration (such as build steps) to access those values, e.g. by using the + ${PARAMETER_NAME} syntax (or %PARAMETER_NAME% on Windows). +
+ This also implies that each parameter defined here should have a unique + Name. +

+ When a project is parameterized, the usual Build Now link will be + replaced with a Build with Parameters link, where users will be + prompted to specify values for each of the defined parameters. If they choose + not to enter anything, the build will start with the default value for each + parameter. +

+ If a build is started automatically, for example if started by an SCM trigger, + the default values for each parameter will be used. +

+ When a parameterized build is in the queue, attempting to start another build + of the same project will only succeed if the parameter values are different, + or if the Execute concurrent builds if necessary option is enabled. +

+ See the Parameterized Builds wiki page for more information about + this feature.

diff --git a/core/src/main/resources/hudson/model/Slave/help-remoteFS.html b/core/src/main/resources/hudson/model/Slave/help-remoteFS.html index d40a982a9b..6915c41fb3 100644 --- a/core/src/main/resources/hudson/model/Slave/help-remoteFS.html +++ b/core/src/main/resources/hudson/model/Slave/help-remoteFS.html @@ -1,36 +1,34 @@

An agent needs to have a directory dedicated to Jenkins. Specify - the path of this work directory on the agent. It is best to use - an absolute path, such as '/var/jenkins' or 'c:\jenkins'. This - should be a path local to the agent machine. There's no need for - this path to be visible from the master, under normal circumstances. - + the path to this directory on the agent. It is best to use + an absolute path, such as /var/jenkins or c:\jenkins. + This should be a path local to the agent machine. There is no need for + this path to be visible from the master.

- Agents do not maintain important data (other than active workspaces - of projects last built on it), so you can possibly set the agent - workspace to a temporary directory. The only downside of doing this - is that you may lose the up-to-date workspace if the agent is turned off. - + Agents do not maintain important data; all job configurations, build logs and + artifacts are stored on the master, so it would be possible to use a temporary + directory as the agent root directory. +
+ However, by giving an agent a directory that is not deleted after a machine + reboot, for example, the agent can cache data such as tool installations, or + build workspaces. This prevents unnecessary downloading of tools, or checking + out source code again when builds start to run on this agent again after a + reboot.

- If you use a relative path, such as './jenkins-slave', the path will - be relative to the current working directory that the launcher provides. + If you use a relative path, such as ./jenkins-agent, the path will be + relative to the working directory provided by the Launch method.

  • For launchers where Jenkins controls starting the agent process, such as SSH, the current working directory will typically be consistent, - e.g. the user's home directory. This means that Jenkins will be able to - rely on the caching of tool installations and workspaces from previous - builds. -
  • + e.g. the user's home directory.
  • For launchers where Jenkins has no control over starting the agent process, such as JNLP when launched from either the command line or via a web browser link, the current working directory may change between launches of the agent and use of a relative path may prove problematic. +
    The principal issue encountered when using relative paths with launchers like JNLP is the proliferation of stale workspaces and tool installation - on the agent machine. This can cause disk space issues. - Note: there are some cloud providers that specifically use relative - paths with the JNLP launcher to allow for dynamically provisioned pools - of semi-heterogeneous agents.
  • + on the agent machine. This can cause disk space issues.
diff --git a/core/src/main/resources/hudson/model/UpdateCenter/sidepanel.jelly b/core/src/main/resources/hudson/model/UpdateCenter/sidepanel.jelly index 3880cfa74c..5f9d40194f 100644 --- a/core/src/main/resources/hudson/model/UpdateCenter/sidepanel.jelly +++ b/core/src/main/resources/hudson/model/UpdateCenter/sidepanel.jelly @@ -32,7 +32,7 @@ THE SOFTWARE. - + diff --git a/core/src/main/resources/hudson/model/UsageStatistics/help-usageStatisticsCollected.html b/core/src/main/resources/hudson/model/UsageStatistics/help-usageStatisticsCollected.html index 160039c362..37b1e5cc65 100644 --- a/core/src/main/resources/hudson/model/UsageStatistics/help-usageStatisticsCollected.html +++ b/core/src/main/resources/hudson/model/UsageStatistics/help-usageStatisticsCollected.html @@ -1,6 +1,6 @@
Knowing how Jenkins is used is a tremendous help in guiding the direction of the development, especially - for open-source projects where users are inheritenly hard to track down. When this option is enabled, + for open-source projects where users are inherently hard to track down. When this option is enabled, Jenkins periodically send information about your usage of Jenkins.

@@ -10,7 +10,7 @@

  • Your Jenkins version
  • For your master and each agent, OS type, and # of executors
  • Plugins that are installed and their versions -
  • Number jobs per each job type in your Jenkins +
  • Number of jobs per each job type in your Jenkins

    @@ -18,7 +18,4 @@ (except information inherently revealed by HTTP, such as the IP address). Tabulated data of these usage statistics submissions will be shared with the community. -

    - You can read - the discussion of this mechanism in the community, and you are welcome to add your voice here.

  • diff --git a/core/src/main/resources/hudson/model/UsageStatistics/help-usageStatisticsCollected_fr.html b/core/src/main/resources/hudson/model/UsageStatistics/help-usageStatisticsCollected_fr.html index 2fdf5eea3b..8d4df6df9d 100644 --- a/core/src/main/resources/hudson/model/UsageStatistics/help-usageStatisticsCollected_fr.html +++ b/core/src/main/resources/hudson/model/UsageStatistics/help-usageStatisticsCollected_fr.html @@ -15,9 +15,9 @@

    - Cette information ne contient rien qui vous identifie ou qui nous permet de vous contacter + Cette information ne contient rien qui vous identifie ou qui nous permette de vous contacter (hors certaines informations intrinsèques à HTTP, comme votre adresse IP). - Les données compilées de ces statistiques d'utilisation selon partagées avec la communauté. + Les données compilées de ces statistiques d'utilisation seront partagées avec la communauté.

    N'hésitez pas à lire diff --git a/core/src/main/resources/hudson/model/UsageStatistics/help-usageStatisticsCollected_pt_BR.html b/core/src/main/resources/hudson/model/UsageStatistics/help-usageStatisticsCollected_pt_BR.html new file mode 100644 index 0000000000..bde77e44f1 --- /dev/null +++ b/core/src/main/resources/hudson/model/UsageStatistics/help-usageStatisticsCollected_pt_BR.html @@ -0,0 +1,20 @@ +

    + Saber como Jenkins é utilizado é uma tremenda ajuda guiando-nos no desenvolvimento, especificamente para + projetos de código livre onde os usuários são inerentemente difíceis de rastrear. Ao ativar esta opção, + Jenkins periodicamente enviará informações sobre o seu uso. + +

    + Especificamente, as informações enviadas serão: + +

      +
    • A versão do seu Jenkins +
    • Para cada master e cada slave, o tipo de Sistema Operacional, e número de executores +
    • Os plugins instalados e suas versões +
    • Número de jobs por tipo de job no seu Jenkins +
    + +

    + Essas informaçãos não contem nada o identifique ou nos permita contatá-lo + (exceto pelas informações reveladas via HTTP, tal como Endereço IP). + Dados das estatísticas de uso submetidas são compartilhados com a comunidade. +

    diff --git a/core/src/main/resources/hudson/model/User/sidepanel.jelly b/core/src/main/resources/hudson/model/User/sidepanel.jelly index 126bdae5d8..46bad7a605 100644 --- a/core/src/main/resources/hudson/model/User/sidepanel.jelly +++ b/core/src/main/resources/hudson/model/User/sidepanel.jelly @@ -34,7 +34,7 @@ THE SOFTWARE. - + diff --git a/core/src/main/resources/hudson/model/View/newJob.jelly b/core/src/main/resources/hudson/model/View/newJob.jelly index ba6ae05161..c37a22c836 100644 --- a/core/src/main/resources/hudson/model/View/newJob.jelly +++ b/core/src/main/resources/hudson/model/View/newJob.jelly @@ -22,20 +22,54 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --> - - - + + + + + + - - - - +