Java tutorial
/* * Copyright 2012 Seitenbau * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.seitenbau.jenkins.plugins.dynamicparameter; import hudson.model.ParameterValue; import hudson.model.SimpleParameterDefinition; import hudson.model.Label; import hudson.model.StringParameterValue; import hudson.remoting.Callable; import hudson.remoting.VirtualChannel; import java.util.Collections; import java.util.Map; import java.util.List; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import net.sf.json.util.JSONUtils; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import org.kohsuke.stapler.StaplerRequest; import com.seitenbau.jenkins.plugins.dynamicparameter.scriptler.ScriptlerParameterDefinition; import com.seitenbau.jenkins.plugins.dynamicparameter.util.JenkinsUtils; /** * Base class for all script parameter definition classes. */ public abstract class BaseParameterDefinition extends SimpleParameterDefinition { /** Serial version UID. */ private static final long serialVersionUID = -4415132917610378545L; /** Logger. */ protected static final Logger logger = Logger.getLogger(ScriptlerParameterDefinition.class.getName()); /** UUID identifying the current parameter. */ private final UUID _uuid; /** Flag showing if the script should be executed remotely. */ private final Boolean _remote; /** * Constructor. * @param name parameter name * @param description parameter description * @param uuid UUID of the parameter definition * @param remote flag showing if the script should be executed remotely */ protected BaseParameterDefinition(String name, String description, String uuid, Boolean remote) { super(name, description); _remote = remote; if (StringUtils.length(uuid) == 0) { _uuid = UUID.randomUUID(); } else { _uuid = UUID.fromString(uuid); } } /** * Return a Parameter value object for a command line parameter. */ @Override public ParameterValue createValue(String value) { // Fix for issue https://github.com/Seitenbau/sb-jenkins-dynamicparameter/issues/3 StringParameterValue parameterValue = createStringParameterValueFor(this.getName(), value); return checkParameterValue(parameterValue); } /** * Should the script be executed to on a remote slave? * @return {@code true} if the script should be executed remotely */ public final boolean isRemote() { if (_remote == null) { return true; } return _remote; } /** * Get unique id for this parameter definition. * @return the _uuid */ public final UUID getUUID() { return _uuid; } /** * Get the script result as a list. * @return list of values if the script returns a non-null list; * {@link Collections#EMPTY_LIST}, otherwise */ @SuppressWarnings("unchecked") public final List<Object> getScriptResultAsList(Map<String, String> parameters) { Object value = executeScript(parameters); if (value instanceof List) { return (List<Object>) value; } String name = getName(); String msg = String.format( "Script parameter with name '%s' the value is not a instance of java.util.List the parameter value is : %s", name, value); logger.info(msg); return Collections.EMPTY_LIST; } /** * Get the script result as a string. * @return the default value generated by the script or {@code null} */ public final String getScriptResultAsString(Map<String, String> parameters) { Object value = executeScript(parameters); return ObjectUtils.toString(value, null); } @Override public final ParameterValue createValue(StaplerRequest req, JSONObject jo) { final JSONObject parameterJsonModel = new JSONObject(false); final Object value = jo.get("value"); final String valueAsText; if (JSONUtils.isArray(value)) { valueAsText = ((JSONArray) value).join(",", true); } else { valueAsText = String.valueOf(value); } parameterJsonModel.put("name", jo.get("name")); parameterJsonModel.put("value", valueAsText); StringParameterValue parameterValue = req.bindJSON(StringParameterValue.class, parameterJsonModel); parameterValue.setDescription(getDescription()); return checkParameterValue(parameterValue); } /** * Factory methods creates a String parameter value object for the given value. * @param value of the object * @return String parameter value object not null. */ private StringParameterValue createStringParameterValueFor(String name, String value) { String description = getDescription(); StringParameterValue parameterValue = new StringParameterValue(name, value, description); return parameterValue; } /** * Checks the validity of the given parameter value. The default implementation does nothing and * should be overridden. * @param value parameter value to check * @return if the value is valid the same parameter value * @throws IllegalArgumentException if the value in not valid */ protected StringParameterValue checkParameterValue(StringParameterValue value) { return value; } /** * Prepare a local call. * @return call instance * @throws Exception if a call instance cannot be created */ protected abstract Callable<Object, Throwable> prepareLocalCall(Map<String, String> parameters) throws Exception; /** * Prepare a remote call. * @param channel channel to the remote slave where the call will be executed * @return call instance * @throws Exception if a call instance cannot be created */ protected abstract Callable<Object, Throwable> prepareRemoteCall(VirtualChannel channel, Map<String, String> parameters) throws Exception; /** * Execute the current script either remotely or locally, depending on the remote flag. * @return script result */ private final Object executeScript(Map<String, String> parameters) { try { if (isRemote()) { Label label = JenkinsUtils.findProjectLabel(getUUID()); if (label == null) { logger.warning(String.format( "No label is assigned to project; script for parameter '%s' will be executed on master", getName())); } else { VirtualChannel channel = JenkinsUtils.findActiveChannel(label); if (channel == null) { logger.warning(String.format( "Cannot find an active node of the label '%s' where to execute the script", label.getDisplayName())); } else { Callable<Object, Throwable> call = prepareRemoteCall(channel, parameters); return channel.call(call); } } } Callable<Object, Throwable> call = prepareLocalCall(parameters); return call.call(); } catch (Throwable e) { String msg = String.format("Error during executing script for parameter '%s'", getName()); logger.log(Level.SEVERE, msg, e); } return null; } }