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

io.convergence_platform.services.infrastructure.InfrastructureDiscoveryHelper Maven / Gradle / Ivy

Go to download

Holds the common functionality needed by all Convergence Platform-based services written in Java.

The newest version!
package io.convergence_platform.services.infrastructure;

import io.convergence_platform.common.annotations.ConvergenceEndpointInfo;
import io.convergence_platform.common.annotations.HideFromApiGateway;
import io.convergence_platform.services.dto.ConvergenceEndpointRateLimitPolicy;
import io.convergence_platform.services.dto.ServiceEndpointDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Pattern;

@Component
public class InfrastructureDiscoveryHelper {
    private static Map intervalUnits = null;
    static {
        intervalUnits = new HashMap<>();
        intervalUnits.put("s", 1);
        intervalUnits.put("m", 60);
        intervalUnits.put("h", 3600);
    }

    @Autowired
    private RequestMappingHandlerMapping mapper;

    @Value("${application.convergence_core_service_url}")
    private String discoveryServerUrl;

    public List loadServiceExposedURLs() {
        Map urls = mapper.getHandlerMethods();

        List endpoints = new ArrayList<>();

        for (RequestMappingInfo url : urls.keySet()) {
            HandlerMethod method = urls.get(url);
            if (method.getBeanType().getPackageName().startsWith("org.springframework.")) {
                continue;
            }

            Method methodInfo = method.getMethod();
            HideFromApiGateway externalAnnotation = methodInfo.getAnnotation(HideFromApiGateway.class);
            ConvergenceEndpointInfo epInfoAnnotation = methodInfo.getAnnotation(ConvergenceEndpointInfo.class);
            PreAuthorize authorizationAnnotation = methodInfo.getAnnotation(PreAuthorize.class);
            Set methods = url.getMethodsCondition().getMethods();

            List patterns = getMappingPatterns(url);
            for (String pattern : patterns) {
                for (RequestMethod requestMethod : methods) {
                    ServiceEndpointDTO ep = new ServiceEndpointDTO();
                    ep.setUrl(pattern);
                    ep.setMethod(requestMethod.name().toUpperCase());
                    ep.setExposedThroughGateway(externalAnnotation == null);

                    String authExpression = "@acl.allowAll()";
                    if (authorizationAnnotation != null) {
                        authExpression = authorizationAnnotation.value();
                    }

                    if (authExpression.equals("@acl.allowAll()")) {
                        ep.setExpectedAuthorization("@allow_all");
                    } else if (authExpression.equals("@acl.isSignedIn()")) {
                        ep.setExpectedAuthorization("@signed_in");
                    } else if (authExpression.equals("@acl.notSignedIn()")) {
                        ep.setExpectedAuthorization("@not_signed_in");
                    } else if (authExpression.equals("@acl.isService()")) {
                        ep.setExpectedAuthorization("@service_call");
                    } else {
                        String authority = authExpression.substring("@acl.hasAuthority(".length() + 1);
                        authority = authority.substring(0, authority.length() - 2);
                        if (authority.contains("(")) {
                            ep.setExpectedAuthorization("");
                        } else {
                            ep.setExpectedAuthorization(authority);
                        }
                    }

                    if (epInfoAnnotation == null) {
                        ep.setMaxPayloadSize(parsePayloadSize("200KB"));
                        ep.setTimeout(parseTimeout("10s"));
                        ep.setMaintenanceMode("restrict");
                        ep.setRateLimitingPolicy(List.of());
                        ep.setAccepts(new String[]{"application/json"});
                    } else {
                        ep.setMaxPayloadSize(parsePayloadSize(epInfoAnnotation.maxPayloadSize()));
                        ep.setTimeout(parseTimeout(epInfoAnnotation.timeout()));
                        ep.setMaintenanceMode(validateMaintenanceMode(epInfoAnnotation.maintenanceMode()));
                        ep.setRateLimitingPolicy(parseRateLimitingPolicies(epInfoAnnotation.rateLimitingPolicies()));
                        ep.setAccepts(epInfoAnnotation.accepts());
                    }

                    endpoints.add(ep);
                }
            }
        }

        return endpoints;
    }

    private List parseRateLimitingPolicies(String[] policies) {
        if (policies == null) {
            return List.of();
        }

        List result = new ArrayList<>();

        for (int i = 0; i < policies.length; i++) {
            String p = policies[i];
            String[] parts = p.split(Pattern.quote(":"));

            if (parts.length != 3) {
                throw new RuntimeException(String.format("The value %s is not a valid rate limiting policy.", p));
            }

            if (!Objects.equals(parts[0], "max_globally") &&
                    !Objects.equals(parts[0], "max_per_session") &&
                    !Objects.equals(parts[0], "max_per_ip")) {
                throw new RuntimeException(String.format("The value %s is not a valid rate limiting policy.", p));
            }

            ConvergenceEndpointRateLimitPolicy c = new ConvergenceEndpointRateLimitPolicy();
            result.add(c);

            c.setPolicy(parts[0]);
            c.setCount(Integer.parseInt(parts[1]));

            int coeff = 0;
            boolean validUnit = false;

            for (String unit : intervalUnits.keySet()) {
                if (parts[2].endsWith(unit)) {
                    validUnit = true;
                    coeff = intervalUnits.get(unit);
                    break;
                }
            }

            if (!validUnit) {
                throw new RuntimeException(String.format("The value %s is not a valid rate limiting policy.", p));
            }

            int value = Integer.parseInt(parts[2].substring(0, parts[2].length() - 1));
            c.setDuration(value * coeff);

        }
        return result;
    }

    private String validateMaintenanceMode(String s) {
        if (!s.equals("allow") && !s.equals("restrict")) {
            throw new RuntimeException(String.format("The value %s is not valid.", s));
        }
        return s;
    }

    private int parseTimeout(String s) {
        int coeff = 0;
        int length = 0;
        if (s.endsWith("ms")) {
            coeff = 1;
            length = 2;
        } else if (s.endsWith("s")) {
            coeff = 1000;
            length = 1;
        } else {
            throw new RuntimeException(String.format("The value %s is not valid.", s));
        }

        int value = Integer.parseInt(s.substring(0, s.length() - length));
        return value * coeff;
    }

    private int parsePayloadSize(String s) {
        int coeff = 0;
        if (s.endsWith("KB")) {
            coeff = 1024;
        } else if (s.endsWith("MB")) {
            coeff = 1024 * 1024;
        } else if (s.endsWith("GB")) {
            coeff = 1024 * 1024 * 1024;
        } else {
            throw new RuntimeException(String.format("The value %s is not valid.", s));
        }

        int value = Integer.parseInt(s.substring(0, s.length() - 2));
        return value * coeff;
    }

    private List getMappingPatterns(RequestMappingInfo url) {
        Set result = new HashSet<>();

        if (url.getPathPatternsCondition() != null) {
            result.addAll(url.getPathPatternsCondition().getPatternValues());
        }
        result.addAll(url.getDirectPaths());

        return result.stream().toList();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy