/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.management.internal.configuration; import static org.apache.geode.distributed.ConfigurationProperties.LOG_FILE_SIZE_LIMIT; import static org.assertj.core.api.Assertions.assertThat; import org.apache.geode.cache.Cache; import org.apache.geode.distributed.internal.InternalLocator; import org.apache.geode.distributed.internal.ClusterConfigurationService; import org.apache.geode.internal.ClassPathLoader; import org.apache.geode.internal.JarClassLoader; import org.apache.geode.internal.JarDeployer; import org.apache.geode.internal.cache.GemFireCacheImpl; import org.apache.geode.internal.lang.StringUtils; import org.apache.geode.management.internal.configuration.domain.Configuration; import org.apache.geode.test.dunit.rules.Locator; import org.apache.geode.test.dunit.rules.LocatorServerStartupRule; import org.apache.geode.test.dunit.rules.Member; import org.apache.geode.test.dunit.rules.Server; import java.io.File; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.stream.Collectors; public class ClusterConfig implements Serializable { private List<ConfigGroup> groups; public ClusterConfig(ConfigGroup... configGroups) { this.groups = new ArrayList<>(); Collections.addAll(this.groups, configGroups); } public String getMaxLogFileSize() { if (this.groups.size() == 0) { return null; } ConfigGroup lastGroupAdded = this.groups.get(this.groups.size() - 1); return lastGroupAdded.getMaxLogFileSize(); } public List<String> getJarNames() { return groups.stream().flatMap((ConfigGroup configGroup) -> configGroup.getJars().stream()) .collect(Collectors.toList()); } public List<String> getRegions() { return groups.stream().flatMap((ConfigGroup configGroup) -> configGroup.getRegions().stream()) .collect(Collectors.toList()); } public List<ConfigGroup> getGroups() { return Collections.unmodifiableList(groups); } public void verify(Locator locator) { verifyLocator(locator); } public void verify(Server server) throws ClassNotFoundException { verifyServer(server); } public void verifyLocator(Member locator) { Set<String> expectedGroupConfigs = this.getGroups().stream().map(ConfigGroup::getName).collect(Collectors.toSet()); // verify info exists in memeory locator.invoke(() -> { InternalLocator internalLocator = LocatorServerStartupRule.locatorStarter.locator; ClusterConfigurationService sc = internalLocator.getSharedConfiguration(); // verify no extra configs exist in memory Set<String> actualGroupConfigs = sc.getEntireConfiguration().keySet(); assertThat(actualGroupConfigs).isEqualTo(expectedGroupConfigs); for (ConfigGroup configGroup : this.getGroups()) { // verify jars are as expected Configuration config = sc.getConfiguration(configGroup.name); assertThat(config.getJarNames()).isEqualTo(configGroup.getJars()); // verify proeprty is as expected if (!StringUtils.isBlank(configGroup.getMaxLogFileSize())) { Properties props = config.getGemfireProperties(); assertThat(props.getProperty(LOG_FILE_SIZE_LIMIT)) .isEqualTo(configGroup.getMaxLogFileSize()); } // verify region is in the region xml for (String regionName : configGroup.getRegions()) { String regionXml = "<region name=\"" + regionName + "\""; assertThat(config.getCacheXmlContent()).contains(regionXml); } } }); File clusterConfigDir = new File(locator.getWorkingDir(), "/cluster_config"); for (ConfigGroup configGroup : this.getGroups()) { Set<String> actualFiles = toSetIgnoringHiddenFiles(new File(clusterConfigDir, configGroup.name).list()); Set<String> expectedFiles = configGroup.getAllFiles(); assertThat(actualFiles).isEqualTo(expectedFiles); } } public void verifyServer(Member server) throws ClassNotFoundException { // verify files exist in filesystem Set<String> expectedJarNames = this.getJarNames().stream().map(ClusterConfig::getServerJarName) .collect(Collectors.toSet()); Set<String> actualJarNames = toSetIgnoringHiddenFiles( server.getWorkingDir().list((dir, filename) -> filename.contains(".jar"))); assertThat(actualJarNames).isEqualTo(expectedJarNames); // verify config exists in memory server.invoke(() -> { Cache cache = GemFireCacheImpl.getInstance(); // TODO: set compare to fail if there are extra regions for (String region : this.getRegions()) { assertThat(cache.getRegion(region)).isNotNull(); } if (!StringUtils.isBlank(this.getMaxLogFileSize())) { Properties props = cache.getDistributedSystem().getProperties(); assertThat(props.getProperty(LOG_FILE_SIZE_LIMIT)).isEqualTo(this.getMaxLogFileSize()); } for (String jar : this.getJarNames()) { JarClassLoader jarClassLoader = findJarClassLoader(jar); assertThat(jarClassLoader).isNotNull(); assertThat(Class.forName(nameOfClassContainedInJar(jar), true, jarClassLoader)).isNotNull(); } }); } private static JarClassLoader findJarClassLoader(final String jarName) { Collection<ClassLoader> classLoaders = ClassPathLoader.getLatest().getClassLoaders(); for (ClassLoader classLoader : classLoaders) { if (classLoader instanceof JarClassLoader && ((JarClassLoader) classLoader).getJarName().equals(jarName)) { return (JarClassLoader) classLoader; } } return null; } private static Set<String> toSetIgnoringHiddenFiles(String[] array) { if (array == null) { return new HashSet<>(); } return Arrays.stream(array).filter((String name) -> !name.startsWith(".")) .collect(Collectors.toSet()); } private static String getServerJarName(String jarName) { return JarDeployer.JAR_PREFIX + jarName + "#1"; } private static String nameOfClassContainedInJar(String jarName) { switch (jarName) { case "cluster.jar": return "Cluster"; case "group1.jar": return "Group1"; case "group2.jar": return "Group2"; default: throw new IllegalArgumentException( "We don't know what class to expect in the jar named " + jarName); } } }