package hudson.plugins.emailext.plugins.content; import hudson.FilePath; import hudson.model.Item; import hudson.model.Run; import hudson.model.TaskListener; import hudson.plugins.emailext.ExtendedEmailPublisherDescriptor; import hudson.plugins.emailext.JellyTemplateConfig.JellyTemplateConfigProvider; import hudson.plugins.emailext.plugins.EmailToken; import jenkins.model.Jenkins; import org.apache.commons.io.IOUtils; import org.apache.commons.jelly.JellyContext; import org.apache.commons.jelly.JellyException; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.Script; import org.apache.commons.jelly.XMLOutput; import org.jenkinsci.lib.configprovider.ConfigProvider; import org.jenkinsci.plugins.scriptsecurity.scripts.ApprovalContext; import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval; import org.jenkinsci.plugins.scriptsecurity.scripts.languages.GroovyLanguage; import org.jenkinsci.plugins.scriptsecurity.scripts.languages.JellyLanguage; import org.jenkinsci.plugins.tokenmacro.MacroEvaluationException; import org.xml.sax.InputSource; import javax.annotation.Nonnull; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.nio.file.attribute.UserDefinedFileAttributeView; @EmailToken public class JellyScriptContent extends AbstractEvalContent { public static final String MACRO_NAME = "JELLY_SCRIPT"; private static final String DEFAULT_HTML_TEMPLATE_NAME = "html"; private static final String DEFAULT_TEMPLATE_NAME = DEFAULT_HTML_TEMPLATE_NAME; public static final String JELLY_EXTENSION = ".jelly"; @Parameter public String template = DEFAULT_TEMPLATE_NAME; public JellyScriptContent() { super(MACRO_NAME); } @Override public String evaluate(@Nonnull Run<?, ?> run, FilePath workspace, @Nonnull TaskListener listener, String macroName) throws MacroEvaluationException, IOException, InterruptedException { InputStream inputStream = null; try { inputStream = getFileInputStream(workspace, template, JELLY_EXTENSION); return renderContent(run, inputStream, listener); } catch (JellyException e) { return "JellyException: " + e.getMessage(); } catch (FileNotFoundException e) { return generateMissingFile("Jelly", template); } finally { IOUtils.closeQuietly(inputStream); } } @Override protected Class<? extends ConfigProvider> getProviderClass() { return JellyTemplateConfigProvider.class; } private String renderContent(@Nonnull Run<?, ?> build, InputStream inputStream, @Nonnull TaskListener listener) throws JellyException, IOException { String rawScript = IOUtils.toString(inputStream); if (inputStream instanceof UserProvidedContentInputStream) { Item parent = build.getParent(); ScriptApproval.get().configuring(rawScript, JellyLanguage.get(), ApprovalContext.create().withItem(parent)); ScriptApproval.get().using(rawScript, JellyLanguage.get()); } JellyContext context = createContext(new ScriptContentBuildWrapper(build), build, listener); Script script = context.compileScript(new InputSource(new StringReader(rawScript))); if (script != null) { return convert(build, context, script); } return null; } private String convert(Run<?, ?> build, JellyContext context, Script script) throws JellyTagException, IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(16 * 1024); XMLOutput xmlOutput = XMLOutput.createXMLOutput(output); script.run(context, xmlOutput); xmlOutput.flush(); xmlOutput.close(); output.close(); return output.toString(getCharset(build)); } private JellyContext createContext(Object it, @Nonnull Run<?, ?> build, @Nonnull TaskListener listener) { JellyContext context = new JellyContext(); ExtendedEmailPublisherDescriptor descriptor = Jenkins.getActiveInstance().getDescriptorByType(ExtendedEmailPublisherDescriptor.class); context.setVariable("it", it); context.setVariable("build", build); context.setVariable("project", build.getParent()); context.setVariable("logger", listener.getLogger()); context.setVariable("rooturl", descriptor.getHudsonUrl()); return context; } }