Merge branch 'master' into printStackTrace-JDK-6507809

This commit is contained in:
Jesse Glick committed 2016-12-12 14:25:12 -05:00
commit 2abddbdfcc
3124 files changed
+75925 -26255

No files matched your search

+90 -34
View File
@@ -25,6 +25,8 @@
*/
package hudson;
import hudson.model.Slave;
import jenkins.util.SystemProperties;
import hudson.cli.CLICommand;
import hudson.console.ConsoleAnnotationDescriptor;
import hudson.console.ConsoleAnnotatorFactory;
@@ -74,7 +76,10 @@ import hudson.tasks.Publisher;
import hudson.tasks.UserAvatarResolver;
import hudson.util.Area;
import hudson.util.FormValidation.CheckMethod;
import hudson.util.HudsonIsLoading;
import hudson.util.HudsonIsRestarting;
import hudson.util.Iterators;
import hudson.util.jna.GNUCLibrary;
import hudson.util.Secret;
import hudson.views.MyViewsTabBar;
import hudson.views.ViewsTabBar;
@@ -82,6 +87,7 @@ import hudson.widgets.RenderOnDemandClosure;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.lang.management.LockInfo;
@@ -126,7 +132,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;
@@ -149,14 +154,15 @@ import org.kohsuke.stapler.jelly.InternationalizedStringExpression.RawHtmlArgume
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import hudson.model.PasswordParameterDefinition;
import hudson.util.RunList;
import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import org.apache.commons.io.IOUtils;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.accmod.restrictions.DoNotUse;
/**
* Utility functions used in views.
@@ -208,20 +214,28 @@ public class Functions {
/**
* During Jenkins start-up, before {@link InitMilestone#PLUGINS_STARTED} the extensions lists will be empty
* and they are not guaranteed to be fully populated until after {@link InitMilestone#EXTENSIONS_AUGMENTED}.
* and they are not guaranteed to be fully populated until after {@link InitMilestone#EXTENSIONS_AUGMENTED},
* similarly, during termination after {@link Jenkins#isTerminating()} is set, it is no longer safe to access
* the extensions lists.
* If you attempt to access the extensions list from a UI thread while the extensions are being loaded you will
* hit a big honking great monitor lock that will block until the effective extension list has been determined
* (as if a plugin fails to start, all of the failed plugin's extensions and any dependent plugins' extensions
* will have to be evicted from the list of extensions. In practical terms this only affects the
* "Jenkins is loading" screen, but as that screen uses the generic layouts we provide this utility method
* so that the generic layouts can avoid iterating extension lists while Jenkins is starting up.
* If you attempt to access the extensions list from a UI thread while Jenkins is being shut down, the extensions
* themselves may no longer be in a valid state and could attempt to revive themselves and block termination.
* In actual terms the termination only affects those views required to render {@link HudsonIsRestarting}'s
* {@code index.jelly} which is the same set as the {@link HudsonIsLoading} pages so it makes sense to
* use both checks here.
*
* @return {@code true} if the extensions lists have been populated.
* @since 1.607
*/
public static boolean isExtensionsAvailable() {
final Jenkins jenkins = Jenkins.getInstance();
return jenkins != null && jenkins.getInitLevel().compareTo(InitMilestone.EXTENSIONS_AUGMENTED) >= 0;
final Jenkins jenkins = Jenkins.getInstanceOrNull();
return jenkins != null && jenkins.getInitLevel().compareTo(InitMilestone.EXTENSIONS_AUGMENTED) >= 0
&& !jenkins.isTerminating();
}
public static void initPageVariables(JellyContext context) {
@@ -461,6 +475,15 @@ public class Functions {
public static boolean isWindows() {
return File.pathSeparatorChar==';';
}
public static boolean isGlibcSupported() {
try {
GNUCLibrary.LIBC.getpid();
return true;
} catch(Throwable t) {
return false;
}
}
public static List<LogRecord> getLogRecords() {
return Jenkins.logRecords;
@@ -553,7 +576,7 @@ public class Functions {
/**
* Set to true if you need to use the debug version of YUI.
*/
public static boolean DEBUG_YUI = Boolean.getBoolean("debug.YUI");
public static boolean DEBUG_YUI = SystemProperties.getBoolean("debug.YUI");
/**
* Creates a sub map by using the given range (both ends inclusive).
@@ -608,7 +631,7 @@ public class Functions {
response.addCookie(c);
}
if (refresh) {
response.addHeader("Refresh", System.getProperty("hudson.Functions.autoRefreshSeconds", "10"));
response.addHeader("Refresh", SystemProperties.getString("hudson.Functions.autoRefreshSeconds", "10"));
}
}
@@ -830,7 +853,7 @@ public class Functions {
*/
public static String getFooterURL() {
if(footerURL == null) {
footerURL = System.getProperty("hudson.footerURL");
footerURL = SystemProperties.getString("hudson.footerURL");
if(StringUtils.isBlank(footerURL)) {
footerURL = "http://jenkins-ci.org/";
}
@@ -843,6 +866,10 @@ public class Functions {
return JobPropertyDescriptor.getPropertyDescriptors(clazz);
}
public static List<JobPropertyDescriptor> getJobPropertyDescriptors(Job job) {
return DescriptorVisibilityFilter.apply(job, JobPropertyDescriptor.getPropertyDescriptors(job.getClass()));
}
public static List<Descriptor<BuildWrapper>> getBuildWrapperDescriptors(AbstractProject<?,?> project) {
return BuildWrappers.getFor(project);
}
@@ -867,10 +894,24 @@ public class Functions {
return SCM._for(project);
}
/**
* @since 2.12
* @deprecated replaced by {@link Slave.SlaveDescriptor#computerLauncherDescriptors(Slave)}
*/
@Deprecated
@Restricted(DoNotUse.class)
@RestrictedSince("2.12")
public static List<Descriptor<ComputerLauncher>> getComputerLauncherDescriptors() {
return Jenkins.getInstance().<ComputerLauncher,Descriptor<ComputerLauncher>>getDescriptorList(ComputerLauncher.class);
}
/**
* @since 2.12
* @deprecated replaced by {@link Slave.SlaveDescriptor#retentionStrategyDescriptors(Slave)}
*/
@Deprecated
@Restricted(DoNotUse.class)
@RestrictedSince("2.12")
public static List<Descriptor<RetentionStrategy<?>>> getRetentionStrategyDescriptors() {
return RetentionStrategy.all();
}
@@ -891,6 +932,13 @@ public class Functions {
return MyViewsTabBar.all();
}
/**
* @deprecated replaced by {@link Slave.SlaveDescriptor#nodePropertyDescriptors(Slave)}
* @since 2.12
*/
@Deprecated
@Restricted(DoNotUse.class)
@RestrictedSince("2.12")
public static List<NodePropertyDescriptor> getNodePropertyDescriptors(Class<? extends Node> clazz) {
List<NodePropertyDescriptor> result = new ArrayList<NodePropertyDescriptor>();
Collection<NodePropertyDescriptor> list = (Collection) Jenkins.getInstance().getDescriptorList(NodeProperty.class);
@@ -943,12 +991,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);
@@ -1387,7 +1431,7 @@ public class Functions {
/**
* If the value exists, return that value. Otherwise return the default value.
* <p>
* Starting 1.294, JEXL supports the elvis operator "x?:y" that supercedes this.
* Starting 1.294, JEXL supports the elvis operator "x?:y" that supersedes this.
*
* @since 1.150
*/
@@ -1399,10 +1443,15 @@ public class Functions {
* Prints a stack trace from an exception into a readable form.
* Unlike {@link Throwable#printStackTrace(PrintWriter)}, this implementation follows the suggestion of JDK-6507809
* to produce a linear trace even when {@link Throwable#getCause} is used.
* @param t any throwable
* @return generally a multiline string ending in a (platform-specific) newline
* @param t Input {@link Throwable}
* @return If {@code t} is not null, generally a multiline string ending in a (platform-specific) newline;
* otherwise, the method returns a default
* &quot;No exception details&quot; string.
*/
public static @Nonnull String printThrowable(@Nonnull Throwable t) {
public static @Nonnull String printThrowable(@CheckForNull Throwable t) {
if (t == null) {
return Messages.Functions_NoExceptionDetails();
}
StringBuilder s = new StringBuilder();
doPrintStackTrace(s, t, null);
return s.toString();
@@ -1544,10 +1593,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;
@@ -1584,15 +1635,11 @@ public class Functions {
return projectName;
}
public String getSystemProperty(String key) {
return System.getProperty(key);
}
/**
* Obtains the host name of the Hudson server that clients can use to talk back to.
* <p>
* This is primarily used in <tt>slave-agent.jnlp.jelly</tt> to specify the destination
* that the slaves talk to.
* that the agents talk to.
*/
public String getServerName() {
// Try to infer this from the configured root URL.
@@ -1666,7 +1713,7 @@ public class Functions {
*/
public static List<PageDecorator> getPageDecorators() {
// this method may be called to render start up errors, at which point Hudson doesn't exist yet. see HUDSON-3608
if(Jenkins.getInstance()==null) return Collections.emptyList();
if(Jenkins.getInstanceOrNull()==null) return Collections.emptyList();
return PageDecorator.all();
}
@@ -1688,13 +1735,13 @@ public class Functions {
}
public static String getCrumb(StaplerRequest req) {
Jenkins h = Jenkins.getInstance();
Jenkins h = Jenkins.getInstanceOrNull();
CrumbIssuer issuer = h != null ? h.getCrumbIssuer() : null;
return issuer != null ? issuer.getCrumb(req) : "";
}
public static String getCrumbRequestField() {
Jenkins h = Jenkins.getInstance();
Jenkins h = Jenkins.getInstanceOrNull();
CrumbIssuer issuer = h != null ? h.getCrumbIssuer() : null;
return issuer != null ? issuer.getDescriptor().getCrumbRequestField() : "";
}
@@ -1759,8 +1806,17 @@ public class Functions {
*/
public String getPasswordValue(Object o) {
if (o==null) return null;
if (o instanceof Secret) return ((Secret)o).getEncryptedValue();
if (getIsUnitTest()) {
if (o instanceof Secret) {
StaplerRequest req = Stapler.getCurrentRequest();
if (req != null) {
Item item = req.findAncestorObject(Item.class);
if (item != null && !item.hasPermission(Item.CONFIGURE)) {
return "********";
}
}
return ((Secret) o).getEncryptedValue();
}
if (getIsUnitTest() && !o.equals(PasswordParameterDefinition.DEFAULT_VALUE)) {
throw new SecurityException("attempted to render plaintext ‘" + o + "’ in password field; use a getter of type Secret instead");
}
return o.toString();
@@ -1789,7 +1845,7 @@ public class Functions {
* the permission can't be configured in the security screen). Got it?</p>
*/
public static boolean isArtifactsPermissionEnabled() {
return Boolean.getBoolean("hudson.security.ArtifactsPermission");
return SystemProperties.getBoolean("hudson.security.ArtifactsPermission");
}
/**
@@ -1804,7 +1860,7 @@ public class Functions {
* control on the "Wipe Out Workspace" action.</p>
*/
public static boolean isWipeOutPermissionEnabled() {
return Boolean.getBoolean("hudson.security.WipeOutPermission");
return SystemProperties.getBoolean("hudson.security.WipeOutPermission");
}
public static String createRenderOnDemandProxy(JellyContext context, String attributesToCapture) {
@@ -1924,7 +1980,7 @@ public class Functions {
* discovery of Jenkins.
*/
public static void advertiseHeaders(HttpServletResponse rsp) {
Jenkins j = Jenkins.getInstance();
Jenkins j = Jenkins.getInstanceOrNull();
if (j!=null) {
rsp.setHeader("X-Hudson","1.395");
rsp.setHeader("X-Jenkins", Jenkins.VERSION);
@@ -1932,7 +1988,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);