Java tutorial
/* * Copyright 2019 ThoughtWorks, Inc. * * 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.thoughtworks.go.config.materials; import com.thoughtworks.go.config.CaseInsensitiveString; import com.thoughtworks.go.config.PipelineConfig; import com.thoughtworks.go.config.SecretParamAware; import com.thoughtworks.go.config.SecretParams; import com.thoughtworks.go.domain.MaterialRevision; import com.thoughtworks.go.domain.materials.*; import com.thoughtworks.go.security.CryptoException; import com.thoughtworks.go.security.GoCipher; import com.thoughtworks.go.util.command.EnvironmentVariableContext; import com.thoughtworks.go.util.command.InMemoryStreamConsumer; import com.thoughtworks.go.util.command.ProcessOutputStreamConsumer; import com.thoughtworks.go.util.command.UrlArgument; import org.apache.commons.lang3.StringUtils; import javax.annotation.PostConstruct; import java.io.File; import java.util.Map; import java.util.Optional; import static com.thoughtworks.go.util.ExceptionUtils.bomb; import static com.thoughtworks.go.util.command.EnvironmentVariableContext.escapeEnvironmentVariable; import static org.apache.commons.lang3.StringUtils.isBlank; /** * @understands a source control repository and its configuration */ public abstract class ScmMaterial extends AbstractMaterial implements SecretParamAware { public static final String GO_REVISION = "GO_REVISION"; public static final String GO_TO_REVISION = "GO_TO_REVISION"; public static final String GO_FROM_REVISION = "GO_FROM_REVISION"; protected final GoCipher goCipher; protected Filter filter; protected String folder; protected boolean autoUpdate = true; protected boolean invertFilter = false; protected String userName; protected String password; protected String encryptedPassword; protected SecretParams secretParamsForPassword; public ScmMaterial(String typeName, GoCipher goCipher) { super(typeName); this.goCipher = goCipher; } @Override protected void appendPipelineUniqueCriteria(Map<String, Object> basicCriteria) { basicCriteria.put("dest", folder); } public File workingdir(File baseFolder) { if (getFolder() == null) { return baseFolder; } return new File(baseFolder, getFolder()); } public String updatingTarget() { return StringUtils.isEmpty(getFolder()) ? "files" : getFolder(); } public void toJson(Map json, Revision revision) { json.put("folder", getFolder() == null ? "" : getFolder()); json.put("scmType", getTypeForDisplay()); json.put("location", getLocation()); if (!CaseInsensitiveString.isBlank(getName())) { json.put("materialName", CaseInsensitiveString.str(getName())); } json.put("action", "Modified"); } //most of the material such as hg, git, p4 all print the file from the root without '/' //but subversion print it with '/', we standarize it here. look at the implementation of subversion as well. public boolean matches(String name, String regex) { if (regex.startsWith("/")) { regex = regex.substring(1); } return name.matches(regex); } public void checkout(File baseDir, Revision revision, SubprocessExecutionContext execCtx) { InMemoryStreamConsumer output = ProcessOutputStreamConsumer.inMemoryConsumer(); this.updateTo(output, baseDir, new RevisionContext(revision), execCtx); } public String getUserName() { return this.userName; } /* Needed although there is a getUserName above */ public String getUsername() { return userName; } public final void setPassword(String password) { resetPassword(password); } private void resetPassword(String passwordToSet) { if (StringUtils.isBlank(passwordToSet)) { encryptedPassword = null; } setPasswordIfNotBlank(passwordToSet); } private void setPasswordIfNotBlank(String password) { this.password = StringUtils.stripToNull(password); this.secretParamsForPassword = SecretParams.parse(password); this.encryptedPassword = StringUtils.stripToNull(encryptedPassword); if (this.password == null) { return; } try { this.encryptedPassword = this.goCipher.encrypt(password); } catch (Exception e) { bomb("Password encryption failed. Please verify your cipher key.", e); } this.password = null; } @PostConstruct public void ensureEncrypted() { this.userName = StringUtils.stripToNull(this.userName); setPasswordIfNotBlank(password); if (encryptedPassword != null) { setEncryptedPassword(goCipher.maybeReEncryptForPostConstructWithoutExceptions(encryptedPassword)); } } public void setUserName(String userName) { this.userName = userName; } public final void setEncryptedPassword(String encryptedPassword) { this.encryptedPassword = encryptedPassword; } public final String getEncryptedPassword() { return encryptedPassword; } public String getPassword() { return currentPassword(); } public String passwordForCommandLine() { return secretParamsForPassword == null || secretParamsForPassword.isEmpty() ? getPassword() : secretParamsForPassword.substitute(getPassword()); } @Override public boolean hasSecretParams() { return this.secretParamsForPassword != null && !this.secretParamsForPassword.isEmpty(); } @Override public SecretParams getSecretParams() { return secretParamsForPassword; } public final String currentPassword() { try { return isBlank(encryptedPassword) ? null : this.goCipher.decrypt(encryptedPassword); } catch (CryptoException e) { throw new RuntimeException("Could not decrypt the password to get the real password", e); } } public abstract boolean isCheckExternals(); public abstract String getUrl(); public abstract String urlForCommandLine(); protected abstract UrlArgument getUrlArgument(); protected abstract String getLocation(); public void setFilter(Filter filter) { this.filter = filter; } public void emailContent(StringBuilder content, Modification modification) { content.append(getTypeForDisplay() + ": " + getLocation()).append('\n') .append(String.format("revision: %s, modified by %s on %s", modification.getRevision(), modification.getUserName(), modification.getModifiedTime())) .append('\n').append(Optional.ofNullable(modification.getComment()).orElse("")); } public String getDescription() { return getUriForDisplay(); } public String getUriForDisplay() { return this.getUrlArgument().forDisplay(); } public void populateEnvironmentContext(EnvironmentVariableContext environmentVariableContext, MaterialRevision materialRevision, File workingDir) { String toRevision = materialRevision.getRevision().getRevision(); String fromRevision = materialRevision.getOldestRevision().getRevision(); setGoRevisionVariables(environmentVariableContext, fromRevision, toRevision); } private void setGoRevisionVariables(EnvironmentVariableContext environmentVariableContext, String fromRevision, String toRevision) { setVariableWithName(environmentVariableContext, toRevision, GO_REVISION); setVariableWithName(environmentVariableContext, toRevision, GO_TO_REVISION); setVariableWithName(environmentVariableContext, fromRevision, GO_FROM_REVISION); } protected void setVariableWithName(EnvironmentVariableContext environmentVariableContext, String value, String propertyName) { String materialNameForEnvironmentVariable = getMaterialNameForEnvironmentVariable(); if (StringUtils.isNotBlank(materialNameForEnvironmentVariable)) { environmentVariableContext.setProperty(propertyName + "_" + materialNameForEnvironmentVariable, value, false); } else { environmentVariableContext.setProperty(propertyName, value, false); } } @Override public String getMaterialNameForEnvironmentVariable() { if (!CaseInsensitiveString.isBlank(this.name)) { return escapeEnvironmentVariable(this.name.toUpper()); } return escapeEnvironmentVariable(folder); } public String getFolder() { return folder; } public String getDisplayName() { return name == null ? getUriForDisplay() : CaseInsensitiveString.str(name); } public boolean isAutoUpdate() { return autoUpdate; } public boolean getAutoUpdate() { return autoUpdate; } public void setAutoUpdate(boolean value) { autoUpdate = value; } public boolean isInvertFilter() { return invertFilter; } public boolean getInvertFilter() { return invertFilter; } public void setInvertFilter(boolean value) { invertFilter = value; } public final MatchedRevision createMatchedRevision(Modification modification, String searchString) { return new MatchedRevision(searchString, getShortRevision(modification.getRevision()), modification.getRevision(), modification.getUserName(), modification.getModifiedTime(), modification.getComment()); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } if (!super.equals(o)) { return false; } ScmMaterial that = (ScmMaterial) o; if (folder != null ? !folder.equals(that.folder) : that.folder != null) { return false; } return true; } @Override public int hashCode() { int result = super.hashCode(); result = 31 * result + (folder != null ? folder.hashCode() : 0); return result; } public static String changesetUrl(Modification modification, String baseUrl, final long id) { return baseUrl + "/api/materials/" + id + "/changeset/" + modification.getRevision() + ".xml"; } public Boolean isUsedInFetchArtifact(PipelineConfig pipelineConfig) { return false; } // TODO: Consider renaming this to dest since we use that word in the UI & Config public void setFolder(String folder) { this.folder = folder; } public Revision oldestRevision(Modifications modifications) { return Modification.oldestRevision(modifications); } @Override public boolean supportsDestinationFolder() { return true; } }