org.geoserver.cluster.integration.IntegrationTestsUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.geoserver.cluster.integration.IntegrationTestsUtils.java

Source

/* (c) 2017 Open Source Geospatial Foundation - all rights reserved
 * This code is licensed under the GPL 2.0 license, available at the root
 * application directory.
 */
package org.geoserver.cluster.integration;

import org.apache.commons.lang.SerializationUtils;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.CoverageStoreInfo;
import org.geoserver.catalog.DataStoreInfo;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.Info;
import org.geoserver.catalog.LayerGroupInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.NamespaceInfo;
import org.geoserver.catalog.StyleInfo;
import org.geoserver.catalog.WMSLayerInfo;
import org.geoserver.catalog.WMSStoreInfo;
import org.geoserver.catalog.WorkspaceInfo;
import org.geoserver.catalog.impl.ModificationProxy;
import org.geoserver.config.GeoServer;
import org.geoserver.config.GeoServerInfo;
import org.geoserver.config.LoggingInfo;
import org.geoserver.config.ServiceInfo;
import org.geoserver.config.SettingsInfo;
import org.geoserver.ows.util.ClassProperties;
import org.geoserver.ows.util.OwsUtils;

import java.io.Serializable;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

/**
 * Contains some util methods used in JMS integration tests.
 */
public final class IntegrationTestsUtils {

    private static final Logger LOGGER = Logger.getLogger(IntegrationTestsUtils.class.getName());

    private IntegrationTestsUtils() {
    }

    /**
     * Equalizes all GeoServer instances to the first instance.
     */
    public static void equalizeInstances(GeoServerInstance... instances) {
        if (instances.length <= 1) {
            // only one instance, so nothing to equalize
            return;
        }
        // get the instance that will be used as reference
        GeoServerInstance instance = instances[0];
        for (int i = 1; i < instances.length; i++) {
            // equalize instance to the reference instance
            equalize(instance, instances[i]);
        }
    }

    /**
     * Equalizes two GeoServer instances, the first instance will be used as reference.
     */
    public static void equalize(GeoServerInstance instanceA, GeoServerInstance instanceB) {
        // get the differences between the two instances
        List<InfoDiff> differences = differences(instanceA, instanceB);
        // equalize each difference
        for (InfoDiff difference : differences) {
            Info infoA = difference.getInfoA();
            Info infoB = difference.getInfoB();
            if (infoA == null) {
                // this info doesn't exists in the reference instance, so it needs to be removed
                remove(instanceB.getGeoServer(), instanceB.getCatalog(), infoB);
            } else if (infoB == null) {
                // this info exists only in the reference instance so it needs to be added
                add(instanceB.getGeoServer(), instanceB.getCatalog(), (Info) SerializationUtils.clone(infoA));
            } else {
                // this info exists in both instances but is different
                save(instanceB.getGeoServer(), instanceB.getCatalog(), ModificationProxy.unwrap(infoA),
                        ModificationProxy.unwrap(infoB));
            }
        }
    }

    /**
     * Helper method that checks that provided instances are the same.
     * The first instance is used as reference.
     */
    public static void checkNoDifferences(GeoServerInstance... instances) {
        if (instances.length <= 1) {
            // only one instance, so noting to check
            return;
        }
        // get the reference instance
        GeoServerInstance instance = instances[0];
        for (int i = 1; i < instances.length; i++) {
            // get differences between this instance and the reference instance
            List<InfoDiff> differences = differences(instance, instances[i]);
            assertThat(differences.size(), is(0));
        }
    }

    /**
     * Returns the catalog and configuration differences between two GeoServer instance.
     */
    public static List<InfoDiff> differences(GeoServerInstance instanceA, GeoServerInstance instanceB) {
        List<InfoDiff> differences = new ArrayList<>();
        // get catalog differences
        differences.addAll(catalogDifferences(instanceA, instanceB));
        // get configuration differences
        differences.addAll(configurationDifferences(instanceA, instanceB));
        return differences;
    }

    /**
     * Returns the catalog differences between two GeoServer instances.
     */
    public static List<InfoDiff> catalogDifferences(GeoServerInstance instanceA, GeoServerInstance instanceB) {
        // instantiate the differences visitor
        CatalogDiffVisitor visitor = new CatalogDiffVisitor(instanceB.getCatalog(), instanceA.getDataDirectory(),
                instanceB.getDataDirectory());
        // visit the two catalogs
        instanceA.getCatalog().accept(visitor);
        // return the found differences
        return visitor.differences();
    }

    /**
     * Return the configuration differences between two GeoServer instances.
     */
    public static List<InfoDiff> configurationDifferences(GeoServerInstance instanceA,
            GeoServerInstance instanceB) {
        ConfigurationDiffVisitor visitor = new ConfigurationDiffVisitor(instanceA.getGeoServer(),
                instanceB.getGeoServer());
        return visitor.differences();
    }

    /**
     * Helper method that just reset the JMS configuration of the provided GeoServe instances.
     */
    public static void resetJmsConfiguration(GeoServerInstance... instances) {
        Arrays.stream(instances).forEach(GeoServerInstance::setJmsDefaultConfiguration);
    }

    /**
     * Helper method that just reset the count of consumed events of the provided GeoServe instances.
     */
    public static void resetEventsCount(GeoServerInstance... instances) {
        Arrays.stream(instances).forEach(GeoServerInstance::resetConsumedEventsCount);
    }

    /**
     * Equalizes the provided infos using info A as reference.
     */
    private static void save(GeoServer geoServer, Catalog catalog, Info infoA, Info infoB) {
        if (infoA instanceof WorkspaceInfo) {
            catalog.save(updateInfoImpl(infoA, infoB, WorkspaceInfo.class));
        } else if (infoA instanceof NamespaceInfo) {
            catalog.save(updateInfoImpl(infoA, infoB, NamespaceInfo.class));
        } else if (infoA instanceof DataStoreInfo) {
            catalog.save(updateInfoImpl(infoA, infoB, DataStoreInfo.class));
        } else if (infoA instanceof CoverageStoreInfo) {
            catalog.save(updateInfoImpl(infoA, infoB, CoverageStoreInfo.class));
        } else if (infoA instanceof WMSStoreInfo) {
            catalog.save(updateInfoImpl(infoA, infoB, WMSStoreInfo.class));
        } else if (infoA instanceof FeatureTypeInfo) {
            catalog.save(updateInfoImpl(infoA, infoB, FeatureTypeInfo.class));
        } else if (infoA instanceof CoverageInfo) {
            catalog.save(updateInfoImpl(infoA, infoB, CoverageInfo.class));
        } else if (infoA instanceof LayerInfo) {
            catalog.save(updateInfoImpl(infoA, infoB, LayerInfo.class));
        } else if (infoA instanceof StyleInfo) {
            catalog.save(updateInfoImpl(infoA, infoB, StyleInfo.class));
        } else if (infoA instanceof LayerGroupInfo) {
            catalog.save(updateInfoImpl(infoA, infoB, LayerGroupInfo.class));
        } else if (infoA instanceof WMSLayerInfo) {
            catalog.save(updateInfoImpl(infoA, infoB, WMSLayerInfo.class));
        } else if (infoA instanceof SettingsInfo) {
            geoServer.save(updateInfoImpl(infoA, infoB, SettingsInfo.class));
        } else if (infoA instanceof ServiceInfo) {
            geoServer.save(updateInfoImpl(infoA, infoB, ServiceInfo.class));
        } else if (infoA instanceof LoggingInfo) {
            geoServer.save(updateInfoImpl(infoA, infoB, LoggingInfo.class));
        } else if (infoA instanceof GeoServerInfo) {
            geoServer.save(updateInfoImpl(infoA, infoB, GeoServerInfo.class));
        } else {
            throw new RuntimeException(
                    String.format("Don't know how to handle info of type '%s'.", infoA.getClass().getSimpleName()));
        }
    }

    /**
     * Updates the second info values using the first info values. Values are cloned when possible.
     */
    private static <U> U updateInfoImpl(Info infoA, Info infoB, Class<U> type) {
        // make sure that we are dealing with infos that are compatible
        if (!type.isAssignableFrom(infoA.getClass()) || !type.isAssignableFrom(infoB.getClass())) {
            throw new RuntimeException(String.format(
                    "Info objects should be of type '%s', but are of types '%s' and '%s'.", type.getSimpleName(),
                    infoA.getClass().getSimpleName(), infoB.getClass().getSimpleName()));
        }
        // create a modification proxy for the second info
        U proxy = ModificationProxy.create(type.cast(infoB), type);
        // get infos properties
        ClassProperties properties = OwsUtils.getClassProperties(type);
        // update every property of the second info using first info value
        for (String propertyName : properties.properties()) {
            try {
                // get first info value for the current property
                Object propertyValue = OwsUtils.get(infoA, propertyName);
                if (propertyValue instanceof Info) {
                    // we are dealing with an info object, check that both properties are compatible
                    Object otherPropertyValue = OwsUtils.get(infoB, propertyName);
                    if (otherPropertyValue instanceof Info) {
                        // recursively update this info
                        propertyValue = updateInfoImpl((Info) propertyValue, (Info) otherPropertyValue,
                                getInfoInterface(propertyValue.getClass()));
                    }
                }
                // if the property value is not a info clone it if possible
                if (propertyValue instanceof Serializable && !(propertyValue instanceof Proxy)) {
                    propertyValue = SerializationUtils.clone((Serializable) propertyValue);
                }
                // update second info value
                OwsUtils.set(proxy, propertyName, propertyValue);
            } catch (IllegalArgumentException exception) {
                // ignore non existing property
                LOGGER.log(Level.FINE, String.format("Error setting property '%s'.", propertyName), exception);
            }
        }
        // return modification proxy of second info
        return proxy;
    }

    /**
     * Helper method that find the interface of an implementation.
     */
    private static Class<?> getInfoInterface(Class<?> type) {
        Class<?>[] classInterfaces = type.getInterfaces();
        for (Class<?> classInterface : classInterfaces) {
            if (Info.class.isAssignableFrom(classInterface)) {
                // compatible interface found, let's use this one
                return classInterface;
            }
        }
        // no compatible interface found
        return Info.class;
    }

    /**
     * Add info object to the provided GeoServer instance.
     */
    private static void add(GeoServer geoServer, Catalog catalog, Info info) {
        if (info instanceof WorkspaceInfo) {
            catalog.add((WorkspaceInfo) info);
        } else if (info instanceof NamespaceInfo) {
            catalog.add((NamespaceInfo) info);
        } else if (info instanceof DataStoreInfo) {
            catalog.add((DataStoreInfo) info);
        } else if (info instanceof CoverageStoreInfo) {
            catalog.add((CoverageStoreInfo) info);
        } else if (info instanceof WMSStoreInfo) {
            catalog.add((WMSStoreInfo) info);
        } else if (info instanceof FeatureTypeInfo) {
            catalog.add((FeatureTypeInfo) info);
        } else if (info instanceof CoverageInfo) {
            catalog.add((CoverageInfo) info);
        } else if (info instanceof LayerInfo) {
            catalog.add((LayerInfo) info);
        } else if (info instanceof StyleInfo) {
            catalog.add((StyleInfo) info);
        } else if (info instanceof LayerGroupInfo) {
            catalog.add((LayerGroupInfo) info);
        } else if (info instanceof WMSLayerInfo) {
            catalog.add((WMSLayerInfo) info);
        } else if (info instanceof SettingsInfo) {
            geoServer.add((SettingsInfo) info);
        } else if (info instanceof ServiceInfo) {
            geoServer.add((ServiceInfo) info);
        } else {
            throw new RuntimeException(
                    String.format("Don't know how to handle info of type '%s'.", info.getClass().getSimpleName()));
        }
    }

    /**
     * Remove info object from the provided GeoServer instance.
     */
    private static void remove(GeoServer geoServer, Catalog catalog, Info info) {
        if (info instanceof WorkspaceInfo) {
            catalog.remove((WorkspaceInfo) info);
        } else if (info instanceof NamespaceInfo) {
            catalog.remove((NamespaceInfo) info);
        } else if (info instanceof DataStoreInfo) {
            catalog.remove((DataStoreInfo) info);
        } else if (info instanceof CoverageStoreInfo) {
            catalog.remove((CoverageStoreInfo) info);
        } else if (info instanceof WMSStoreInfo) {
            catalog.remove((WMSStoreInfo) info);
        } else if (info instanceof FeatureTypeInfo) {
            catalog.remove((FeatureTypeInfo) info);
        } else if (info instanceof CoverageInfo) {
            catalog.remove((CoverageInfo) info);
        } else if (info instanceof LayerInfo) {
            catalog.remove((LayerInfo) info);
        } else if (info instanceof StyleInfo) {
            catalog.remove((StyleInfo) info);
        } else if (info instanceof LayerGroupInfo) {
            catalog.remove((LayerGroupInfo) info);
        } else if (info instanceof WMSLayerInfo) {
            catalog.remove((WMSLayerInfo) info);
        } else if (info instanceof SettingsInfo) {
            geoServer.remove((SettingsInfo) info);
        } else if (info instanceof ServiceInfo) {
            geoServer.remove((ServiceInfo) info);
        } else {
            throw new RuntimeException(
                    String.format("Don't know how to handle info of type '%s'.", info.getClass().getSimpleName()));
        }
    }
}