package hudson.plugins.accurev;
import com.cloudbees.plugins.credentials.CredentialsMatchers;
import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.CredentialsScope;
import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
import com.cloudbees.plugins.credentials.domains.DomainRequirement;
import com.cloudbees.plugins.credentials.domains.URIRequirementBuilder;
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl;
import hudson.*;
import hudson.model.*;
import hudson.plugins.accurev.cmd.Login;
import hudson.plugins.accurev.cmd.ShowDepots;
import hudson.plugins.accurev.cmd.ShowStreams;
import hudson.plugins.accurev.delegates.AbstractModeDelegate;
import hudson.scm.*;
import hudson.security.ACL;
import hudson.util.ComboBoxModel;
import hudson.util.FormValidation;
import hudson.util.ListBoxModel;
import hudson.util.Secret;
import jenkins.model.Jenkins;
import jenkins.plugins.accurev.AccurevTool;
import jenkins.plugins.accurev.util.UUIDUtils;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Logger;
/**
* @author connollys
* @since 09-Oct-2007 16:17:34
*/
public class AccurevSCM extends SCM {
// ------------------------------ FIELDS ------------------------------
static final Date NO_TRANS_DATE = new Date(0);
private static final Logger LOGGER = Logger.getLogger(AccurevSCM.class.getName());
private final String depot;
private final String stream;
private String serverName;
private boolean ignoreStreamParent;
private String wspaceORreftree;
private boolean cleanreftree;
private String workspace;
private boolean useSnapshot;
private boolean dontPopContent;
private String snapshotNameFormat;
private boolean synctime;
private String reftree;
private String subPath;
private String filterForPollSCM;
private String directoryOffset;
private boolean useReftree;
private boolean useWorkspace;
private boolean noWspaceNoReftree;
private String serverUUID;
@CheckForNull
private String accurevTool = null;
private Job<?, ?> activeProject;
// --------------------------- CONSTRUCTORS ---------------------------
@DataBoundConstructor
public AccurevSCM(
String serverUUID, String depot, String stream
) {
this.serverUUID = serverUUID;
this.depot = depot;
this.stream = stream;
AccurevServer server = getDescriptor().getServer(serverUUID);
if (server != null) serverName = server.getName();
updateMode();
}
public static AccurevSCMDescriptor configuration() {
return Jenkins.getInstance().getDescriptorByType(AccurevSCMDescriptor.class);
}
// --------------------- GETTER / SETTER METHODS ---------------------
public String getDepot() {
return depot;
}
public String getServerName() {
return serverName;
}
@DataBoundSetter
public void setServerName(String serverName) {
this.serverName = serverName;
}
public String getServerUUID() {
return serverUUID;
}
public void setServerUUID(String uuid) {
serverUUID = uuid;
}
/**
* Getter for Accurev server
*
* @return AccurevServer based on serverUUID (or serverName if serverUUID is null)
*/
@CheckForNull
public AccurevServer getServer() {
AccurevServer server;
AccurevSCMDescriptor descriptor = getDescriptor();
if (serverUUID == null) {
if (serverName == null) {
// No fallback
LOGGER.severe("AccurevSCM.getServer called but serverName and serverUUID are NULL!");
return null;
}
LOGGER.warning("Getting server by name (" + serverName + "), because UUID is not set.");
server = descriptor.getServer(serverName);
if (server != null) {
this.setServerUUID(server.getUuid());
descriptor.save();
}
} else {
server = descriptor.getServer(serverUUID);
}
return server;
}
public String getStream() {
return stream;
}
public String getWspaceORreftree() {
return wspaceORreftree;
}
@DataBoundSetter
public void setWspaceORreftree(String wspaceORreftree) {
this.wspaceORreftree = wspaceORreftree;
updateMode();
}
public String getReftree() {
return reftree;
}
@DataBoundSetter
public void setReftree(String reftree) {
this.reftree = reftree;
}
public String getWorkspace() {
return workspace;
}
@DataBoundSetter
public void setWorkspace(String workspace) {
this.workspace = workspace;
}
@CheckForNull
public String getAccurevTool() {
return accurevTool;
}
@DataBoundSetter
public void setAccurevTool(String accurevTool) {
this.accurevTool = accurevTool;
}
public String getSubPath() {
return subPath;
}
@DataBoundSetter
public void setSubPath(String subPath) {
this.subPath = subPath;
}
public String getFilterForPollSCM() {
return filterForPollSCM;
}
@DataBoundSetter
public void setFilterForPollSCM(String filterForPollSCM) {
this.filterForPollSCM = filterForPollSCM;
}
public String getSnapshotNameFormat() {
return snapshotNameFormat;
}
@DataBoundSetter
public void setSnapshotNameFormat(String snapshotNameFormat) {
this.snapshotNameFormat = snapshotNameFormat;
}
public boolean isIgnoreStreamParent() {
return ignoreStreamParent;
}
@DataBoundSetter
public void setIgnoreStreamParent(boolean ignoreStreamParent) {
this.ignoreStreamParent = ignoreStreamParent;
}
public boolean isSynctime() {
return synctime;
}
@DataBoundSetter
public void setSynctime(boolean synctime) {
this.synctime = synctime;
}
public boolean isDontPopContent() {
return dontPopContent;
}
@DataBoundSetter
public void setDontPopContent(boolean dontPopContent) {
this.dontPopContent = dontPopContent;
}
public boolean isCleanreftree() {
return cleanreftree;
}
@DataBoundSetter
public void setCleanreftree(boolean cleanreftree) {
this.cleanreftree = cleanreftree;
}
public boolean isUseSnapshot() {
return useSnapshot;
}
@DataBoundSetter
public void setUseSnapshot(boolean useSnapshot) {
this.useSnapshot = useSnapshot;
if (!useSnapshot) {
snapshotNameFormat = "";
}
}
public boolean isUseReftree() {
return useReftree;
}
public boolean isUseWorkspace() {
return useWorkspace;
}
public boolean isNoWspaceNoReftree() {
return noWspaceNoReftree;
}
public String getDirectoryOffset() {
return directoryOffset;
}
@DataBoundSetter
public void setDirectoryOffset(String directoryOffset) {
this.directoryOffset = directoryOffset;
}
// ------------------------ INTERFACE METHODS ------------------------
// --------------------- Interface Describable ---------------------
private void updateMode() {
AccurevMode accurevMode = AccurevMode.findMode(this);
useReftree = accurevMode.isReftree();
useWorkspace = accurevMode.isWorkspace();
noWspaceNoReftree = accurevMode.isNoWorkspaceOrRefTree();
}
/**
* {@inheritDoc}
*
* @return SCMDescriptor
*/
@Override
public AccurevSCMDescriptor getDescriptor() {
return (AccurevSCMDescriptor) super.getDescriptor();
}
// -------------------------- OTHER METHODS --------------------------
/**
* Exposes AccuRev-specific information to the environment. The following
* variables become available, if not null:
* <ul>
* <li>ACCUREV_DEPOT - The depot name</li>
* <li>ACCUREV_STREAM - The stream name</li>
* <li>ACCUREV_SERVER - The server name</li>
* <li>ACCUREV_REFTREE - The workspace name</li>
* <li>ACCUREV_SUBPATH - The workspace subpath</li>
* </ul>
*
* @param build build
* @param env enviroments
* @since 0.6.9
*/
@Override
public void buildEnvVars(AbstractBuild<?, ?> build, Map<String, String> env) {
// call super even though SCM.buildEnvVars currently does nothing - this could change
super.buildEnvVars(build, env);
AbstractModeDelegate delegate = AccurevMode.findDelegate(this);
delegate.buildEnvVars(build, env);
}
/**
* {@inheritDoc}
*
* @param build build
* @param launcher launcher
* @param workspace jenkins workspace
* @param listener listener
* @param changelogFile change log file
* @param baseline SCMRevisionState
* @throws java.io.IOException on failing IO
* @throws java.lang.InterruptedException on failing interrupt
*/
public void checkout(@Nonnull Run<?, ?> build, @Nonnull Launcher launcher, @Nonnull FilePath workspace,
@Nonnull TaskListener listener, @CheckForNull File changelogFile,
@CheckForNull SCMRevisionState baseline) throws IOException, InterruptedException {
// TODO: Implement SCMRevisionState?
boolean checkout = AccurevMode.findDelegate(this).checkout(build, launcher, workspace, listener, changelogFile);
if (checkout) listener.getLogger().println("Checkout done");
else listener.getLogger().println("Checkout failed");
}
/**
* {@inheritDoc}
*
* @return ChangeLogParser
*/
public ChangeLogParser createChangeLogParser() {
return new AccurevChangeLogParser();
}
@Override
public boolean requiresWorkspaceForPolling() {
boolean requiresWorkspace = AccurevMode.findMode(this).isRequiresWorkspace();
if (getDescriptor().isPollOnMaster() && !requiresWorkspace) {
// Does not require workspace if Poll On Master is enabled; unless build is using workspace
return false;
}
if (activeProject != null && !activeProject.isBuilding()) {
// Check if project is no longer active.
activeProject = null;
}
// Return true if activeProject null and it does require a workspace, otherwise false.
return requiresWorkspace && activeProject == null;
}
/**
* Gets the lock to be used on "normal" accurev commands, or
* <code>null</code> if command synchronization is switched off.
*
* @return See above.
*/
public Lock getOptionalLock() {
final AccurevServer server = getServer();
final boolean shouldLock = server != null && server.isSyncOperations();
if (shouldLock) {
return getMandatoryLock();
} else {
return null;
}
}
/**
* Gets the lock to be used on accurev commands where synchronization is
* mandatory.
*
* @return See above.
*/
private Lock getMandatoryLock() {
return AccurevSCMDescriptor.ACCUREV_LOCK;
}
@Override
public SCMRevisionState calcRevisionsFromBuild(@Nonnull Run<?, ?> build, @Nullable FilePath workspace,
@Nullable Launcher launcher, @Nonnull TaskListener listener) throws IOException, InterruptedException {
// TODO: Implement SCMRevisionState?
return SCMRevisionState.NONE;
}
@Override
public PollingResult compareRemoteRevisionWith(@Nonnull Job<?, ?> project, @Nullable Launcher launcher,
@Nullable FilePath workspace, @Nonnull TaskListener listener,
@Nonnull SCMRevisionState baseline) throws IOException, InterruptedException {
// TODO: Implement SCMRevisionState?
if (activeProject != null && activeProject.isBuilding()) {
// Skip polling while there is an active project.
// This will prevent waiting for the workspace to become available.
return PollingResult.NO_CHANGES;
}
activeProject = project;
AbstractModeDelegate delegate = AccurevMode.findDelegate(this);
return delegate.compareRemoteRevisionWith(project, launcher, workspace, listener, baseline);
}
public boolean hasStringVariableReference(final String str) {
return StringUtils.isNotEmpty(str) && str.startsWith("$");
}
/**
* @param project Running build
* @param listener Listener that it runs the build on
* @return Stream name tries to expand Variable reference to a String
* @throws IllegalArgumentException Thrown when Variable reference is not supported or cannot expand
*/
public String getPollingStream(Job<?, ?> project, TaskListener listener) throws IllegalArgumentException {
String parsedLocalStream;
if (hasStringVariableReference(stream)) {
ParametersDefinitionProperty paramDefProp = project
.getProperty(ParametersDefinitionProperty.class);
if (paramDefProp == null) {
throw new IllegalArgumentException(
"Polling is not supported when stream name has a variable reference '" + stream + "'.");
}
Map<String, String> keyValues = new TreeMap<>();
/* Scan for all parameter with an associated default values */
for (ParameterDefinition paramDefinition : paramDefProp.getParameterDefinitions()) {
ParameterValue defaultValue = paramDefinition.getDefaultParameterValue();
if (defaultValue instanceof StringParameterValue) {
StringParameterValue strdefvalue = (StringParameterValue) defaultValue;
keyValues.put(defaultValue.getName(), strdefvalue.value);
}
}
final EnvVars environment = new EnvVars(keyValues);
parsedLocalStream = environment.expand(getStream());
listener.getLogger().println("... expanded '" + stream + "' to '" + parsedLocalStream + "'.");
} else {
parsedLocalStream = stream;
}
if (hasStringVariableReference(parsedLocalStream)) {
throw new IllegalArgumentException(
"Failed to expand variable reference '" + stream + "'.");
}
return parsedLocalStream;
}
//--------------------------- Inner Class - DescriptorImplementation ----------------------------
@Extension
public static class AccurevSCMDescriptor extends SCMDescriptor<AccurevSCM> implements ModelObject {
/**
* The accurev server has been known to crash if more than one copy of
* the accurev has been run concurrently on the local machine. <br>
* Also, the accurev client has been known to complain that it's not
* logged in if another client on the same machine logs in again.
*/
transient static final Lock ACCUREV_LOCK = new ReentrantLock();
private static final Logger DESCRIPTORLOGGER = Logger.getLogger(AccurevSCMDescriptor.class.getName());
private List<AccurevServer> _servers;
// The servers field is here for backwards compatibility.
// The transient modifier means it won't be written to the config file
private transient List<AccurevServer> servers;
private boolean pollOnMaster;
/**
* Constructs a new AccurevSCMDescriptor.
*/
public AccurevSCMDescriptor() {
super(AccurevSCM.class, null);
load();
}
public static void lock() {
ACCUREV_LOCK.lock();
}
public static void unlock() {
ACCUREV_LOCK.unlock();
}
/**
* {@inheritDoc}
*
* @return String
*/
@Override
@Nonnull
public String getDisplayName() {
return "AccuRev";
}
@SuppressWarnings("unused") // used by stapler
public boolean showAccurevToolOptions() {
return Jenkins.getInstance().getDescriptorByType(AccurevTool.DescriptorImpl.class).getInstallations().length > 1;
}
/**
* Lists available tool installations.
*
* @return list of available accurev tools
*/
public List<AccurevTool> getAccurevTools() {
AccurevTool[] accurevToolInstallations = Jenkins.getInstance().getDescriptorByType(AccurevTool.DescriptorImpl.class).getInstallations();
return Arrays.asList(accurevToolInstallations);
}
/**
* {@inheritDoc}
*
* @param req request
* @param formData json object
* @return boolean
* @throws hudson.model.Descriptor.FormException if form data is incorrect/incomplete
*/
@Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
req.bindJSON(this, formData);
save();
return true;
}
/**
* Getter for property 'servers'.
*
* @return Value for property 'servers'.
*/
@Nonnull
public List<AccurevServer> getServers() {
if (this._servers == null) {
this._servers = new ArrayList<>();
}
// We put this here to maintain backwards compatibility
// because we changed the name of the 'servers' field to '_servers'
if (this.servers != null) {
this._servers.addAll(servers);
servers = null;
}
return this._servers;
}
/**
* Setter for property 'servers'.
*
* @param servers Value to set for property 'servers'.
*/
public void setServers(List<AccurevServer> servers) {
this._servers = servers;
}
/**
* Getter for property 'pollOnMaster'.
*
* @return Value for property 'pollOnMaster'.
*/
public boolean isPollOnMaster() {
return pollOnMaster;
}
/**
* Setter for property 'pollOnMaster'.
*
* @param pollOnMaster poll on aster
*/
public void setPollOnMaster(boolean pollOnMaster) {
this.pollOnMaster = pollOnMaster;
}
@CheckForNull
public AccurevServer getServer(String uuid) {
if (uuid == null || this._servers == null) {
LOGGER.fine("No server found. - getServer(NULL)");
return null;
}
for (AccurevServer server : this._servers) {
if (UUIDUtils.isValid(uuid) && uuid.equals(server.getUuid())) {
return server;
} else if (uuid.equals(server.getName())) {
// support old server name
return server;
}
}
LOGGER.fine("No server found.");
return null;
}
@SuppressWarnings("unused") // Used by stapler
public ListBoxModel doFillServerUUIDItems(@QueryParameter String serverUUID) {
ListBoxModel s = new ListBoxModel();
if (this._servers == null) {
DESCRIPTORLOGGER.warning("Failed to find AccuRev server. Add Server under AccuRev section in the Manage Jenkins > Configure System page.");
return s;
}
for (AccurevServer server : this._servers) {
s.add(server.getName(), server.getUuid());
}
return s;
}
@SuppressWarnings("unused") // Used by stapler
public ListBoxModel doFillDepotItems(@QueryParameter String serverUUID, @QueryParameter String depot) throws IOException, InterruptedException {
if (StringUtils.isBlank(serverUUID) && !getServers().isEmpty()) serverUUID = getServers().get(0).getUuid();
final AccurevServer server = getServer(serverUUID);
if (server == null) {
return new ListBoxModel();
}
List<String> depots = new ArrayList<>();
// Execute the login command first & upon success of that run show depots
// command. If any of the command's exitvalue is 1 proper error message is
// logged
if (Login.accurevLoginFromGlobalConfig(server)) {
depots = ShowDepots.getDepots(server, DESCRIPTORLOGGER);
}
ListBoxModel d = new ListBoxModel();
for (String dname : depots) {
d.add(dname, dname);
}
// Below while loop is for to retain the selected item when you open the
// Job to reconfigure
d.stream().filter(o -> depot.equals(o.name)).forEach(o -> o.selected = true);
return d;
}
// Populating the streams
@SuppressWarnings("unused") // Used by stapler
public ComboBoxModel doFillStreamItems(@QueryParameter String serverUUID, @QueryParameter String depot) throws IOException, InterruptedException {
if (StringUtils.isBlank(serverUUID) && !getServers().isEmpty()) serverUUID = getServers().get(0).getUuid();
final AccurevServer server = getServer(serverUUID);
if (server == null) {
return new ComboBoxModel();
}
ComboBoxModel cbm = new ComboBoxModel();
if (Login.accurevLoginFromGlobalConfig(server)) {
if (StringUtils.isBlank(depot)) {
depot = Util.fixNull(ShowDepots.getDepots(server, DESCRIPTORLOGGER)).get(0);
}
cbm = ShowStreams.getStreamsForGlobalConfig(server, depot, cbm);
}
return cbm;
}
@SuppressWarnings("unused") // Used by stapler
public ListBoxModel doFillAccurevToolItems() {
ListBoxModel r = new ListBoxModel();
for (AccurevTool accurev : getAccurevTools()) {
r.add(accurev.getName());
}
return r;
}
@Override
public boolean isApplicable(Job project) {
return true;
}
}
// --------------------------- Inner Class ---------------------------------------------------
public static final class AccurevServer extends AbstractDescribableImpl<AccurevServer> {
// public static final String DEFAULT_VALID_TRANSACTION_TYPES = "add,chstream,co,defcomp,defunct,keep,mkstream,move,promote,purge,dispatch";
protected static final List<String> DEFAULT_VALID_STREAM_TRANSACTION_TYPES = Collections
.unmodifiableList(Arrays.asList("chstream", "defcomp", "mkstream", "promote", "demote_to", "demote_from", "purge"));
protected static final List<String> DEFAULT_VALID_WORKSPACE_TRANSACTION_TYPES = Collections
.unmodifiableList(Arrays.asList("add", "chstream", "co", "defcomp", "defunct", "keep",
"mkstream", "move", "promote", "purge", "dispatch"));
// keep all transaction types in a set for validation
private static final String[] VTT_LIST = {"chstream", "defcomp", "mkstream", "promote", "demote_to", "demote_from", "purge"};
private static final Set<String> VALID_TRANSACTION_TYPES = new HashSet<>(Arrays.asList(VTT_LIST));
private transient static final String __OBFUSCATE = "OBF:";
private final String name;
private final String host;
transient String username;
transient String password;
private int port = 5050;
private String credentialsId;
private UUID uuid;
private String validTransactionTypes;
private boolean syncOperations;
private boolean minimiseLogins;
private boolean useNonexpiringLogin;
private boolean useRestrictedShowStreams;
private boolean useColor;
private boolean usePromoteListen;
@DataBoundConstructor
public AccurevServer(//
String uuid,
String name, //
String host) {
if (StringUtils.isEmpty(uuid)) this.uuid = UUID.randomUUID();
else this.uuid = UUID.fromString(uuid);
this.name = name;
this.host = host;
AccurevPromoteTrigger.validateListeners();
}
/* Used for testing */
public AccurevServer(String uuid, String name, String host, int port, String username, String password) {
this.uuid = StringUtils.isEmpty(uuid) ? null : UUID.fromString(uuid);
this.name = name;
this.host = host;
this.port = port;
this.username = username;
this.password = password;
}
private static String deobfuscate(String s) {
if (s.startsWith(__OBFUSCATE))
s = s.substring(__OBFUSCATE.length());
if (StringUtils.isEmpty(s)) return "";
byte[] b = new byte[s.length() / 2];
int l = 0;
for (int i = 0; i < s.length(); i += 4) {
String x = s.substring(i, i + 4);
int i0 = Integer.parseInt(x, 36);
int i1 = (i0 / 256);
int i2 = (i0 % 256);
b[l++] = (byte) ((i1 + i2 - 254) / 2);
}
return new String(b, 0, l, StandardCharsets.UTF_8);
}
/**
* When f:repeatable tags are nestable, we can change the advances page
* of the server config to allow specifying these locations... until
* then this hack!
*
* @return This.
*/
private Object readResolve() {
if (uuid == null) {
uuid = UUID.randomUUID();
}
return this;
}
/**
* Getter for property 'uuid'.
* If value is null generate random UUID
*
* @return Value for property 'uuid'.
*/
public String getUuid() {
if (uuid == null) {
uuid = UUID.randomUUID();
}
return uuid.toString();
}
/**
* Getter for property 'name'.
*
* @return Value for property 'name'.
*/
public String getName() {
return name;
}
/**
* Getter for property 'host'.
*
* @return Value for property 'host'.
*/
public String getHost() {
return host;
}
/**
* Getter for property 'port'.
*
* @return Value for property 'port'.
*/
public int getPort() {
return port;
}
@DataBoundSetter
public void setPort(int port) {
this.port = port;
}
/**
* Getter for property 'credentialsId'.
*
* @return Value for property 'credentialsId'.
*/
public String getCredentialsId() {
return credentialsId;
}
@DataBoundSetter
public void setCredentialsId(String credentialsId) {
this.credentialsId = credentialsId;
}
/**
* Getter for property 'credentials'.
*
* @return Value for property 'credentials'.
*/
@CheckForNull
public StandardUsernamePasswordCredentials getCredentials() {
if (StringUtils.isBlank(credentialsId)) return null;
else {
return CredentialsMatchers.firstOrNull(
CredentialsProvider
.lookupCredentials(StandardUsernamePasswordCredentials.class,
Jenkins.getInstance(), ACL.SYSTEM,
URIRequirementBuilder.fromUri("").withHostnamePort(host, port).build()),
CredentialsMatchers.withId(credentialsId)
);
}
}
/**
* Getter for property 'username'.
*
* @return Value for property 'username'.
*/
public String getUsername() {
StandardUsernamePasswordCredentials credentials = getCredentials();
return credentials == null ? "jenkins" : credentials.getUsername();
}
/**
* Getter for property 'password'.
*
* @return Value for property 'password'.
*/
public String getPassword() {
StandardUsernamePasswordCredentials credentials = getCredentials();
return credentials == null ? "" : Secret.toString(credentials.getPassword());
}
/**
* @return returns the currently set transaction types that are seen as
* valid for triggering builds and whos authors get notified when a
* build fails
*/
public String getValidTransactionTypes() {
return validTransactionTypes;
}
/**
* @param validTransactionTypes the currently set transaction types that
* are seen as valid for triggering builds and whos authors get notified
* when a build fails
*/
@DataBoundSetter
public void setValidTransactionTypes(String validTransactionTypes) {
this.validTransactionTypes = validTransactionTypes;
}
public boolean isSyncOperations() {
return syncOperations;
}
@DataBoundSetter
public void setSyncOperations(boolean syncOperations) {
this.syncOperations = syncOperations;
}
public boolean isMinimiseLogins() {
return minimiseLogins;
}
@DataBoundSetter
public void setMinimiseLogins(boolean minimiseLogins) {
this.minimiseLogins = minimiseLogins;
}
public boolean isUseNonexpiringLogin() {
return useNonexpiringLogin;
}
@DataBoundSetter
public void setUseNonexpiringLogin(boolean useNonexpiringLogin) {
this.useNonexpiringLogin = useNonexpiringLogin;
}
public boolean isUseRestrictedShowStreams() {
return useRestrictedShowStreams;
}
@DataBoundSetter
public void setUseRestrictedShowStreams(boolean useRestrictedShowStreams) {
this.useRestrictedShowStreams = useRestrictedShowStreams;
}
public boolean isUseColor() {
return useColor;
}
@DataBoundSetter
public void setUseColor(boolean useColor) {
this.useColor = useColor;
}
public boolean isUsePromoteListen() {
return usePromoteListen;
}
@DataBoundSetter
public void setUsePromoteListen(boolean usePromoteListen) {
this.usePromoteListen = usePromoteListen;
}
public FormValidation doValidTransactionTypesCheck(@QueryParameter String value)//
{
final String[] formValidTypes = value.split(",");
for (final String formValidType : formValidTypes) {
if (!VALID_TRANSACTION_TYPES.contains(formValidType)) {
return FormValidation.error("Invalid transaction type [" + formValidType + "]. Valid types are: " + Arrays.toString(VTT_LIST));
}
}
return FormValidation.ok();
}
public boolean migrateCredentials() {
if (username != null) {
LOGGER.info("Migrating to credentials");
String secret = deobfuscate(password);
String credentialsId = "";
List<DomainRequirement> domainRequirements = Util.fixNull(URIRequirementBuilder
.fromUri("")
.withHostnamePort(host, port)
.build());
List<StandardUsernamePasswordCredentials> credentials = CredentialsMatchers.filter(
CredentialsProvider.lookupCredentials(
StandardUsernamePasswordCredentials.class,
Jenkins.getInstance(), ACL.SYSTEM, domainRequirements),
CredentialsMatchers.withUsername(username)
);
for (StandardUsernamePasswordCredentials cred : credentials) {
if (StringUtils.equals(secret, Secret.toString(cred.getPassword()))) {
// If some credentials have the same username/password, use those.
credentialsId = cred.getId();
this.credentialsId = credentialsId;
break;
}
}
if (StringUtils.isBlank(credentialsId)) {
// If we couldn't find any existing credentials,
// create new credentials with the principal and secret and use it.
StandardUsernamePasswordCredentials newCredentials = new UsernamePasswordCredentialsImpl(
CredentialsScope.SYSTEM, null, "Migrated by Accurev Plugin", username, secret);
SystemCredentialsProvider.getInstance().getCredentials().add(newCredentials);
credentialsId = newCredentials.getId();
this.credentialsId = credentialsId;
}
if (StringUtils.isNotEmpty(this.credentialsId)) {
LOGGER.info("Migrated successfully to credentials");
username = null;
password = null;
return true;
} else {
LOGGER.severe("Migration failed");
}
}
return false;
}
@Override
public DescriptorImpl getDescriptor() {
return (DescriptorImpl) Jenkins.getInstance().getDescriptorOrDie(getClass());
}
@Extension
public static class DescriptorImpl extends Descriptor<AccurevServer> {
@Nonnull
@Override
public String getDisplayName() {
return "AccuRev Server";
}
@SuppressWarnings("unused")
public ListBoxModel doFillCredentialsIdItems(@QueryParameter String host, @QueryParameter int port, @QueryParameter String credentialsId) {
if (!Jenkins.getInstance().hasPermission(Jenkins.ADMINISTER)) {
return new StandardListBoxModel().includeCurrentValue(credentialsId);
}
return new StandardListBoxModel()
.includeEmptyValue()
.includeMatchingAs(ACL.SYSTEM,
Jenkins.getInstance(),
StandardUsernamePasswordCredentials.class,
URIRequirementBuilder.fromUri("").withHostnamePort(host, port).build(),
CredentialsMatchers.always()
);
}
}
}
// -------------------------- INNER CLASSES --------------------------
/**
* Class responsible for parsing change-logs recorded by the builds. If this
* is renamed or moved it'll break data-compatibility with old builds.
*/
private static final class AccurevChangeLogParser extends ParseChangeLog {
}
}