All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.jersey.internal.config.ExternalPropertiesConfigurationFactory Maven / Gradle / Ivy

Go to download

A bundle project producing JAX-RS RI bundles. The primary artifact is an "all-in-one" OSGi-fied JAX-RS RI bundle (jaxrs-ri.jar). Attached to that are two compressed JAX-RS RI archives. The first archive (jaxrs-ri.zip) consists of binary RI bits and contains the API jar (under "api" directory), RI libraries (under "lib" directory) as well as all external RI dependencies (under "ext" directory). The secondary archive (jaxrs-ri-src.zip) contains buildable JAX-RS RI source bundle and contains the API jar (under "api" directory), RI sources (under "src" directory) as well as all external RI dependencies (under "ext" directory). The second archive also contains "build.xml" ANT script that builds the RI sources. To build the JAX-RS RI simply unzip the archive, cd to the created jaxrs-ri directory and invoke "ant" from the command line.

There is a newer version: 3.1.9
Show newest version
/*
 * Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.internal.config;

import org.glassfish.jersey.internal.ServiceFinder;
import org.glassfish.jersey.spi.ExternalConfigurationModel;
import org.glassfish.jersey.spi.ExternalConfigurationProvider;

import jakarta.annotation.Priority;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.core.Configurable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.function.BiConsumer;

/**
 * Factory for external properties providers
 * Offers methods to work with properties loaded from providers or
 * just configure Jersey's Configurables with loaded properties from providers
 */
public class ExternalPropertiesConfigurationFactory {

    private static final List EXTERNAL_CONFIGURATION_PROVIDERS =
            getExternalConfigurations();


    /**
     * Map of merged properties from all found providers
     *
     * @return map of merged properties from all found/plugged providers
     */
    static Map readExternalPropertiesMap() {
        return readExternalPropertiesMap(EXTERNAL_CONFIGURATION_PROVIDERS);
    }

    /**
     * Map of merged properties from all given providers
     *
     * @param externalConfigProviders list of providers to use
     * @return map of merged properties from {@code externalConfigProviders} providers
     */
    private static Map readExternalPropertiesMap(List externalConfigProviders) {
        final ExternalConfigurationProvider provider = mergeConfigs(externalConfigProviders);
        return provider == null ? Collections.emptyMap() : provider.getProperties();
    }

    /**
     * Input Configurable object shall be provided in order to be filled with all found properties
     *
     * @param config Input Configurable initialised object to be filled with properties
     * @return true if configured false otherwise
     */

    public static boolean configure(Configurable config) {
        return configure((k, v) -> config.property(k, v), EXTERNAL_CONFIGURATION_PROVIDERS);
    }

    /**
     * Key Value pairs gathered by {@link ExternalConfigurationProvider}s are applied to a given {@code config}. The
     * {@code config} can be for instance {@code (k,v) -> configurable.property(k,v)} of a
     * {@link Configurable#property(String, Object) Configurable structure}, or {@code (k,v) -> properties.put(k,v)} of a
     * {@link java.util.Properties#put(Object, Object) Properties structure}.
     *
     * @param config
     * @param externalConfigurationProviders the providers to grab the properties from it.
     * @return true if configured false otherwise.
     */
    public static boolean configure(BiConsumer config,
                                    List externalConfigurationProviders) {
        if (config instanceof ExternalConfigurationModel) {
            return false; //shall not configure itself
        }

        final Map properties = readExternalPropertiesMap(externalConfigurationProviders);

        properties.forEach((k, v) -> config.accept(k, v));

        return true;
    }

    /**
     * Merged config model from all found configuration models
     *
     * @return merged Model object with all properties
     */
    static ExternalConfigurationModel getConfig() {
        final ExternalConfigurationProvider provider = mergeConfigs(getExternalConfigurations());
        return provider == null ? null : provider.getConfiguration();
    }

    /**
     * List of all found models as they are found by Jersey
     *
     * @return list of models (or empty list)
     */
    private static List getExternalConfigurations() {
        final List providers = new ArrayList<>();
        final ServiceFinder finder =
                ServiceFinder.find(ExternalConfigurationProvider.class);
        if (finder.iterator().hasNext()) {
            finder.forEach(providers::add);
        } else {
            providers.add(new SystemPropertiesConfigurationProvider());
        }
        return providers;
    }

    private static ExternalConfigurationProvider mergeConfigs(List configurations) {
        final Set orderedConfigurations = orderConfigs(configurations);
        final Iterator configurationIterator = orderedConfigurations.iterator();
        if (!configurationIterator.hasNext()) {
            return null;
        }
        final ExternalConfigurationProvider firstConfig = configurationIterator.next();
        while (configurationIterator.hasNext()) {
            final ExternalConfigurationProvider nextConfig = configurationIterator.next();
            firstConfig.merge(nextConfig.getConfiguration());
        }

        return firstConfig;
    }

    private static Set orderConfigs(List configurations) {

        final SortedSet sortedSet = new TreeSet<>(new ConfigComparator());
        sortedSet.addAll(configurations);
        return Collections.unmodifiableSortedSet(sortedSet);
    }

    private static class ConfigComparator implements Comparator {

        @Override
        public int compare(ExternalConfigurationProvider config1, ExternalConfigurationProvider config2) {

            boolean config1PriorityPresent = config1.getClass().isAnnotationPresent(Priority.class);
            boolean config2PriorityPresent = config2.getClass().isAnnotationPresent(Priority.class);

            int priority1 = Priorities.USER;
            int priority2 = Priorities.USER;

            if (config1PriorityPresent) {
                priority1 = config1.getClass().getAnnotation(Priority.class).value();
            }
            if (config2PriorityPresent) {
                priority2 = config2.getClass().getAnnotation(Priority.class).value();
            }

            if (priority1 == priority2) {
                return config1.getClass().getName().compareTo(config2.getClass().getName());
            }
            return Integer.compare(priority1, priority2);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy