package jenkins;
import hudson.Extension;
import hudson.ExtensionList;
import hudson.ExtensionPoint;
import hudson.TcpSlaveAgentListener;
import java.io.IOException;
import java.net.Socket;
import java.util.Set;
import jenkins.model.Jenkins;
/**
* Pluggable Jenkins TCP agent protocol handler called from {@link TcpSlaveAgentListener}.
*
* <p>
* To register your extension, put {@link Extension} annotation on your subtype.
* Implementations of this extension point is singleton, and its {@link #handle(Socket)} method
* gets invoked concurrently whenever a new connection comes in.
*
* @author Kohsuke Kawaguchi
* @since 1.467
* @see TcpSlaveAgentListener
*/
public abstract class AgentProtocol implements ExtensionPoint {
/**
* Allow experimental {@link AgentProtocol} implementations to declare being opt-in.
* Note that {@link Jenkins#setAgentProtocols(Set)} only records the protocols where the admin has made a
* conscious decision thus:
* <ul>
* <li>if a protocol is opt-in, it records the admin enabling it</li>
* <li>if a protocol is opt-out, it records the admin disabling it</li>
* </ul>
* Implementations should not transition rapidly from {@code opt-in -> opt-out -> opt-in}.
* Implementations should never flip-flop: {@code opt-in -> opt-out -> opt-in -> opt-out} as that will basically
* clear any preference that an admin has set. This latter restriction should be ok as we only ever will be
* adding new protocols and retiring old ones.
*
* @return {@code true} if the protocol requires explicit opt-in.
* @since 2.16
* @see Jenkins#setAgentProtocols(Set)
*/
public boolean isOptIn() {
return false;
}
/**
* Allow essential {@link AgentProtocol} implementations (basically {@link TcpSlaveAgentListener.PingAgentProtocol})
* to be always enabled.
*
* @return {@code true} if the protocol can never be disabled.
* @since 2.16
*/
public boolean isRequired() {
return false;
}
/**
* Protocol name.
*
* This is a short string that consists of printable ASCII chars. Sent by the client to select the protocol.
*
* @return
* null to be disabled. This is useful for avoiding getting used
* until the protocol is properly configured.
*/
public abstract String getName();
/**
* Returns the human readable protocol display name.
*
* @return the human readable protocol display name.
* @since 2.16
*/
public String getDisplayName() {
return getName();
}
/**
* Called by the connection handling thread to execute the protocol.
*/
public abstract void handle(Socket socket) throws IOException, InterruptedException;
/**
* Returns all the registered {@link AgentProtocol}s.
*/
public static ExtensionList<AgentProtocol> all() {
return ExtensionList.lookup(AgentProtocol.class);
}
public static AgentProtocol of(String protocolName) {
for (AgentProtocol p : all()) {
String n = p.getName();
if (n!=null && n.equals(protocolName))
return p;
}
return null;
}
}