Skip to content
Permalink
Browse files

Merge remote-tracking branch 'primary/master' into JENKINS-33950-mult…

…iple-dependency-install-fix
  • Loading branch information...
kzantow committed Apr 22, 2016
2 parents dd226f7 + 5d90f81 commit 2ada9b70464b19bf8f15edee86b683606b4d860f
Showing with 249 additions and 188 deletions.
  1. +1 −1 Jenkinsfile
  2. +6 −2 changelog.html
  3. +1 −1 cli/pom.xml
  4. +1 −7 cli/src/main/java/hudson/cli/CLI.java
  5. +1 −1 core/pom.xml
  6. +2 −10 core/src/main/java/hudson/ClassicPluginStrategy.java
  7. +4 −2 core/src/main/java/hudson/Functions.java
  8. +6 −0 core/src/main/java/hudson/PluginManager.java
  9. +2 −0 core/src/main/java/hudson/PluginWrapper.java
  10. +37 −98 core/src/main/java/hudson/Util.java
  11. +8 −4 core/src/main/java/hudson/model/Action.java
  12. +8 −5 core/src/main/java/hudson/model/ManagementLink.java
  13. +1 −1 core/src/main/java/hudson/model/TopLevelItemDescriptor.java
  14. +4 −0 core/src/main/java/hudson/model/UpdateCenter.java
  15. +1 −0 core/src/main/java/hudson/model/UpdateSite.java
  16. +3 −2 core/src/main/java/hudson/model/User.java
  17. +2 −1 core/src/main/java/hudson/model/View.java
  18. +1 −0 core/src/main/java/hudson/model/ViewDescriptor.java
  19. +2 −7 core/src/main/java/jenkins/ClassLoaderReflectionToolkit.java
  20. +16 −4 core/src/main/java/jenkins/model/Jenkins.java
  21. +4 −23 core/src/main/java/jenkins/model/RunIdMigrator.java
  22. +1 −0 core/src/main/resources/jenkins/install/pluginSetupWizard.properties
  23. +32 −0 core/src/main/resources/jenkins/management/Messages_lt.properties
  24. +47 −0 core/src/main/resources/jenkins/model/Messages_lt.properties
  25. +4 −2 core/src/main/resources/jenkins/slaves/systemInfo/Messages_lt.properties
  26. +4 −0 core/src/main/resources/jenkins/triggers/Messages_lt.properties
  27. +5 −2 core/src/test/java/jenkins/xml/XMLUtilsTest.java
  28. +1 −1 pom.xml
  29. +2 −2 test/pom.xml
  30. +3 −5 test/src/test/java/hudson/bugs/JnlpAccessWithSecuredHudsonTest.java
  31. +27 −0 test/src/test/java/hudson/model/ManagementLinkTest.java
  32. +1 −1 war/pom.xml
  33. +2 −2 war/src/main/js/pluginSetupWizardGui.js
  34. +4 −3 war/src/main/js/templates/pluginSelectionPanel.hbs
  35. +1 −1 war/src/main/js/templates/welcomePanel.hbs
  36. +4 −0 war/src/main/less/pluginSetupWizard.less
@@ -15,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') {

@@ -24,7 +24,7 @@
<!--[if IE]>
<style type="text/css">div.rate-offset { bottom: 0.2em !important; left: 5em !important; }</style>
<![endif]-->
<script type="text/javascript" src="https://jenkins-ci.org/rate/rate.js"></script>
<script type="text/javascript" src="https://rating.jenkins.io/rate/rate.js"></script>
</head>
<body>
<div align="right">Legend:
@@ -56,6 +56,8 @@
<!-- Record your changes in the trunk here. -->
<div id="trunk" style="display:none"><!--=TRUNK-BEGIN=-->

</div><!--=TRUNK-END=-->
<h3><a name=v2.0>What's new in 2.0</a> (2016/04/20)</h3>
<div style="margin: 10px; padding: 10px; background-color: #FFFFCE;">
<strong>More detailed information about the new features in Jenkins 2.0 <a href="/2.0/">on the overview page</a>.</strong>
</div>
@@ -85,6 +87,9 @@
<li class="rfe">
Bundled Groovy updated from 1.8.9 to 2.4.6.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-21249">issue 21249</a>)
<li class="rfe">
Added option to prohibit anonymous access to security realm "Logged in users can do anything", enable by default.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-30749">issue 30749</a>)
<li class="rfe">
Renamed 'slave' to 'agent' on the UI.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-27268">issue 27268</a>)
@@ -103,7 +108,6 @@
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-33942">issue 33942</a>)

</ul>
</div><!--=TRUNK-END=-->
<h3><a name=v1.656>What's new in 1.656</a> (2016/04/03)</h3>
<ul class=image>
<li class="bug">
@@ -5,7 +5,7 @@
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>2.0-rc-2-SNAPSHOT</version>
<version>2.1-SNAPSHOT</version>
</parent>

<artifactId>cli</artifactId>
@@ -131,13 +131,7 @@ public CLI(URL jenkins, ExecutorService exec, String httpsProxyTunnel) throws IO
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;
}
}
@@ -29,7 +29,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>2.0-rc-2-SNAPSHOT</version>
<version>2.1-SNAPSHOT</version>
</parent>

<artifactId>jenkins-core</artifactId>
@@ -59,6 +59,7 @@
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,17 +207,8 @@ private static Manifest loadLinkedManifest(File archive) throws IOException {
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 | IllegalAccessException | InvocationTargetException e) {
throw new Error(e);
} catch (ClassNotFoundException e) {
baseResourceURL = expandDir.toURI().toURL();
}
}
File disableFile = new File(archive.getPath() + ".disabled");
if (disableFile.exists()) {
@@ -1532,10 +1532,12 @@ public static String joinPath(String... components) {
/**
* 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;
@@ -994,6 +994,7 @@ public void stop() {
*/
@Restricted(DoNotUse.class) // WebOnly
public HttpResponse doPlugins() {
Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER);
JSONArray response = new JSONArray();
Map<String,JSONObject> allPlugins = new HashMap<>();
for (PluginWrapper plugin : plugins) {
@@ -1006,6 +1007,7 @@ public HttpResponse doPlugins() {
pluginInfo.put("bundled", plugin.isBundled);
pluginInfo.put("deleted", plugin.isDeleted());
pluginInfo.put("downgradable", plugin.isDowngradable());
pluginInfo.put("website", plugin.getUrl());
List<Dependency> dependencies = plugin.getDependencies();
if (dependencies != null && !dependencies.isEmpty()) {
Map<String, String> dependencyMap = new HashMap<>();
@@ -1030,6 +1032,7 @@ public HttpResponse doPlugins() {
pluginInfo.put("excerpt", plugin.excerpt);
pluginInfo.put("site", site.getId());
pluginInfo.put("dependencies", plugin.dependencies);
pluginInfo.put("website", plugin.wiki);
response.add(pluginInfo);
}
}
@@ -1059,6 +1062,7 @@ public HttpResponse doUpdateSources(StaplerRequest req) throws IOException {
* Performs the installation of the plugins.
*/
public void doInstall(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER);
Set<String> plugins = new LinkedHashSet<>();

Enumeration<String> en = req.getParameterNames();
@@ -1087,6 +1091,7 @@ public void doInstall(StaplerRequest req, StaplerResponse rsp) throws IOExceptio
@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 +1124,7 @@ public HttpResponse doInstallPlugins(StaplerRequest req) throws IOException {
* @return The install job list.
* @since FIXME
*/
@Restricted(NoExternalUse.class)
public List<Future<UpdateCenter.UpdateCenterJob>> install(@Nonnull Collection<String> plugins, boolean dynamicLoad) {
return install(plugins, dynamicLoad, null);
}
@@ -656,6 +656,7 @@ public HttpResponse doMakeDisabled() throws IOException {
@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 HttpResponse doPin() throws IOException {
@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();
@@ -63,6 +63,12 @@
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 static void deleteFile(@Nonnull File f) throws IOException {

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)
@@ -367,10 +363,8 @@ public static boolean isSymlink(@Nonnull File file) throws IOException {
@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);
}
@@ -1218,48 +1212,36 @@ public static void createSymlink(@Nonnull File baseDir, @Nonnull String targetPa

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);
}
@@ -1310,62 +1292,19 @@ public static File resolveSymlinkToFile(@Nonnull File link) throws InterruptedEx
*/
@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);
}
}

/**

0 comments on commit 2ada9b7

Please sign in to comment.
You can’t perform that action at this time.