com.thoughtworks.go.server.service.EntityHashingService.java Source code

Java tutorial

Introduction

Here is the source code for com.thoughtworks.go.server.service.EntityHashingService.java

Source

/*
 * 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.server.service;

import com.google.gson.GsonBuilder;
import com.thoughtworks.go.config.*;
import com.thoughtworks.go.config.elastic.ClusterProfile;
import com.thoughtworks.go.config.elastic.ElasticProfile;
import com.thoughtworks.go.config.merge.MergePipelineConfigs;
import com.thoughtworks.go.config.registry.ConfigElementImplementationRegistry;
import com.thoughtworks.go.config.remote.ConfigRepoConfig;
import com.thoughtworks.go.domain.PipelineGroups;
import com.thoughtworks.go.domain.UsageStatisticsReporting;
import com.thoughtworks.go.domain.packagerepository.PackageDefinition;
import com.thoughtworks.go.domain.packagerepository.PackageRepository;
import com.thoughtworks.go.domain.scm.SCM;
import com.thoughtworks.go.domain.scm.SCMs;
import com.thoughtworks.go.listener.ConfigChangedListener;
import com.thoughtworks.go.listener.EntityConfigChangedListener;
import com.thoughtworks.go.plugin.domain.common.CombinedPluginInfo;
import com.thoughtworks.go.server.cache.GoCache;
import com.thoughtworks.go.server.domain.DataSharingSettings;
import com.thoughtworks.go.server.domain.PluginSettings;
import com.thoughtworks.go.server.initializers.Initializer;
import com.thoughtworks.go.util.CachedDigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

@Component
public class EntityHashingService implements ConfigChangedListener, Initializer {
    private GoConfigService goConfigService;
    private GoCache goCache;
    private static final String ETAG_CACHE_KEY = "GO_ETAG_CACHE".intern();
    private ConfigCache configCache;
    private ConfigElementImplementationRegistry registry;

    @Autowired
    public EntityHashingService(GoConfigService goConfigService, GoCache goCache, ConfigCache configCache,
            ConfigElementImplementationRegistry registry) {
        this.goConfigService = goConfigService;
        this.goCache = goCache;
        this.configCache = configCache;
        this.registry = registry;
    }

    public void initialize() {
        goConfigService.register(this);
        goConfigService.register(new PipelineConfigChangedListener());
        goConfigService.register(new BasicPipelineConfigsChangedListener());
        goConfigService.register(new MergePipelineConfigsChangedListener());
        goConfigService.register(new SCMConfigChangedListner());
        goConfigService.register(new TemplateConfigChangedListner());
        goConfigService.register(new EnvironmentConfigListener());
        goConfigService.register(new PackageRepositoryChangeListener());
        goConfigService.register(new ElasticAgentProfileConfigListener());
        goConfigService.register(new SecretConfigListener());
        goConfigService.register(new PackageListener());
        goConfigService.register(new SecurityAuthConfigListener());
        goConfigService.register(new ConfigRepoListener());
        goConfigService.register(new RoleConfigListener());
        goConfigService.register(new ArtifactStoreListener());
        goConfigService.register(new AdminsConfigListener());
        goConfigService.register(new ClusterProfileListener());
        goConfigService.register(new SCMChangeListener());
    }

    @Override
    public void startDaemon() {
    }

    @Override
    public void onConfigChange(CruiseConfig newCruiseConfig) {
        goCache.remove(ETAG_CACHE_KEY);
    }

    public String md5ForEntity(PipelineTemplateConfig config) {
        String cacheKey = cacheKey(config, config.name());
        return getDomainEntityMd5FromCache(config, cacheKey);
    }

    public String md5ForEntity(EnvironmentConfig config) {
        String cacheKey = cacheKey(config, config.name());
        return getDomainEntityMd5FromCache(config, cacheKey);
    }

    public String md5ForEntity(PackageRepository config) {
        String cacheKey = cacheKey(config, config.getId());
        return getDomainEntityMd5FromCache(config, cacheKey);
    }

    public String md5ForEntity(SCM config) {
        String cacheKey = cacheKey(config, config.getName());
        return getDomainEntityMd5FromCache(config, cacheKey);
    }

    public String md5ForEntity(PipelineConfig config) {
        String cacheKey = cacheKey(config, config.name());
        return getDomainEntityMd5FromCache(config, cacheKey);
    }

    public String md5ForEntity(ConfigRepoConfig config) {
        String cacheKey = cacheKey(config, config.getId());
        return getDomainEntityMd5FromCache(config, cacheKey);
    }

    public String md5ForEntity(ElasticProfile config) {
        String cacheKey = cacheKey(config, config.getId());
        return getDomainEntityMd5FromCache(config, cacheKey);
    }

    public String md5ForEntity(SecretConfig config) {
        String cacheKey = cacheKey(config, config.getId());
        return getDomainEntityMd5FromCache(config, cacheKey);
    }

    public String md5ForEntity(ClusterProfile profile) {
        String cacheKey = cacheKey(profile, profile.getId());
        return getDomainEntityMd5FromCache(profile, cacheKey);
    }

    public String md5ForEntity(SecurityAuthConfig config) {
        String cacheKey = cacheKey(config, config.getId());
        return getDomainEntityMd5FromCache(config, cacheKey);
    }

    public String md5ForEntity(SecurityAuthConfigs authConfigs) {
        List<String> md5s = new ArrayList<>();
        for (SecurityAuthConfig authConfig : authConfigs) {
            md5s.add(md5ForEntity(authConfig));
        }
        return CachedDigestUtils.md5Hex(StringUtils.join(md5s, "/"));
    }

    public String md5ForEntity(Role config) {
        String cacheKey = cacheKey(config, config.getName());
        return getDomainEntityMd5FromCache(config, cacheKey);
    }

    public String md5ForEntity(AdminsConfig config) {
        String cacheKey = cacheKey(config, "cacheKey");
        return getDomainEntityMd5FromCache(config, cacheKey);
    }

    public String md5ForEntity(PackageDefinition config) {
        String cacheKey = cacheKey(config, config.getId());
        return getDomainEntityMd5FromCache(config, cacheKey);
    }

    public String md5ForEntity(PluginSettings pluginSettings) {
        String cacheKey = cacheKey(pluginSettings, pluginSettings.getPluginId());
        return getFromCache(cacheKey, () -> String.valueOf(pluginSettings.hashCode()));
    }

    public String md5ForEntity(ArtifactStore artifactStore) {
        String cacheKey = cacheKey(artifactStore, artifactStore.getId());
        return getDbEntityMd5FromCache(cacheKey, artifactStore);
    }

    private String cacheKey(Object domainObject, CaseInsensitiveString name) {
        return cacheKey(domainObject, name.toLower());
    }

    private String cacheKey(Object domainObject, String name) {
        return getClass(domainObject) + "." + name;
    }

    private String getDbEntityMd5FromCache(String cacheKey, Object dbObject) {
        return getFromCache(cacheKey, () -> new GsonBuilder().create().toJson(dbObject));
    }

    private String getDomainEntityMd5FromCache(Object domainObject, String cacheKey) {
        return getFromCache(cacheKey, () -> getDomainObjectXmlPartial(domainObject));
    }

    private String getFromCache(String cacheKey, Supplier<String> fingerprintSupplier) {
        String cachedMD5 = getFromCache(cacheKey);

        if (cachedMD5 != null) {
            return cachedMD5;
        }
        String md5 = CachedDigestUtils.md5Hex(fingerprintSupplier.get());
        goCache.put(ETAG_CACHE_KEY, cacheKey, md5);

        return md5;
    }

    public void removeFromCache(Object domainObject, CaseInsensitiveString name) {
        removeFromCache(domainObject, name.toLower());
    }

    public void removeFromCache(Object domainObject, String name) {
        goCache.remove(ETAG_CACHE_KEY, cacheKey(domainObject, name));
    }

    private String getFromCache(String cacheKey) {
        return (String) goCache.get(ETAG_CACHE_KEY, cacheKey);
    }

    private String getClass(Object entity) {
        return entity.getClass().getName();
    }

    private String getDomainObjectXmlPartial(Object domainObject) {
        return new MagicalGoConfigXmlWriter(configCache, registry).toXmlPartial(domainObject);
    }

    public String md5ForEntity(RolesConfig roles) {
        List<String> md5s = new ArrayList<>();
        for (Role role : roles) {
            md5s.add(md5ForEntity(role));
        }
        return CachedDigestUtils.md5Hex(StringUtils.join(md5s, "/"));
    }

    public String md5ForEntity(UsageStatisticsReporting usageStatisticsReporting) {
        String cacheKey = cacheKey(usageStatisticsReporting, usageStatisticsReporting.getServerId());
        return getDbEntityMd5FromCache(cacheKey, usageStatisticsReporting);
    }

    public String md5ForEntity(DataSharingSettings dataSharingSettings) {
        String cacheKey = cacheKey(dataSharingSettings, "data_sharing_settings");
        return getDbEntityMd5FromCache(cacheKey, dataSharingSettings);
    }

    public String md5ForEntity(PipelineGroups pipelineGroups) {
        List<String> md5s = new ArrayList<>();
        for (PipelineConfigs pipelineConfigs : pipelineGroups) {
            md5s.add(md5ForEntity(pipelineConfigs));
        }
        return CachedDigestUtils.md5Hex(StringUtils.join(md5s, "/"));
    }

    public String md5ForEntity(PipelineConfigs pipelineConfigs) {
        String cacheKey = cacheKey(pipelineConfigs, pipelineConfigs.getGroup());
        return getDomainEntityMd5FromCache(pipelineConfigs, cacheKey);
    }

    public String md5ForEntity(CombinedPluginInfo pluginInfo) {
        String cacheKey = cacheKey(pluginInfo, String.format("plugin_info_%s", pluginInfo.getDescriptor().id()));
        return getFromCache(cacheKey, () -> String.valueOf(Objects.hash(pluginInfo)));
    }

    public String md5ForEntity(Collection<CombinedPluginInfo> pluginInfos) {
        List<String> md5s = new ArrayList<>();
        for (CombinedPluginInfo pluginInfo : pluginInfos) {
            md5s.add(md5ForEntity(pluginInfo));
        }
        return CachedDigestUtils.md5Hex(StringUtils.join(md5s, "/"));
    }

    public String md5ForEntity(SecretConfigs secretConfigs) {
        List<String> md5s = new ArrayList<>();
        for (SecretConfig secretConfig : secretConfigs) {
            md5s.add(md5ForEntity(secretConfig));
        }
        return CachedDigestUtils.md5Hex(StringUtils.join(md5s, "/"));
    }

    public String md5ForEntity(SCMs scms) {
        List<String> md5s = new ArrayList<>();
        for (SCM scm : scms) {
            md5s.add(md5ForEntity(scm));
        }
        return CachedDigestUtils.md5Hex(StringUtils.join(md5s, "/"));
    }

    class PipelineConfigChangedListener extends EntityConfigChangedListener<PipelineConfig> {
        @Override
        public void onEntityConfigChange(PipelineConfig pipelineConfig) {
            removeFromCache(pipelineConfig, pipelineConfig.name());
        }
    }

    class SCMConfigChangedListner extends EntityConfigChangedListener<SCM> {
        @Override
        public void onEntityConfigChange(SCM scm) {
            removeFromCache(scm, scm.getName());
        }
    }

    class TemplateConfigChangedListner extends EntityConfigChangedListener<PipelineTemplateConfig> {
        @Override
        public void onEntityConfigChange(PipelineTemplateConfig pipelineTemplateConfig) {
            removeFromCache(pipelineTemplateConfig, pipelineTemplateConfig.name());
        }
    }

    class EnvironmentConfigListener extends EntityConfigChangedListener<BasicEnvironmentConfig> {
        @Override
        public void onEntityConfigChange(BasicEnvironmentConfig config) {
            removeFromCache(config, config.name());
        }
    }

    private class PackageRepositoryChangeListener extends EntityConfigChangedListener<PackageRepository> {
        @Override
        public void onEntityConfigChange(PackageRepository repo) {
            removeFromCache(repo, repo.getId());
        }
    }

    class ElasticAgentProfileConfigListener extends EntityConfigChangedListener<ElasticProfile> {
        @Override
        public void onEntityConfigChange(ElasticProfile profile) {
            removeFromCache(profile, profile.getId());
        }
    }

    class SecretConfigListener extends EntityConfigChangedListener<SecretConfig> {
        @Override
        public void onEntityConfigChange(SecretConfig config) {
            removeFromCache(config, config.getId());
        }
    }

    class SCMChangeListener extends EntityConfigChangedListener<SCM> {
        @Override
        public void onEntityConfigChange(SCM scm) {
            removeFromCache(scm, scm.getId());
        }
    }

    class ClusterProfileListener extends EntityConfigChangedListener<ClusterProfile> {
        @Override
        public void onEntityConfigChange(ClusterProfile clusterProfile) {
            removeFromCache(clusterProfile, clusterProfile.getId());
        }
    }

    private class PackageListener extends EntityConfigChangedListener<PackageDefinition> {
        @Override
        public void onEntityConfigChange(PackageDefinition entity) {
            removeFromCache(entity, entity.getId());
        }
    }

    class SecurityAuthConfigListener extends EntityConfigChangedListener<SecurityAuthConfig> {
        @Override
        public void onEntityConfigChange(SecurityAuthConfig profile) {
            removeFromCache(profile, profile.getId());
        }
    }

    class ConfigRepoListener extends EntityConfigChangedListener<ConfigRepoConfig> {
        @Override
        public void onEntityConfigChange(ConfigRepoConfig entity) {
            removeFromCache(entity, entity.getId());
        }
    }

    private class RoleConfigListener extends EntityConfigChangedListener<Role> {
        @Override
        public void onEntityConfigChange(Role entity) {
            removeFromCache(entity, entity.getName());
        }
    }

    private class ArtifactStoreListener extends EntityConfigChangedListener<ArtifactStore> {
        @Override
        public void onEntityConfigChange(ArtifactStore entity) {
            removeFromCache(entity, entity.getId());
        }
    }

    private class AdminsConfigListener extends EntityConfigChangedListener<AdminsConfig> {
        @Override
        public void onEntityConfigChange(AdminsConfig entity) {
            removeFromCache(entity, "cacheKey");
        }
    }

    private class BasicPipelineConfigsChangedListener extends EntityConfigChangedListener<BasicPipelineConfigs> {
        @Override
        public void onEntityConfigChange(BasicPipelineConfigs pipelineConfigs) {
            removeFromCache(pipelineConfigs, pipelineConfigs.getGroup());
        }
    }

    private class MergePipelineConfigsChangedListener extends EntityConfigChangedListener<MergePipelineConfigs> {
        @Override
        public void onEntityConfigChange(MergePipelineConfigs pipelineConfigs) {
            removeFromCache(pipelineConfigs, pipelineConfigs.getGroup());
        }
    }
}