/**
* Hudson Sametime Plugin
*/
package hudson.plugins.sametime.im.transport;
import hudson.Util;
import hudson.model.AbstractProject;
import hudson.util.FormValidation;
import hudson.model.Describable;
import hudson.model.Descriptor;
import hudson.plugins.sametime.im.IMException;
import hudson.plugins.sametime.im.IMMessageTargetConversionException;
import hudson.plugins.sametime.tools.Assert;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Publisher;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.ServletException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.io.IOException;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.QueryParameter;
/**
* Descriptor for the SametimePublisher. A Descriptor is an object that has metadata about a {@link Describable}
* object, and also serves as a factory.
*
* @author Jamie Burrell
* @since 18 Jan 2008
*/
public class SametimePublisherDescriptor extends BuildStepDescriptor<Publisher>
{
private static final String PREFIX = "sametimePlugin.";
/** Name for the PORT parameter, as it appears in the jelly scripts */
public static final String PARAMETERNAME_PORT = SametimePublisherDescriptor.PREFIX + "port";
/** Name for the HOSTNAME parameter, as it appears in the jelly scripts */
public static final String PARAMETERNAME_HOSTNAME = SametimePublisherDescriptor.PREFIX + "hostname";
/** Name for the PRESENCE parameter, as it appears in the jelly scripts */
public static final String PARAMETERNAME_PRESENCE = SametimePublisherDescriptor.PREFIX + "exposePresence";
/** Name for the PASSWORD parameter, as it appears in the jelly scripts */
public static final String PARAMETERNAME_PASSWORD = SametimePublisherDescriptor.PREFIX + "password";
/** Name for the NICKNAME parameter, as it appears in the jelly scripts */
public static final String PARAMETERNAME_NICKNAME = SametimePublisherDescriptor.PREFIX + "nick";
/** Name for the TARGETS parameter, as it appears in the jelly scripts */
public static final String PARAMETERNAME_TARGETS = SametimePublisherDescriptor.PREFIX + "targets";
/** Name for the STRATEGY parameter, as it appears in the jelly scripts */
public static final String PARAMETERNAME_STRATEGY = SametimePublisherDescriptor.PREFIX + "strategy";
/** Name for the NOTIFY_START parameter, as it appears in the jelly scripts */
public static final String PARAMETERNAME_NOTIFY_START = SametimePublisherDescriptor.PREFIX + "notifyStart";
/** Name for the NOTIFY_SUSPECTS parameter, as it appears in the jelly scripts */
public static final String PARAMETERNAME_NOTIFY_SUSPECTS = SametimePublisherDescriptor.PREFIX + "notifySuspects";
/** Name for the NOTIFY_FIXERS parameter, as it appears in the jelly scripts */
public static final String PARAMETERNAME_NOTIFY_FIXERS = SametimePublisherDescriptor.PREFIX + "notifyFixers";
/** Name for the INITIAL_GROUPCHATS parameter, as it appears in the jelly scripts */
public static final String PARAMETERNAME_INITIAL_GROUPCHATS = SametimePublisherDescriptor.PREFIX + "initialGroupChats";
/** Name for the COMMAND_PREFIX parameter, as it appears in the jelly scripts */
public static final String PARAMETERNAME_COMMAND_PREFIX = SametimePublisherDescriptor.PREFIX + "commandPrefix";
/** Default value for the STRATEGY_ALL parameter */
public static final String PARAMETERVALUE_STRATEGY_ALL = "all";
/** Default value for the STRATEGY_FAILURE parameter */
public static final String PARAMETERVALUE_STRATEGY_FAILURE = "failure";
/** Default value for the STRATEGY_STATE_CHANGE parameter */
public static final String PARAMETERVALUE_STRATEGY_STATE_CHANGE = "change";
/** Default value for the STRATEGY_VALUES parameter */
public static final String[] PARAMETERVALUE_STRATEGY_VALUES = {
PARAMETERVALUE_STRATEGY_ALL,
PARAMETERVALUE_STRATEGY_FAILURE,
PARAMETERVALUE_STRATEGY_STATE_CHANGE
};
/** Default value for the STRATEGY_DEFAULT parameter */
public static final String PARAMETERVALUE_STRATEGY_DEFAULT = PARAMETERVALUE_STRATEGY_STATE_CHANGE;
/** DEFAULT_COMMAND_PREFIX */
public static final String DEFAULT_COMMAND_PREFIX = "!";
private int port = 5222;
private String hostname = null;
private String hudsonNickname = "hudson";
private String hudsonPassword = "secret";
private boolean exposePresence = true;
private String initialGroupChats = null;
private String commandPrefix = DEFAULT_COMMAND_PREFIX;
/**
* Constructor.
*/
public SametimePublisherDescriptor()
{
super(SametimePublisher.class);
load();
try
{
SametimeIMConnectionProvider.getInstance().createConnection(this);
}
catch (final IMException dontCare)
{
// Server temporarily unavailable ?
dontCare.printStackTrace();
}
}
/**
* Sets the hostname, amd attempts to get a response from the host itself.
* @param req The form request.
* @throws FormException
*/
private void applyHostname(final HttpServletRequest req) throws FormException
{
final String s = req.getParameter(SametimePublisherDescriptor.PARAMETERNAME_HOSTNAME);
if (s != null && s.trim().length() > 0)
{
try
{
InetAddress.getByName(s); // try to resolve
this.hostname = s;
}
catch (final UnknownHostException e)
{
throw new FormException("Cannot find Host '" + s + "'.",
SametimePublisherDescriptor.PARAMETERNAME_HOSTNAME);
}
}
else
{
this.hostname = null;
}
}
/**
* Sets the user name, and does some validation.
* @param req The form request
* @throws FormException
*/
private void applyNickname(final HttpServletRequest req) throws FormException
{
this.hudsonNickname = req.getParameter(SametimePublisherDescriptor.PARAMETERNAME_NICKNAME);
if (this.hostname != null && (this.hudsonNickname == null || this.hudsonNickname.trim().length() == 0))
{
throw new FormException("Account/Nickname cannot be empty.",
SametimePublisherDescriptor.PARAMETERNAME_NICKNAME);
}
}
/**
* Sets the password, and does some validation.
* @param req The form request
* @throws FormException
*/
private void applyPassword(final HttpServletRequest req) throws FormException
{
this.hudsonPassword = req.getParameter(SametimePublisherDescriptor.PARAMETERNAME_PASSWORD);
if (this.hostname != null && this.hudsonPassword == null || this.hudsonPassword.trim().length() == 0)
{
throw new FormException("Password cannot be empty.", SametimePublisherDescriptor.PARAMETERNAME_PASSWORD);
}
}
/**
* Sets the port, and does some validation.
* @param req The form request
* @throws FormException
*/
private void applyPort(final HttpServletRequest req) throws FormException
{
final String p = Util.fixEmptyAndTrim(req.getParameter(SametimePublisherDescriptor.PARAMETERNAME_PORT));
if (p != null)
{
try
{
final int i = Integer.parseInt(p);
if (i < 0 || i > 65535)
{
throw new FormException("Port out of range.", SametimePublisherDescriptor.PARAMETERNAME_PORT);
}
this.port = i;
}
catch (final NumberFormatException e)
{
throw new FormException("Port cannot be parsed.", SametimePublisherDescriptor.PARAMETERNAME_PORT);
}
} else {
this.port = 5222;
}
}
/**
* Sets the presence option.
* @param req The form request
*/
private void applyPresence(final HttpServletRequest req)
{
this.exposePresence = req.getParameter(SametimePublisherDescriptor.PARAMETERNAME_PRESENCE) != null;
}
/**
* Sets the group chats to initally enter
* @param req The form request
*/
private void applyInitialGroupChats(final HttpServletRequest req) {
this.initialGroupChats = Util.fixEmptyAndTrim(req.getParameter(SametimePublisherDescriptor.PARAMETERNAME_INITIAL_GROUPCHATS));
}
/**
* Sets the prefix for bot commands
* @param req The form request
*/
private void applyCommandPrefix(final HttpServletRequest req) {
String commandPrefix = req.getParameter(SametimePublisherDescriptor.PARAMETERNAME_COMMAND_PREFIX);
if (commandPrefix != null && commandPrefix.trim().length() > 0) {
this.commandPrefix = commandPrefix;
} else {
this.commandPrefix = DEFAULT_COMMAND_PREFIX;
}
}
/**
* This human readable name is used in the configuration screen.
*/
@Override
public String getDisplayName()
{
return "Sametime Notification";
}
/**
* Returns the text to be put into the form field.
* If the port is default, leave it empty.
* @return The text.
*/
public String getPortString() {
if(port==5222) return null;
else return String.valueOf(port);
}
/**
* Whether to show up on Sametime as accessible.
* @return <code>true</code> or <code>false</code>
*/
public boolean isExposePresence()
{
return this.exposePresence;
}
/**
* Gets the whitespace separated list of group chats to join,
* or null if nothing is configured.
* @return The list.
*/
public String getInitialGroupChats() {
return Util.fixEmptyAndTrim(this.initialGroupChats);
}
/**
* Accessor for the prefix used in sending commands.
* @return The prefix.
*/
public String getCommandPrefix() {
return this.commandPrefix;
}
@Override
public boolean isApplicable(Class<? extends AbstractProject> jobType) {
return true;
}
/**
* Creates a new instance of {@link SametimePublisher} from a submitted form.
*/
@Override
public SametimePublisher newInstance(final StaplerRequest req, JSONObject formData) throws FormException
{
Assert.isNotNull(req, "Parameter 'req' must not be null.");
final String t = req.getParameter(SametimePublisherDescriptor.PARAMETERNAME_TARGETS);
String n = req.getParameter(SametimePublisherDescriptor.PARAMETERNAME_STRATEGY);
if (n == null) {
n = PARAMETERVALUE_STRATEGY_DEFAULT;
} else {
boolean foundStrategyValueMatch = false;
for (final String strategyValue : PARAMETERVALUE_STRATEGY_VALUES) {
if (strategyValue.equals(n)) {
foundStrategyValueMatch = true;
break;
}
}
if (! foundStrategyValueMatch) {
n = PARAMETERVALUE_STRATEGY_DEFAULT;
}
}
final String s = req.getParameter(SametimePublisherDescriptor.PARAMETERNAME_NOTIFY_START);
final String ns = req.getParameter(SametimePublisherDescriptor.PARAMETERNAME_NOTIFY_SUSPECTS);
final String nf = req.getParameter(SametimePublisherDescriptor.PARAMETERNAME_NOTIFY_FIXERS);
try
{
return new SametimePublisher(t, n,
(s != null && "on".equals(s)),
(ns != null && "on".equals(ns)),
(nf != null && "on".equals(nf)));
}
catch (final IMMessageTargetConversionException e)
{
throw new FormException(e, SametimePublisherDescriptor.PARAMETERNAME_TARGETS);
}
}
/**
* Shuts down the connection etc.
*/
public void shutdown()
{
final SametimeIMConnectionProvider factory = SametimeIMConnectionProvider.getInstance();
factory.releaseConnection();
}
/* (non-Javadoc)
* @see hudson.model.Descriptor#configure(org.kohsuke.stapler.StaplerRequest)
*/
@Override
public boolean configure(StaplerRequest req, JSONObject formData) throws hudson.model.Descriptor.FormException {
Assert.isNotNull(req, "Parameter 'req' must not be null.");
applyPresence(req);
applyHostname(req);
applyPort(req);
applyNickname(req);
applyPassword(req);
applyInitialGroupChats(req);
applyCommandPrefix(req);
try
{
SametimeIMConnectionProvider.getInstance().createConnection(this);
}
catch (final Exception e)
{
throw new FormException("Unable to create Client: " + e, null);
}
save();
return super.configure(req, formData);
}
/**
* Validates the server name.
* @param req The Stapler request
* @param rsp The response
* @throws IOException
* @throws ServletException
*/
public FormValidation doServerCheck(@QueryParameter final String value) {
String v = Util.fixEmptyAndTrim(value);
if (v != null) {
try {
InetAddress.getByName(v);
} catch (UnknownHostException e) {
return FormValidation.error("Unknown host "+v);
}
}
return FormValidation.ok();
}
/**
* Getter method for the port field.
*
* @return The port property.
*/
public int getPort()
{
return port;
}
/**
* Getter method for the hostname field.
*
* @return The hostname property.
*/
public String getHostname()
{
return hostname;
}
/**
* Getter method for the hudsonNickname field.
*
* @return The hudsonNickname property.
*/
public String getHudsonNickname()
{
return hudsonNickname;
}
/**
* Getter method for the hudsonPassword field.
*
* @return The hudsonPassword property.
*/
public String getHudsonPassword()
{
return hudsonPassword;
}
}