Skip to content
This repository has been archived by the owner on Apr 6, 2022. It is now read-only.

Commit

Permalink
Adapted version to match master
Browse files Browse the repository at this point in the history
  • Loading branch information
Julianus Pfeuffer committed May 15, 2017
2 parents 600de81 + 8af3c8b commit 97ab4d2
Show file tree
Hide file tree
Showing 28 changed files with 573 additions and 89 deletions.
14 changes: 7 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<artifactId>warnings</artifactId>
<packaging>hpi</packaging>
<name>Warnings Plug-in</name>
<version>4.61</version>
<version>4.63-SNAPSHOT</version>
<url>http://wiki.jenkins-ci.org/x/G4CGAQ</url>
<description>This plug-in reads the compiler warnings from the console log file and generates a trend report.</description>

Expand Down Expand Up @@ -44,7 +44,12 @@
<dependency>
<groupId>org.jvnet.hudson.plugins</groupId>
<artifactId>analysis-core</artifactId>
<version>1.82</version>
<version>1.86</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>script-security</artifactId>
<version>1.25</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
Expand All @@ -57,11 +62,6 @@
<artifactId>commons-digester3</artifactId>
<version>3.2</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>script-security</artifactId>
<version>1.17</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-scm-step</artifactId>
Expand Down
24 changes: 19 additions & 5 deletions src/main/java/hudson/plugins/warnings/GroovyParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;

import groovy.lang.GroovyShell;
import jenkins.model.Jenkins;

import hudson.Extension;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import hudson.plugins.warnings.parser.*;
import hudson.plugins.warnings.parser.AbstractWarningsParser;
import hudson.plugins.warnings.parser.DynamicDocumentParser;
import hudson.plugins.warnings.parser.DynamicParser;
import hudson.plugins.warnings.parser.GroovyExpressionMatcher;
import hudson.plugins.warnings.parser.Warning;
import hudson.util.FormValidation;
import hudson.util.FormValidation.Kind;

Expand All @@ -28,7 +32,6 @@
* @author Ulli Hafner
*/
public class GroovyParser extends AbstractDescribableImpl<GroovyParser> {

private static final int MAX_EXAMPLE_SIZE = 4096;

private final String name;
Expand Down Expand Up @@ -223,6 +226,7 @@ public AbstractWarningsParser getParser() {
public static class DescriptorImpl extends Descriptor<GroovyParser> {
private static final String NEWLINE = "\n";
private static final int MAX_MESSAGE_LENGTH = 60;
private static final FormValidation NO_RUN_SCRIPT_PERMISSION_WARNING = FormValidation.warning(Messages.Warnings_GroovyParser_Warning_NoRunScriptPermission());

private FormValidation validate(final String name, final String message) {
if (StringUtils.isBlank(name)) {
Expand Down Expand Up @@ -293,13 +297,16 @@ public FormValidation doCheckRegexp(@QueryParameter(required = true) final Strin
* @return the validation result
*/
public FormValidation doCheckScript(@QueryParameter(required = true) final String script) {
if (!canRunScripts()) {
return NO_RUN_SCRIPT_PERMISSION_WARNING;
}
try {
if (StringUtils.isBlank(script)) {
return FormValidation.error(Messages.Warnings_GroovyParser_Error_Script_isEmpty());
}

GroovyShell groovyShell = new GroovyShell(WarningsDescriptor.class.getClassLoader());
groovyShell.parse(script);
GroovyExpressionMatcher matcher = new GroovyExpressionMatcher(script, null);
matcher.compile();

return FormValidation.ok();
}
Expand All @@ -308,6 +315,10 @@ public FormValidation doCheckScript(@QueryParameter(required = true) final Strin
}
}

private boolean canRunScripts() {
return Jenkins.getInstance().getACL().hasPermission(Jenkins.RUN_SCRIPTS);
}

/**
* Parses the example message with the specified regular expression and script.
*
Expand All @@ -321,6 +332,9 @@ public FormValidation doCheckScript(@QueryParameter(required = true) final Strin
*/
public FormValidation doCheckExample(@QueryParameter final String example,
@QueryParameter final String regexp, @QueryParameter final String script) {
if (!canRunScripts()) {
return NO_RUN_SCRIPT_PERMISSION_WARNING;
}
if (StringUtils.isNotBlank(example) && StringUtils.isNotBlank(regexp) && StringUtils.isNotBlank(script)) {
FormValidation response = parseExample(script, example, regexp, containsNewline(regexp));
if (example.length() <= MAX_EXAMPLE_SIZE) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.IOException;
import java.util.Collection;

import org.jenkinsci.Symbol;
import org.kohsuke.stapler.Ancestor;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.QueryParameter;
Expand All @@ -28,7 +29,7 @@
*
* @author Ulli Hafner
*/
@Extension(ordinal = 100) // NOCHECKSTYLE
@Extension(ordinal = 100) @Symbol("warnings")
public final class WarningsDescriptor extends PluginDescriptor implements StaplerProxy {
/** The ID of this plug-in is used as URL. */
static final String PLUGIN_ID = "warnings";
Expand Down
43 changes: 31 additions & 12 deletions src/main/java/hudson/plugins/warnings/WarningsPublisher.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException;
import org.jenkinsci.plugins.scriptsecurity.scripts.ApprovalContext;
import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;

Expand Down Expand Up @@ -367,19 +370,29 @@ private List<ParserResult> parseConsoleLog(final Run<?, ?> run, final FilePath w
String parserName = parser.getParserName();
logger.log("Parsing warnings in console log with parser " + parserName);

Collection<FileAnnotation> warnings = new ParserRegistry(ParserRegistry.getParsers(parserName),
getDefaultEncoding()).parse(run.getLogFile());
if (!workspace.isRemote()) {
guessModuleNames(workspace, warnings);
}
ParserResult project = new ParserResult(workspace, canResolveRelativePaths());
project.addAnnotations(warnings);
try {
Collection<FileAnnotation> warnings = new ParserRegistry(ParserRegistry.getParsers(parserName),
getDefaultEncoding()).parse(run.getLogFile());
if (!workspace.isRemote()) {
guessModuleNames(workspace, warnings);
}
ParserResult project = new ParserResult(workspace, canResolveRelativePaths());
project.addAnnotations(warnings);

results.add(annotate(run, workspace, filterWarnings(project, logger), parserName));
results.add(annotate(run, workspace, filterWarnings(project, logger), parserName));
}
catch (RejectedAccessException exception) {
handleRejectedException(logger, parserName, exception);
}
}
return results;
}

private void handleRejectedException(final PluginLogger logger, final String parserName, final RejectedAccessException exception) {
logger.log(Messages.Warnings_GroovyParser_Warning_Rejected(parserName, exception.getMessage()));
ScriptApproval.get().accessRejected(exception, ApprovalContext.create());
}

private ParserResult filterWarnings(final ParserResult project, final PluginLogger logger) {
WarningsFilter filter = new WarningsFilter();
if (filter.isActive(getIncludePattern(), getExcludePattern(), getMessagesPattern(), getCategoriesPattern())) {
Expand Down Expand Up @@ -410,11 +423,17 @@ private List<ParserResult> parseFiles(final Run<?, ?> run, final FilePath worksp
FilesParser parser = new FilesParser(PLUGIN_NAME, filePattern,
new FileWarningsParser(ParserRegistry.getParsers(parserName), getDefaultEncoding()),
shouldDetectModules(), isMavenBuild(run), canResolveRelativePaths());
ParserResult project = workspace.act(parser);
logger.logLines(project.getLogMessages());
ParserResult project = null;
try {
project = workspace.act(parser);
logger.logLines(project.getLogMessages());

returnIfCanceled();
results.add(annotate(run, workspace, filterWarnings(project, logger), configuration.getParserName()));
returnIfCanceled();
results.add(annotate(run, workspace, filterWarnings(project, logger), configuration.getParserName()));
}
catch (RejectedAccessException exception) {
handleRejectedException(logger, parserName, exception);
}
}
return results;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.Whitelisted;
import org.jvnet.localizer.Localizable;

import hudson.ExtensionPoint;

import hudson.plugins.analysis.util.model.FileAnnotation;
import hudson.plugins.analysis.util.model.Priority;
import hudson.plugins.warnings.Messages;
Expand Down Expand Up @@ -189,6 +189,7 @@ protected String getId() {
* the message of the warning
* @return the warning
*/
@Whitelisted
public Warning createWarning(final String fileName, final int start, final String category, final String message) {
return new Warning(fileName, start, getGroup(), category, message);
}
Expand All @@ -205,6 +206,7 @@ public Warning createWarning(final String fileName, final int start, final Strin
* the message of the warning
* @return the warning
*/
@Whitelisted
public Warning createWarning(final String fileName, final int start, final String message) {
return createWarning(fileName, start, StringUtils.EMPTY, message);
}
Expand All @@ -224,6 +226,7 @@ public Warning createWarning(final String fileName, final int start, final Strin
* the priority of the warning
* @return the warning
*/
@Whitelisted
public Warning createWarning(final String fileName, final int start, final String category, final String message, final Priority priority) {
return new Warning(fileName, start, getGroup(), category, message, priority);
}
Expand All @@ -246,6 +249,7 @@ public Warning createWarning(final String fileName, final int start, final Strin
* @return the warning
* @since 4.24
*/
@Whitelisted
public Warning createWarning(final String fileName, final int start, final String type, final String category, final String message, final Priority priority) {
return new Warning(fileName, start, type, category, message, priority);
}
Expand All @@ -264,6 +268,7 @@ public Warning createWarning(final String fileName, final int start, final Strin
* the priority of the warning
* @return the warning
*/
@Whitelisted
public Warning createWarning(final String fileName, final int start, final String message, final Priority priority) {
return createWarning(fileName, start, StringUtils.EMPTY, message, priority);
}
Expand Down Expand Up @@ -295,6 +300,7 @@ public String getLargeImage() {
* the line number (as a string)
* @return the line number
*/
@Whitelisted
protected final int getLineNumber(final String lineNumber) {
return convertLineNumber(lineNumber);
}
Expand All @@ -309,6 +315,7 @@ protected final int getLineNumber(final String lineNumber) {
* @return the line number
* @since 4.37
*/
@Whitelisted
public static int convertLineNumber(final String lineNumber) {
if (StringUtils.isNotBlank(lineNumber)) {
try {
Expand All @@ -328,6 +335,7 @@ public static int convertLineNumber(final String lineNumber) {
* @return the escaped text
* @see StringEscapeUtils#escapeXml11
*/
@Whitelisted
protected String escapeXml(final String text) {
return StringEscapeUtils.escapeXml10(text);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package hudson.plugins.warnings.parser;

import java.io.Serializable;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;

import org.codehaus.groovy.control.CompilationFailedException;
import org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException;
import org.jenkinsci.plugins.scriptsecurity.sandbox.Whitelist;
import org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
Expand All @@ -26,7 +30,6 @@ public class GroovyExpressionMatcher implements Serializable {

private transient Script compiled;


/**
* Creates a new instance of {@link GroovyExpressionMatcher}.
*
Expand All @@ -43,19 +46,30 @@ public GroovyExpressionMatcher(final String script, final Warning falsePositive)
private void compileScriptIfNotYetDone() {
synchronized (script) {
if (compiled == null) {
GroovyShell shell = new GroovyShell(WarningsDescriptor.class.getClassLoader());
try {
compiled = shell.parse(script);
compiled = compile();
}
catch (CompilationFailedException exception) {
LOGGER.log(Level.SEVERE, "Groovy dynamic warnings parser: exception during compiling: ", exception);
}

compiled.getBinding().setVariable("falsePositive", falsePositive);
}
}
}

/**
* Compiles the script.
*
* @return the compiled script
* @throws CompilationFailedException if the script contains compile errors
*/
public Script compile() throws CompilationFailedException {
ClassLoader loader = GroovySandbox.createSecureClassLoader(WarningsDescriptor.class.getClassLoader());
Binding binding = new Binding();
binding.setVariable("falsePositive", falsePositive);
GroovyShell shell = new GroovyShell(loader, binding, GroovySandbox.createSecureCompilerConfiguration());
return shell.parse(script);
}

/**
* Creates a new annotation for the specified match.
*
Expand All @@ -64,16 +78,20 @@ private void compileScriptIfNotYetDone() {
* @param lineNumber
* the current line number
* @return a new annotation for the specified pattern
* @throws RejectedAccessException if the Groovy sandbox rejected the parsing script
*/
public Warning createWarning(final Matcher matcher, final int lineNumber) {
public Warning createWarning(final Matcher matcher, final int lineNumber) throws RejectedAccessException {
try {
Object result = run(matcher, lineNumber);
if (result instanceof Warning) {
return (Warning)result;
}
}
catch (RejectedAccessException exception) {
throw exception; // Groovy sandbox rejected the parsing script: needs to be presented to the user
}
catch (Exception exception) { // NOPMD NOCHECKSTYLE: catch all exceptions of the Groovy script
LOGGER.log(Level.SEVERE, "Groovy dynamic warnings parser: exception during parsing: ", exception);
LOGGER.log(Level.SEVERE, "Groovy dynamic warnings parser: exception during execution: ", exception);
}
return falsePositive;
}
Expand All @@ -86,15 +104,29 @@ public Warning createWarning(final Matcher matcher, final int lineNumber) {
* @param lineNumber
* the current line number
* @return unchecked result of the script
* @throws RejectedAccessException if the Groovy sandbox rejected the parsing script
*/
public Object run(final Matcher matcher, final int lineNumber) {
public Object run(final Matcher matcher, final int lineNumber) throws RejectedAccessException {
compileScriptIfNotYetDone();

Binding binding = compiled.getBinding();
binding.setVariable("matcher", matcher);
binding.setVariable("lineNumber", lineNumber);

return compiled.run();
try {
return GroovySandbox.runInSandbox(new Callable<Object>() {
@Override public Object call() throws Exception {
return compiled.run();
}
}, Whitelist.all());
}
catch (RejectedAccessException exception) {
throw exception; // Groovy sandbox rejected the parsing script: needs to be presented to the user
}
catch (Exception exception) {
LOGGER.log(Level.SEVERE, "Groovy dynamic warnings parser: exception during execution: ", exception);
return falsePositive;
}
}

/**
Expand Down

0 comments on commit 97ab4d2

Please sign in to comment.