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

io.gravitee.rest.api.service.impl.ParameterServiceImpl Maven / Gradle / Ivy

There is a newer version: 3.10.0
Show newest version
/**
 * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
 *
 * 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 io.gravitee.rest.api.service.impl;

import static io.gravitee.repository.management.model.Audit.AuditProperties.PARAMETER;
import static io.gravitee.repository.management.model.Parameter.AuditEvent.PARAMETER_CREATED;
import static io.gravitee.repository.management.model.Parameter.AuditEvent.PARAMETER_UPDATED;
import static java.lang.String.join;
import static java.util.Arrays.stream;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonMap;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

import io.gravitee.common.event.EventManager;
import io.gravitee.repository.exceptions.TechnicalException;
import io.gravitee.repository.management.api.ParameterRepository;
import io.gravitee.repository.management.model.Parameter;
import io.gravitee.repository.management.model.ParameterReferenceType;
import io.gravitee.rest.api.model.parameters.Key;
import io.gravitee.rest.api.model.parameters.KeyScope;
import io.gravitee.rest.api.service.AuditService;
import io.gravitee.rest.api.service.EnvironmentService;
import io.gravitee.rest.api.service.ParameterService;
import io.gravitee.rest.api.service.common.GraviteeContext;
import io.gravitee.rest.api.service.exceptions.TechnicalManagementException;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.stereotype.Component;

/**
 * @author Azize ELAMRANI (azize at graviteesource.com)
 * @author Nicolas GERAUD (nicolas.geraud at graviteesource.com)
 * @author GraviteeSource Team
 */
@Component
public class ParameterServiceImpl extends TransactionalService implements ParameterService {

    public static final String SEPARATOR = ";";
    public static final String KV_SEPARATOR = "@";

    private static final Logger LOGGER = LoggerFactory.getLogger(ParameterServiceImpl.class);

    @Inject
    private ParameterRepository parameterRepository;

    @Inject
    private AuditService auditService;

    @Inject
    private ConfigurableEnvironment environment;

    @Inject
    private EventManager eventManager;

    @Inject
    @Lazy
    private EnvironmentService environmentService;

    // Current context
    @Override
    public String find(Key key, io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType) {
        return find(key, null, referenceType);
    }

    @Override
    public boolean findAsBoolean(final Key key, final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType) {
        return findAsBoolean(key, null, referenceType);
    }

    @Override
    public List findAll(final Key key, final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType) {
        return findAll(key, Function.identity(), null, null, referenceType);
    }

    @Override
    public Map> findAll(
        final List keys,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return findAll(keys, Function.identity(), null, null, referenceType);
    }

    @Override
    public  List findAll(
        final Key key,
        final Function mapper,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return findAll(key, mapper, null, null, referenceType);
    }

    @Override
    public  Map> findAll(
        final List keys,
        final Function mapper,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return findAll(keys, mapper, null, null, referenceType);
    }

    @Override
    public  List findAll(
        final Key key,
        final Function mapper,
        final Predicate filter,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return findAll(key, mapper, filter, null, referenceType);
    }

    @Override
    public  Map> findAll(
        List keys,
        Function mapper,
        Predicate filter,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return findAll(keys, mapper, filter, null, referenceType);
    }

    @Override
    public Parameter save(
        final Key key,
        final String value,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return save(key, value, null, referenceType);
    }

    @Override
    public Parameter save(
        final Key key,
        final List values,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return save(key, values, null, referenceType);
    }

    @Override
    public Parameter save(
        final Key key,
        final Map values,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return save(key, values, null, referenceType);
    }

    // Specific context
    @Override
    public String find(
        final Key key,
        final String referenceId,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return GraviteeContext
            .getCurrentParameters()
            .computeIfAbsent(
                key,
                k -> {
                    final List values = findAll(k, referenceId, referenceType);
                    final String value;
                    if (values == null || values.isEmpty()) {
                        value = k.defaultValue();
                    } else {
                        value = String.join(SEPARATOR, values);
                    }
                    return value;
                }
            );
    }

    @Override
    public boolean findAsBoolean(
        final Key key,
        final String referenceId,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return Boolean.parseBoolean(find(key, referenceId, referenceType));
    }

    @Override
    public List findAll(
        final Key key,
        final String referenceId,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return findAll(key, Function.identity(), null, referenceId, referenceType);
    }

    @Override
    public Map> findAll(
        final List keys,
        final String referenceId,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return findAll(keys, Function.identity(), null, referenceId, referenceType);
    }

    @Override
    public  List findAll(
        final Key key,
        final Function mapper,
        final String referenceId,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return findAll(key, mapper, null, referenceId, referenceType);
    }

    @Override
    public  Map> findAll(
        final List keys,
        final Function mapper,
        final String referenceId,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return findAll(keys, mapper, null, referenceId, referenceType);
    }

    @Override
    public  List findAll(
        final Key key,
        final Function mapper,
        final Predicate filter,
        final String referenceId,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        String refIdToUse = getEffectiveReferenceId(referenceId, referenceType);
        try {
            Optional optionalParameter = this.getSystemParameter(key);
            if (optionalParameter.isPresent()) {
                return splitValue(optionalParameter.get().getValue(), mapper, filter);
            }
            switch (referenceType) {
                case ENVIRONMENT:
                    optionalParameter = this.getEnvParameter(key, refIdToUse);
                    if (optionalParameter.isPresent()) {
                        return splitValue(optionalParameter.get().getValue(), mapper, filter);
                    }
                    //String organizationId = "DEFAULT";
                    String organizationId = environmentService.findById(refIdToUse).getOrganizationId();
                    optionalParameter = this.getOrgParameter(key, organizationId);
                    if (optionalParameter.isPresent()) {
                        return splitValue(optionalParameter.get().getValue(), mapper, filter);
                    }
                case ORGANIZATION:
                    optionalParameter = this.getOrgParameter(key, refIdToUse);
                    if (optionalParameter.isPresent()) {
                        return splitValue(optionalParameter.get().getValue(), mapper, filter);
                    }
            }
            return splitValue(this.getDefaultParameterValue(key), mapper, filter);
        } catch (final TechnicalException ex) {
            final String message = "An error occurs while trying to find parameter values with key: " + key;
            LOGGER.error(message, ex);
            throw new TechnicalManagementException(message, ex);
        }
    }

    @Override
    public  Map> findAll(
        List keys,
        Function mapper,
        Predicate filter,
        final String referenceId,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        String refIdToUse = getEffectiveReferenceId(referenceId, referenceType);
        try {
            List keysToFind = new ArrayList<>(keys);
            Map> result = new HashMap<>();

            // Get System parameters
            for (Key keyToFind : keys) {
                this.getSystemParameter(keyToFind)
                    .ifPresent(
                        p -> {
                            result.put(p.getKey(), splitValue(p.getValue(), mapper, filter));
                            keysToFind.remove(keyToFind);
                        }
                    );
            }

            if (!keysToFind.isEmpty()) {
                switch (referenceType) {
                    case ENVIRONMENT:
                        this.getEnvParameters(keysToFind, refIdToUse)
                            .forEach(
                                p -> {
                                    result.put(p.getKey(), splitValue(p.getValue(), mapper, filter));
                                    keysToFind.remove(Key.findByKey(p.getKey()));
                                }
                            );
                        if (!keysToFind.isEmpty()) {
                            //String organizationId = "DEFAULT";//environmentService.findById(referenceId).getOrganizationId();
                            String organizationId = environmentService.findById(refIdToUse).getOrganizationId();
                            this.getOrgParameters(keysToFind, organizationId)
                                .forEach(
                                    p -> {
                                        result.put(p.getKey(), splitValue(p.getValue(), mapper, filter));
                                        keysToFind.remove(Key.findByKey(p.getKey()));
                                    }
                                );
                            if (!keysToFind.isEmpty()) {
                                keysToFind.forEach(k -> result.put(k.key(), splitValue(k.defaultValue(), mapper, filter)));
                            }
                        }
                        break;
                    case ORGANIZATION:
                        this.getOrgParameters(keysToFind, refIdToUse)
                            .forEach(
                                p -> {
                                    result.put(p.getKey(), splitValue(p.getValue(), mapper, filter));
                                    keysToFind.remove(Key.findByKey(p.getKey()));
                                }
                            );
                        if (!keysToFind.isEmpty()) {
                            keysToFind.forEach(k -> result.put(k.key(), splitValue(k.defaultValue(), mapper, filter)));
                        }
                        break;
                    default:
                        keysToFind.forEach(k -> result.put(k.key(), splitValue(k.defaultValue(), mapper, filter)));
                        break;
                }
            }

            return result;
        } catch (final TechnicalException ex) {
            final String message = "An error occurs while trying to find parameter values with keys: " + keys;
            LOGGER.error(message, ex);
            throw new TechnicalManagementException(message, ex);
        }
    }

    private String getEffectiveReferenceId(String referenceId, io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType) {
        String refIdToUse = referenceId;
        if (refIdToUse == null) {
            if (referenceType == io.gravitee.rest.api.model.parameters.ParameterReferenceType.ORGANIZATION) {
                refIdToUse = GraviteeContext.getCurrentOrganization();
            } else {
                refIdToUse = GraviteeContext.getCurrentEnvironment();
            }
        }
        return refIdToUse;
    }

    private  List splitValue(final String value, final Function mapper, final Predicate filter) {
        if (value == null || value.isEmpty()) {
            return emptyList();
        }
        Stream stream = stream(value.split(SEPARATOR));
        if (filter != null) {
            stream = stream.filter(filter);
        }
        return stream.map(mapper).collect(toList());
    }

    @Override
    public Parameter save(
        final Key key,
        final String value,
        final String referenceId,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        String refIdToUse = getEffectiveReferenceId(referenceId, referenceType);
        try {
            Optional optionalParameter = parameterRepository.findById(
                key.key(),
                refIdToUse,
                ParameterReferenceType.valueOf(referenceType.name())
            );
            final boolean updateMode = optionalParameter.isPresent();

            final Parameter parameter = new Parameter();
            parameter.setKey(key.key());
            parameter.setReferenceId(refIdToUse);
            parameter.setReferenceType(ParameterReferenceType.valueOf(referenceType.name()));
            parameter.setValue(value);

            if (environment.containsProperty(key.key()) && key.isOverridable()) {
                parameter.setValue(toSemicolonSeparatedString(key, environment.getProperty(key.key())));
                return parameter;
            }

            if (updateMode) {
                if (value == null) {
                    parameterRepository.delete(key.key(), refIdToUse, ParameterReferenceType.valueOf(referenceType.name()));
                    return null;
                } else if (!value.equals(optionalParameter.get().getValue())) {
                    final Parameter updatedParameter = parameterRepository.update(parameter);
                    auditService.createEnvironmentAuditLog(
                        singletonMap(PARAMETER, updatedParameter.getKey()),
                        PARAMETER_UPDATED,
                        new Date(),
                        optionalParameter.get(),
                        updatedParameter
                    );
                    eventManager.publishEvent(key, parameter);
                    return updatedParameter;
                } else {
                    return optionalParameter.get();
                }
            } else {
                if (value == null) {
                    return null;
                }
                final Parameter savedParameter = parameterRepository.create(parameter);
                auditService.createEnvironmentAuditLog(
                    singletonMap(PARAMETER, savedParameter.getKey()),
                    PARAMETER_CREATED,
                    new Date(),
                    null,
                    savedParameter
                );
                eventManager.publishEvent(key, parameter);
                return savedParameter;
            }
        } catch (final TechnicalException ex) {
            final String message = "An error occurs while trying to create parameter for key/value: " + key + '/' + value;
            LOGGER.error(message, ex);
            throw new TechnicalManagementException(message, ex);
        }
    }

    @Override
    public Parameter save(
        final Key key,
        final List values,
        final String referenceId,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return save(key, values == null ? null : join(SEPARATOR, values), referenceId, referenceType);
    }

    @Override
    public Parameter save(
        final Key key,
        final Map values,
        final String referenceId,
        final io.gravitee.rest.api.model.parameters.ParameterReferenceType referenceType
    ) {
        return save(
            key,
            values == null
                ? null
                : values.entrySet().stream().map(entry -> entry.getKey() + KV_SEPARATOR + entry.getValue()).collect(joining(SEPARATOR)),
            referenceId,
            referenceType
        );
    }

    private String toSemicolonSeparatedString(Key key, String value) {
        if (key.type() != null && List.class.isAssignableFrom(key.type())) {
            value = value.replace(",", SEPARATOR);
        }
        return value;
    }

    private Optional getEnvParameter(Key key, String environmentId) throws TechnicalException {
        if (key.scopes().contains(KeyScope.ENVIRONMENT)) {
            return parameterRepository.findById(key.key(), environmentId, ParameterReferenceType.ENVIRONMENT);
        }
        return Optional.empty();
    }

    private List getEnvParameters(List keys, String environmentId) throws TechnicalException {
        List keysToFind = keys.stream().filter(k -> k.scopes().contains(KeyScope.ENVIRONMENT)).collect(toList());
        if (!keysToFind.isEmpty()) {
            return parameterRepository
                .findByKeys(keysToFind.stream().map(Key::key).collect(toList()), environmentId, ParameterReferenceType.ENVIRONMENT)
                .stream()
                .filter(Objects::nonNull)
                .collect(toList());
        }
        return Collections.emptyList();
    }

    private Optional getOrgParameter(Key key, String organizationId) throws TechnicalException {
        if (key.scopes().contains(KeyScope.ORGANIZATION)) {
            return parameterRepository.findById(key.key(), organizationId, ParameterReferenceType.ORGANIZATION);
        }
        return Optional.empty();
    }

    private List getOrgParameters(List keys, String organizationId) throws TechnicalException {
        List keysToFind = keys.stream().filter(k -> k.scopes().contains(KeyScope.ORGANIZATION)).collect(toList());
        if (!keysToFind.isEmpty()) {
            return parameterRepository
                .findByKeys(keysToFind.stream().map(Key::key).collect(toList()), organizationId, ParameterReferenceType.ORGANIZATION)
                .stream()
                .filter(Objects::nonNull)
                .collect(toList());
        }
        return Collections.emptyList();
    }

    private Optional getSystemParameter(Key key) {
        if (environment.containsProperty(key.key()) && key.isOverridable()) {
            final Parameter parameter = new Parameter();
            parameter.setKey(key.key());
            parameter.setValue(toSemicolonSeparatedString(key, environment.getProperty(key.key())));
            return Optional.of(parameter);
        }
        return Optional.empty();
    }

    private String getDefaultParameterValue(Key key) {
        return key.defaultValue();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy