![JAR search and dependency download from the Maven repository](/logo.png)
templates.evaluatorHeader.mustache Maven / Gradle / Ivy
The 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 {{packageName}};
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.gravitee.common.http.HttpHeader;
import io.gravitee.gateway.reactive.api.ExecutionFailure;
import io.gravitee.gateway.reactive.api.context.DeploymentContext;
import io.gravitee.gateway.reactive.api.context.base.BaseExecutionContext;
import io.gravitee.gateway.reactive.api.context.http.HttpPlainExecutionContext;
import io.gravitee.secrets.api.el.FieldKind;
import io.gravitee.secrets.api.el.SecretFieldAccessControl;
import io.reactivex.rxjava3.core.Completable;
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.core.Maybe;
import io.reactivex.rxjava3.core.Single;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import org.hibernate.validator.HibernateValidator;
import org.hibernate.validator.messageinterpolation.ParameterMessageInterpolator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
public class {{evaluatorSimpleClassName}} {
private static final String FAILURE_CONFIGURATION_INVALID = "FAILURE_CONFIGURATION_INVALID";
private final Logger logger = LoggerFactory.getLogger({{evaluatorSimpleClassName}}.class);
private final ObjectMapper objectMapper = new ObjectMapper();
private final {{simpleClassName}} configuration;
private static final Validator validator;
private final String attributePrefix = "{{attributePrefix}}";
private final String internalId;
static {
ValidatorFactory factory = Validation.byProvider(HibernateValidator.class).configure()
.messageInterpolator(new ParameterMessageInterpolator()).buildValidatorFactory();
validator = factory.getValidator();
}
public {{evaluatorSimpleClassName}} (
{{simpleClassName}} configuration)
{
this.configuration = configuration;
this.internalId = UUID.randomUUID().toString();
}
// Utility methods
private String buildAttributeName(String attributePrefix, String name) {
return attributePrefix.concat(".").concat(name);
}
private String buildFieldName(String attributeName) {
return attributeName.substring(this.attributePrefix.length()+1);
}
private Maybe evalStringProperty(String name, String value, String attributePrefix, BaseExecutionContext ctx, String secretKind) {
//First check attributes
String attributeName = buildAttributeName(attributePrefix, name);
String attribute = ctx.getAttribute(attributeName);
if (attribute != null) {
//If a value is found for this attribute, override the original value with it
value = attribute;
}
//If value is null, return empty
if(value == null) {
return Maybe.empty();
}
SecretFieldAccessControl accessControl;
if(secretKind.isEmpty()) {
accessControl = new SecretFieldAccessControl(false, null, null);
} else {
accessControl = new SecretFieldAccessControl(true, FieldKind.valueOf(secretKind), buildFieldName(attributeName));
}
//Then check EL
String finalValue = value;
return ctx
.getTemplateEngine()
.eval(value, String.class)
.doOnSubscribe(d -> ctx.getTemplateEngine().getTemplateContext().setVariable(SecretFieldAccessControl.EL_VARIABLE, accessControl))
.doOnTerminate(() -> ctx.getTemplateEngine().getTemplateContext().setVariable(SecretFieldAccessControl.EL_VARIABLE, null))
.doOnError(throwable -> logger.error("Unable to evaluate property [{}] with expression [{}].", name, finalValue));
}
private Maybe evalStringProperty(String name, String value, String attributePrefix, DeploymentContext ctx, String secretKind) {
// If value is null, return empty
if(value == null) {
return Maybe.empty();
}
SecretFieldAccessControl accessControl;
String property = buildFieldName(buildAttributeName(attributePrefix, name));
if(secretKind.isEmpty()) {
accessControl = new SecretFieldAccessControl(false, null, null);
} else {
accessControl = new SecretFieldAccessControl(true, FieldKind.valueOf(secretKind), property);
}
//Then check EL
return ctx
.getTemplateEngine()
.eval(value, String.class)
.doOnSubscribe(d -> ctx.getTemplateEngine().getTemplateContext().setVariable(SecretFieldAccessControl.EL_VARIABLE, accessControl))
.doOnTerminate(() -> ctx.getTemplateEngine().getTemplateContext().setVariable(SecretFieldAccessControl.EL_VARIABLE, null))
.doOnError(throwable -> logger.error("Unable to evaluate property [{}] with expression [{}].", property, value));
}
private > T evalEnumProperty(String name, T value, Class enumClass, String attributePrefix, BaseExecutionContext ctx) {
String attribute = ctx.getAttribute(buildAttributeName(attributePrefix, name));
if (attribute != null) {
return T.valueOf(enumClass, attribute);
}
return value;
}
private Integer evalIntegerProperty(String name, Integer value, String attributePrefix, BaseExecutionContext ctx) {
Integer attribute = ctx.getAttribute(buildAttributeName(attributePrefix, name));
if (attribute != null) {
return attribute;
}
return value;
}
private Long evalLongProperty(String name, Long value, String attributePrefix, BaseExecutionContext ctx) {
Long attribute = ctx.getAttribute(buildAttributeName(attributePrefix, name));
if (attribute != null) {
return attribute;
}
return value;
}
private Boolean evalBooleanProperty(String name, Boolean value, String attributePrefix, BaseExecutionContext ctx) {
Boolean attribute = ctx.getAttribute(buildAttributeName(attributePrefix, name));
if (attribute != null) {
return attribute;
}
return value;
}
private Set evalSetProperty(String name, Set value, String attributePrefix, BaseExecutionContext ctx) {
//Try to get a Set and if it fails try to get a String and split it
try {
Set attribute = ctx.getAttribute(buildAttributeName(attributePrefix, name));
if (attribute != null) {
return attribute;
}
} catch (ClassCastException cce) {
List attribute = ctx.getAttributeAsList(buildAttributeName(attributePrefix, name));
if(attribute != null) {
return Set.copyOf(attribute);
}
}
return value;
}
private List evalListProperty(String name, List value, String attributePrefix, BaseExecutionContext ctx) {
List attribute = ctx.getAttributeAsList(buildAttributeName(attributePrefix, name));
if (attribute != null) {
return attribute;
}
return value;
}
private Maybe> evalListStringProperty(String name, List value, String attributePrefix, BaseExecutionContext ctx) {
List attribute = ctx.getAttributeAsList(buildAttributeName(attributePrefix, name));
if (attribute != null) {
//If a value is found for this attribute, override the original value with it
value = attribute;
}
//If value is null, return empty
if(value == null) {
return Maybe.empty();
}
//Then check EL
return Flowable.fromIterable(value).filter(Objects::nonNull)
.flatMapMaybe(v -> ctx
.getTemplateEngine()
.eval(v, String.class)
.doOnError(throwable -> logger.error("Unable to evaluate property [{}] with expression [{}].", name, v)))
.toList()
.toMaybe();
}
private Maybe> evalListStringProperty(String name, List value, String attributePrefix, DeploymentContext ctx) {
//If value is null, return empty
if(value == null) {
return Maybe.empty();
}
//Then check EL
return Flowable.fromIterable(value).filter(Objects::nonNull)
.flatMapMaybe(v -> ctx
.getTemplateEngine()
.eval(v, String.class)
.doOnError(throwable -> logger.error("Unable to evaluate property [{}] with expression [{}].", name, v)))
.toList()
.toMaybe();
}
private Maybe> evalListHeaderProperty(
String name,
List headers,
String attributePrefix,
BaseExecutionContext ctx
) {
//First check attributes
String attributeName = buildAttributeName(attributePrefix, name);
List attribute = ctx.getAttribute(attributeName);
if (attribute != null) {
//If a value is found for this attribute, override the original value with it
headers = attribute;
}
//If headers is null, return empty
if (headers == null) {
return Maybe.empty();
}
//Then check EL
return Flowable
.fromIterable(headers)
.filter(Objects::nonNull)
.flatMapMaybe(header -> {
SecretFieldAccessControl accessControl = new SecretFieldAccessControl(true, FieldKind.HEADER, header.getName());
return ctx
.getTemplateEngine()
.eval(header.getValue(), String.class)
.doOnSubscribe(d ->
ctx.getTemplateEngine().getTemplateContext().setVariable(SecretFieldAccessControl.EL_VARIABLE, accessControl)
)
.doOnTerminate(() ->
ctx.getTemplateEngine().getTemplateContext().setVariable(SecretFieldAccessControl.EL_VARIABLE, null)
)
.map(evaluatedValue -> new HttpHeader(header.getName(), evaluatedValue))
.doOnError(throwable -> logger.error("Unable to evaluate property [{}] with expression [{}].", name, header.getValue())
);
})
.toList()
.toMaybe();
}
private Maybe> evalListHeaderProperty(
String name,
List headers,
String attributePrefix,
DeploymentContext ctx
) {
//If headers is null, return empty
if (headers == null) {
return Maybe.empty();
}
//Then check EL
return Flowable
.fromIterable(headers)
.filter(Objects::nonNull)
.flatMapMaybe(header -> {
SecretFieldAccessControl accessControl = new SecretFieldAccessControl(true, FieldKind.HEADER, header.getName());
return ctx
.getTemplateEngine()
.eval(header.getValue(), String.class)
.doOnSubscribe(d ->
ctx.getTemplateEngine().getTemplateContext().setVariable(SecretFieldAccessControl.EL_VARIABLE, accessControl)
)
.doOnTerminate(() ->
ctx.getTemplateEngine().getTemplateContext().setVariable(SecretFieldAccessControl.EL_VARIABLE, null)
)
.map(evaluatedValue -> new HttpHeader(header.getName(), evaluatedValue))
.doOnError(throwable -> logger.error("Unable to evaluate property [{}] with expression [{}].", name, header.getValue())
);
})
.toList()
.toMaybe();
}
private void validateConfiguration(T configuration) {
Set> constraintViolations = validator.validate(configuration);
if (!constraintViolations.isEmpty()) {
StringBuilder exceptionMessage = new StringBuilder(constraintViolations.size() + " constraint violations found : ");
constraintViolations.forEach(violation ->
exceptionMessage
.append("[attribute[")
.append(violation.getPropertyPath())
.append("] reason[")
.append(violation.getMessage())
.append("]]")
);
//LOG
logger.error(exceptionMessage.toString());
//Throw exception with info
throw new IllegalStateException(exceptionMessage.toString());
}
}
/**
* Blocking eval method (see {@link #eval(BaseExecutionContext)} Eval})
* Caution when using this method if the evaluation involves EL expressions that trigger blocking fetches
* @param ctx the current execution context
* @return configuration with all dynamic configuration parameters updated
*/
public {{simpleClassName}} evalNow(BaseExecutionContext ctx) {
return eval(ctx).blockingGet();
}
/**
* Blocking eval method (see {@link #eval(DeploymentContext)} Eval})
* Caution when using this method if the evaluation involves EL expressions that trigger blocking fetches
* @param ctx the current deployment context
* @return configuration with all dynamic configuration parameters updated
*/
public {{simpleClassName}} evalNow(DeploymentContext ctx) {
return eval(ctx).blockingGet();
}
/**
* Evaluates the configuration using the execution context to update parameters using attributes or EL
* and stores it as an internal attributes to avoid multiple evaluation
* @param ctx the current context
* @return configuration with all dynamic configuration parameters updated
*/
public Single<{{simpleClassName}}> eval(BaseExecutionContext ctx) {
return eval(ctx, null);
}
/**
* Evaluates the configuration using a deployment context to update parameters using EL
* and stores it as an internal attributes to avoid multiple evaluation
* @param ctx the current deployment context
* @return configuration with all dynamic configuration parameters updated
*/
public Single<{{simpleClassName}}> eval(DeploymentContext ctx) {
return eval(null, ctx);
}
private Single<{{simpleClassName}}> eval(BaseExecutionContext baseExecutionContext, DeploymentContext deploymentContext) {
if(baseExecutionContext != null) {
if (attributePrefix.isEmpty()) {
return Single.error(new IllegalArgumentException("@ConfigurationEvaluator(attributePrefix=\"...\") is required when using BaseExecutionContext."));
}
//First check if the configuration has not been already evaluated
{{simpleClassName}} evaluatedConf = baseExecutionContext.getInternalAttribute("{{evaluatedConfigurationName}}-"+this.internalId);
if(evaluatedConf != null) {
return Single.just(evaluatedConf);
}
}
{{simpleClassName}} evaluatedConfiguration;
try {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
evaluatedConfiguration = objectMapper.readValue(objectMapper.writeValueAsString(configuration), {{simpleClassName}}.class);
} catch (com.fasterxml.jackson.core.JsonProcessingException e) {
logger.error("Unable to clone configuration", e);
return Single.error(e);
}
String currentAttributePrefix = attributePrefix;
List> toEval = new ArrayList<>();
List>> toEvalList = new ArrayList<>();
List>> toEvalHeaderList = new ArrayList<>();
© 2015 - 2025 Weber Informatics LLC | Privacy Policy