Skip to content

Commit

Permalink
Merge remote-tracking branch 'primary/master' into JENKINS-34137-smar…
Browse files Browse the repository at this point in the history
…ter-setup-wizard-close
  • Loading branch information
kzantow committed Apr 22, 2016
2 parents d0f5c2b + d1bcd1f commit 1c39655
Show file tree
Hide file tree
Showing 31 changed files with 235 additions and 182 deletions.
2 changes: 1 addition & 1 deletion Jenkinsfile
Expand Up @@ -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') {

Expand Down
8 changes: 6 additions & 2 deletions changelog.html
Expand Up @@ -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:
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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>)
Expand All @@ -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">
Expand Down
2 changes: 1 addition & 1 deletion cli/pom.xml
Expand Up @@ -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>
Expand Down
8 changes: 1 addition & 7 deletions cli/src/main/java/hudson/cli/CLI.java
Expand Up @@ -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;
}
}
Expand Down
2 changes: 1 addition & 1 deletion core/pom.xml
Expand Up @@ -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>
Expand Down
12 changes: 2 additions & 10 deletions core/src/main/java/hudson/ClassicPluginStrategy.java
Expand Up @@ -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;
Expand Down Expand Up @@ -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()) {
Expand Down
6 changes: 4 additions & 2 deletions core/src/main/java/hudson/Functions.java
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/java/hudson/PluginManager.java
Expand Up @@ -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) {
Expand Down Expand Up @@ -1059,6 +1060,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();
Expand Down Expand Up @@ -1087,6 +1089,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");
Expand Down Expand Up @@ -1119,6 +1122,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);
}
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/hudson/PluginWrapper.java
Expand Up @@ -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();
Expand All @@ -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();
Expand Down
135 changes: 37 additions & 98 deletions core/src/main/java/hudson/Util.java
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
}

/**
Expand Down
12 changes: 8 additions & 4 deletions core/src/main/java/hudson/model/Action.java
Expand Up @@ -25,6 +25,8 @@

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.)
Expand Down Expand Up @@ -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.
Expand All @@ -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();
}

0 comments on commit 1c39655

Please sign in to comment.