/*
* Copyright 2016 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;
import com.rits.cloning.Cloner;
import com.thoughtworks.go.config.registry.ConfigElementImplementationRegistry;
import com.thoughtworks.go.config.remote.FileConfigOrigin;
import com.thoughtworks.go.config.remote.PartialConfig;
import com.thoughtworks.go.config.update.FullConfigUpdateCommand;
import com.thoughtworks.go.domain.GoConfigRevision;
import com.thoughtworks.go.server.util.ServerVersion;
import com.thoughtworks.go.service.ConfigRepository;
import com.thoughtworks.go.util.CachedDigestUtils;
import com.thoughtworks.go.util.SystemEnvironment;
import com.thoughtworks.go.util.TimeProvider;
import org.jdom2.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
public abstract class FullConfigSaveFlow {
protected final MagicalGoConfigXmlLoader loader;
protected final MagicalGoConfigXmlWriter writer;
protected final ServerVersion serverVersion;
protected final TimeProvider timeProvider;
protected final ConfigRepository configRepository;
protected final CachedGoPartials cachedGoPartials;
protected final GoConfigFileWriter fileWriter;
protected final ConfigElementImplementationRegistry configElementImplementationRegistry;
protected final Cloner cloner = new Cloner();
protected final Logger LOGGER = LoggerFactory.getLogger(getClass().getName());
public FullConfigSaveFlow(MagicalGoConfigXmlLoader loader, MagicalGoConfigXmlWriter writer,
ConfigElementImplementationRegistry configElementImplementationRegistry,
ServerVersion serverVersion, TimeProvider timeProvider,
ConfigRepository configRepository, CachedGoPartials cachedGoPartials,
GoConfigFileWriter fileWriter) {
this.loader = loader;
this.writer = writer;
this.configElementImplementationRegistry = configElementImplementationRegistry;
this.serverVersion = serverVersion;
this.timeProvider = timeProvider;
this.configRepository = configRepository;
this.cachedGoPartials = cachedGoPartials;
this.fileWriter = fileWriter;
}
public FullConfigSaveFlow(MagicalGoConfigXmlLoader loader, MagicalGoConfigXmlWriter writer,
ConfigElementImplementationRegistry configElementImplementationRegistry,
SystemEnvironment systemEnvironment, ServerVersion serverVersion,
TimeProvider timeProvider, ConfigRepository configRepository, CachedGoPartials cachedGoPartials) {
this(loader, writer, configElementImplementationRegistry, serverVersion, timeProvider, configRepository, cachedGoPartials,
new GoConfigFileWriter(systemEnvironment));
}
public abstract GoConfigHolder execute(FullConfigUpdateCommand updatingCommand, List<PartialConfig> partials, String currentUser) throws Exception;
protected void postValidationUpdates(CruiseConfig configForEdit, String xmlString) throws NoSuchFieldException, IllegalAccessException {
String md5 = CachedDigestUtils.md5Hex(xmlString);
configForEdit.setOrigins(new FileConfigOrigin());
MagicalGoConfigXmlLoader.setMd5(configForEdit, md5);
}
protected String toXmlString(CruiseConfig configForEdit) throws Exception {
Document document = documentFrom(configForEdit);
validateDocument(document);
return toXmlString(document);
}
protected void checkinToConfigRepo(String currentUser, CruiseConfig updatedConfig, String xmlString) throws Exception {
LOGGER.debug("[Config Save] Checkin updated config to git: Starting.");
configRepository.checkin(new GoConfigRevision(xmlString, updatedConfig.getMd5(), currentUser, serverVersion.version(), timeProvider));
LOGGER.debug("[Config Save] Checkin updated config to git: Done.");
}
protected void writeToConfigXml(String xmlString) {
LOGGER.debug("[Config Save] Writing config xml to file: Starting.");
this.fileWriter.writeToConfigXmlFile(xmlString);
LOGGER.debug("[Config Save] Writing config xml to file: Done.");
}
protected CruiseConfig configForEditWithPartials(FullConfigUpdateCommand updatingCommand, List<PartialConfig> partials) throws Exception {
CruiseConfig config = updatingCommand.configForEdit();
config.setPartials(partials);
return config;
}
protected CruiseConfig preprocessAndValidate(CruiseConfig configForEdit) throws Exception {
return loader.preprocessAndValidate(configForEdit);
}
protected org.jdom2.Document documentFrom(CruiseConfig configForEdit) {
LOGGER.debug("[Config Save] Building Document from CruiseConfig object: Starting.");
Document document = writer.documentFrom(configForEdit);
LOGGER.debug("[Config Save] Building Document from CruiseConfig object: Done.");
return document;
}
protected void validateDocument(Document document) throws Exception {
LOGGER.debug("[Config Save] In XSD validation: Starting.");
writer.verifyXsdValid(document);
LOGGER.debug("[Config Save] In XSD validation: Done.");
LOGGER.debug("[Config Save] In DOM validation: Starting.");
MagicalGoConfigXmlLoader.validateDom(document.getRootElement(), configElementImplementationRegistry);
LOGGER.debug("[Config Save] In DOM validation: Done.");
}
protected String toXmlString(Document document) throws IOException {
LOGGER.debug("[Config Save] Serializing Document to xml: Starting.");
String xmlString = writer.toString(document);
LOGGER.debug("[Config Save] Serializing Document to xml: Done.");
return xmlString;
}
protected void setMergedConfigForEditOn(GoConfigHolder validatedConfigHolder, List<PartialConfig> partials) {
if (partials.isEmpty()) return;
LOGGER.debug("[Config Save] Updating GoConfigHolder with mergedCruiseConfigForEdit: Starting.");
CruiseConfig mergedCruiseConfigForEdit = cloner.deepClone(validatedConfigHolder.configForEdit);
mergedCruiseConfigForEdit.merge(partials, true);
validatedConfigHolder.mergedConfigForEdit = mergedCruiseConfigForEdit;
LOGGER.debug("[Config Save] Updating GoConfigHolder with mergedCruiseConfigForEdit: Done.");
}
}