Java tutorial
// Copyright (c) 2015 Exquance Software Oy // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. package com.exquance.jenkins.plugins; import hudson.Extension; import hudson.Util; import hudson.console.AnnotatedLargeText; import hudson.model.Action; import hudson.model.Hudson; import hudson.model.Item; import hudson.model.Job; import hudson.triggers.Trigger; import hudson.triggers.TriggerDescriptor; import hudson.util.SequentialExecutionQueue; import hudson.util.StreamTaskListener; import jenkins.model.ParameterizedJobMixIn; import jenkins.triggers.SCMTriggerItem; import org.apache.commons.jelly.XMLOutput; import org.kohsuke.stapler.DataBoundConstructor; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.nio.charset.Charset; import java.text.DateFormat; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; /** */ public class HarbormasterTrigger extends Trigger<Job<?, ?>> { @DataBoundConstructor public HarbormasterTrigger() { } /** * Called when a POST is made. */ public void onPost(String triggeredByUser) { final String pushBy = triggeredByUser; getDescriptor().queue.execute(new Runnable() { private boolean runPolling() { try { StreamTaskListener listener = new StreamTaskListener(getLogFile()); try { PrintStream logger = listener.getLogger(); long start = System.currentTimeMillis(); logger.println("Started on " + DateFormat.getDateTimeInstance().format(new Date())); boolean result = SCMTriggerItem.SCMTriggerItems.asSCMTriggerItem(job).poll(listener) .hasChanges(); logger.println("Done. Took " + Util.getTimeSpanString(System.currentTimeMillis() - start)); if (result) logger.println("Changes found"); else logger.println("No changes"); return result; } catch (Error e) { e.printStackTrace(listener.error("Failed to record SCM polling")); LOGGER.log(Level.SEVERE, "Failed to record SCM polling", e); throw e; } catch (RuntimeException e) { e.printStackTrace(listener.error("Failed to record SCM polling")); LOGGER.log(Level.SEVERE, "Failed to record SCM polling", e); throw e; } finally { listener.close(); } } catch (IOException e) { LOGGER.log(Level.SEVERE, "Failed to record SCM polling", e); } return false; } public void run() { if (runPolling()) { String name = " #" + job.getNextBuildNumber(); HarbormasterPushCause cause; try { cause = new HarbormasterPushCause(getLogFile(), pushBy); } catch (IOException e) { LOGGER.log(Level.WARNING, "Failed to parse the polling log", e); cause = new HarbormasterPushCause(pushBy); } ParameterizedJobMixIn pJob = new ParameterizedJobMixIn() { @Override protected Job asJob() { return job; } }; if (pJob.scheduleBuild(cause)) { LOGGER.info("SCM changes detected in " + job.getName() + ". Triggering " + name); } else { LOGGER.info("SCM changes detected in " + job.getName() + ". Job is already in the queue"); } } } }); } @Override public Collection<? extends Action> getProjectActions() { return Collections.singleton(new HarbormasterWebHookPollingAction()); } /** * Returns the file that records the last/current polling activity. */ public File getLogFile() { return new File(job.getRootDir(), "harbormaster-polling.log"); } /** * Check if "harbormaster-polling.log" already exists to initialize it */ public boolean IsLogFileInitialized() { File file = new File(job.getRootDir(), "harbormaster-polling.log"); return file.exists(); } @Override public DescriptorImpl getDescriptor() { return (DescriptorImpl) super.getDescriptor(); } /** * Action object for {@link Project}. Used to display the polling log. */ public final class HarbormasterWebHookPollingAction implements Action { public Job<?, ?> getOwner() { return job; } public String getIconFileName() { return "clipboard.png"; } public String getDisplayName() { return "Harbormaster Hook Log"; } public String getUrlName() { return "HarbormasterPollLog"; } public String getLog() throws IOException { return Util.loadFile(getLogFile()); } /** * Writes the annotated log to the given output. */ public void writeLogTo(XMLOutput out) throws IOException { new AnnotatedLargeText<HarbormasterWebHookPollingAction>(getLogFile(), Charset.defaultCharset(), true, this).writeHtmlTo(0, out.asWriter()); } } @Extension public static class DescriptorImpl extends TriggerDescriptor { private transient final SequentialExecutionQueue queue = new SequentialExecutionQueue( Hudson.MasterComputer.threadPoolForRemoting); @Override public boolean isApplicable(Item item) { return item instanceof Job && SCMTriggerItem.SCMTriggerItems.asSCMTriggerItem(item) != null && item instanceof ParameterizedJobMixIn.ParameterizedJob; } @Override public String getDisplayName() { return "Build when a change is pushed to Diffusion"; } } private static final Logger LOGGER = Logger.getLogger(HarbormasterTrigger.class.getName()); }