pub use camel_api::{LanguageExpressionDef, StreamSplitConfig, ValueSourceDef};
#[derive(Default)]
pub struct SecurityCompileContext {
pub authenticator: Option<std::sync::Arc<dyn camel_auth::TokenAuthenticator>>,
pub registry: Option<std::sync::Arc<camel_auth::SecurityPolicyRegistry>>,
pub evaluator_registry: Option<std::sync::Arc<camel_auth::PermissionEvaluatorRegistry>>,
}
impl Clone for SecurityCompileContext {
fn clone(&self) -> Self {
Self {
authenticator: self.authenticator.clone(),
registry: self.registry.clone(),
evaluator_registry: self.evaluator_registry.clone(),
}
}
}
impl SecurityCompileContext {
pub fn new(
authenticator: Option<std::sync::Arc<dyn camel_auth::TokenAuthenticator>>,
registry: Option<std::sync::Arc<camel_auth::SecurityPolicyRegistry>>,
) -> Self {
Self {
authenticator,
registry,
evaluator_registry: None,
}
}
pub fn with_evaluator_registry(
mut self,
registry: std::sync::Arc<camel_auth::PermissionEvaluatorRegistry>,
) -> Self {
self.evaluator_registry = Some(registry);
self
}
pub fn with_security_policy_registry(
mut self,
registry: std::sync::Arc<camel_auth::SecurityPolicyRegistry>,
) -> Self {
self.registry = Some(registry);
self
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DeclarativeConcurrency {
Sequential,
Concurrent { max: Option<usize> },
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DeclarativeCircuitBreaker {
pub failure_threshold: u32,
pub open_duration_ms: u64,
}
#[derive(Debug, Clone, PartialEq)]
pub enum DeclarativeSecurityPolicy {
Roles {
roles: Vec<String>,
all_required: bool,
trust_upstream_principal: bool,
},
Scopes {
scopes: Vec<String>,
all_required: bool,
trust_upstream_principal: bool,
},
Ref {
name: String,
},
Wasm {
path: String,
config: std::collections::HashMap<String, String>,
},
Permission {
policy: String,
resource: camel_auth::PermissionValueSource,
action: camel_auth::PermissionValueSource,
scopes: Vec<String>,
context: camel_auth::PermissionContextConfig,
cache_ttl_secs: Option<u64>,
cache_negative_ttl_secs: Option<u64>,
},
}
#[derive(Debug, Clone, PartialEq)]
pub struct DeclarativeRedeliveryPolicy {
pub max_attempts: u32,
pub initial_delay_ms: u64,
pub multiplier: f64,
pub max_delay_ms: u64,
pub jitter_factor: f64,
pub handled_by: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct DeclarativeOnException {
pub kind: Option<String>,
pub message_contains: Option<String>,
pub retry: Option<DeclarativeRedeliveryPolicy>,
pub steps: Vec<DeclarativeStep>,
pub handled: Option<bool>,
pub continued: Option<bool>,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct DeclarativeErrorHandler {
pub dead_letter_channel: Option<String>,
pub retry: Option<DeclarativeRedeliveryPolicy>,
pub on_exceptions: Option<Vec<DeclarativeOnException>>,
pub use_original_message: bool,
}
#[derive(Debug, Clone)]
pub struct DeclarativeRoute {
pub from: String,
pub route_id: String,
pub auto_startup: bool,
pub startup_order: i32,
pub concurrency: Option<DeclarativeConcurrency>,
pub error_handler: Option<DeclarativeErrorHandler>,
pub circuit_breaker: Option<DeclarativeCircuitBreaker>,
pub security_policy: Option<DeclarativeSecurityPolicy>,
pub unit_of_work: Option<camel_api::UnitOfWorkConfig>,
pub steps: Vec<DeclarativeStep>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ToStepDef {
pub uri: String,
}
impl ToStepDef {
pub fn new(uri: impl Into<String>) -> Self {
Self { uri: uri.into() }
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LogLevelDef {
Trace,
Debug,
Info,
Warn,
Error,
}
#[derive(Debug, Clone, PartialEq)]
pub struct LogStepDef {
pub message: ValueSourceDef,
pub level: LogLevelDef,
}
impl LogStepDef {
pub fn info(message: impl Into<String>) -> Self {
Self {
message: ValueSourceDef::Literal(serde_json::Value::String(message.into())),
level: LogLevelDef::Info,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SetHeaderStepDef {
pub key: String,
pub value: ValueSourceDef,
}
impl SetHeaderStepDef {
pub fn literal(key: impl Into<String>, value: impl Into<String>) -> Self {
Self {
key: key.into(),
value: ValueSourceDef::Literal(serde_json::Value::String(value.into())),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SetPropertyStepDef {
pub key: String,
pub value: ValueSourceDef,
}
impl SetPropertyStepDef {
pub fn literal(key: impl Into<String>, value: impl Into<String>) -> Self {
Self {
key: key.into(),
value: ValueSourceDef::Literal(serde_json::Value::String(value.into())),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SetBodyStepDef {
pub value: ValueSourceDef,
}
#[derive(Debug, Clone, PartialEq)]
pub struct FilterStepDef {
pub predicate: LanguageExpressionDef,
pub steps: Vec<DeclarativeStep>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FunctionStepDef {
pub runtime: String,
pub source: String,
pub timeout_ms: Option<u64>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct WhenStepDef {
pub predicate: LanguageExpressionDef,
pub steps: Vec<DeclarativeStep>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ChoiceStepDef {
pub whens: Vec<WhenStepDef>,
pub otherwise: Option<Vec<DeclarativeStep>>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum SplitExpressionDef {
BodyLines,
BodyJsonArray,
Language(LanguageExpressionDef),
Stream(StreamSplitConfig),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SplitAggregationDef {
LastWins,
CollectAll,
Original,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SplitStepDef {
pub expression: SplitExpressionDef,
pub aggregation: SplitAggregationDef,
pub parallel: bool,
pub parallel_limit: Option<usize>,
pub stop_on_exception: bool,
pub steps: Vec<DeclarativeStep>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AggregateStrategyDef {
CollectAll,
}
#[derive(Debug, Clone, PartialEq)]
pub struct AggregateStepDef {
pub header: String,
pub correlation_key: Option<String>,
pub completion_size: Option<usize>,
pub completion_timeout_ms: Option<u64>,
pub completion_predicate: Option<LanguageExpressionDef>,
pub strategy: AggregateStrategyDef,
pub max_buckets: Option<usize>,
pub bucket_ttl_ms: Option<u64>,
pub force_completion_on_stop: Option<bool>,
pub discard_on_timeout: Option<bool>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WireTapStepDef {
pub uri: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BeanStepDef {
pub name: String,
pub method: String,
}
impl BeanStepDef {
pub fn new(name: impl Into<String>, method: impl Into<String>) -> Self {
Self {
name: name.into(),
method: method.into(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub enum ThrottleStrategyDef {
#[default]
Delay,
Reject,
Drop,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ThrottleStepDef {
pub max_requests: usize,
pub period_ms: u64,
pub strategy: ThrottleStrategyDef,
pub steps: Vec<DeclarativeStep>,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub enum LoadBalanceStrategyDef {
#[default]
RoundRobin,
Random,
Failover,
Weighted {
distribution_ratio: String,
},
}
#[derive(Debug, Clone, PartialEq)]
pub struct LoadBalanceStepDef {
pub strategy: LoadBalanceStrategyDef,
pub steps: Vec<DeclarativeStep>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DynamicRouterStepDef {
pub expression: LanguageExpressionDef,
pub uri_delimiter: String,
pub cache_size: i32,
pub ignore_invalid_endpoints: bool,
pub max_iterations: usize,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RoutingSlipStepDef {
pub expression: LanguageExpressionDef,
pub uri_delimiter: String,
pub cache_size: i32,
pub ignore_invalid_endpoints: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RecipientListStepDef {
pub expression: LanguageExpressionDef,
pub delimiter: String,
pub parallel: bool,
pub parallel_limit: Option<usize>,
pub stop_on_exception: bool,
pub aggregation: MulticastAggregationDef,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MulticastAggregationDef {
LastWins,
CollectAll,
Original,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MulticastStepDef {
pub steps: Vec<DeclarativeStep>,
pub parallel: bool,
pub parallel_limit: Option<usize>,
pub stop_on_exception: bool,
pub timeout_ms: Option<u64>,
pub aggregation: MulticastAggregationDef,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ScriptStepDef {
pub expression: LanguageExpressionDef,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BodyTypeDef {
Text,
Json,
Bytes,
Xml,
Empty,
}
#[derive(Debug, Clone, PartialEq)]
pub struct DataFormatDef {
pub format: String,
pub schema: Option<serde_json::Value>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DelayStepDef {
pub delay_ms: u64,
pub dynamic_header: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct LoopStepDef {
pub count: Option<usize>,
pub while_predicate: Option<LanguageExpressionDef>,
pub steps: Vec<DeclarativeStep>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StreamCacheStepDef {
pub threshold: Option<usize>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ValidateStepDef {
pub predicate: LanguageExpressionDef,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ClaimCheckStepDef {
pub repository: String,
pub operation: String,
pub key: LanguageExpressionDef,
pub filter: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct IdempotentConsumerStepDef {
pub repository: String,
pub expression: LanguageExpressionDef,
pub steps: Vec<DeclarativeStep>,
pub eager: Option<bool>,
pub remove_on_failure: Option<bool>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SamplingStepDef {
pub period: usize,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SortStepDef {
pub expression: LanguageExpressionDef,
pub reverse: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ResequenceStepDef {
pub mode: ResequenceModeDef,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ResequenceModeDef {
Batch {
correlation: String,
sort: String,
completion: camel_api::resequencer::BatchCompletion,
},
Stream {
sequence: String,
capacity: usize,
gap_timeout: u64,
on_gap: camel_api::resequencer::GapPolicy,
on_capacity_exceeded: camel_api::resequencer::CapacityPolicy,
dedup: bool,
},
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EnrichStepDef {
pub uri: String,
pub strategy: Option<String>,
pub timeout_ms: Option<u64>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct DoTryCatchClauseDef {
pub exception: Option<Vec<String>>,
pub when: Option<LanguageExpressionDef>,
pub on_when: Option<LanguageExpressionDef>,
pub disposition: camel_api::error_handler::ExceptionDisposition,
pub steps: Vec<DeclarativeStep>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct DoTryFinallyDef {
pub on_when: Option<LanguageExpressionDef>,
pub steps: Vec<DeclarativeStep>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum DeclarativeStep {
To(ToStepDef),
SetHeader(SetHeaderStepDef),
SetProperty(SetPropertyStepDef),
SetBody(SetBodyStepDef),
ConvertBodyTo(BodyTypeDef),
DynamicRouter(DynamicRouterStepDef),
Filter(FilterStepDef),
Function(FunctionStepDef),
LoadBalance(LoadBalanceStepDef),
Log(LogStepDef),
Choice(ChoiceStepDef),
Split(SplitStepDef),
Aggregate(AggregateStepDef),
WireTap(WireTapStepDef),
Multicast(MulticastStepDef),
RoutingSlip(RoutingSlipStepDef),
RecipientList(RecipientListStepDef),
Stop,
Throttle(ThrottleStepDef),
Script(ScriptStepDef),
StreamCache(StreamCacheStepDef),
Marshal(DataFormatDef),
Unmarshal(DataFormatDef),
Validate(ValidateStepDef),
Bean(BeanStepDef),
Delay(DelayStepDef),
Loop(LoopStepDef),
Enrich(EnrichStepDef),
PollEnrich(EnrichStepDef),
IdempotentConsumer(IdempotentConsumerStepDef),
ClaimCheck(ClaimCheckStepDef),
Sampling(SamplingStepDef),
Sort(SortStepDef),
Resequence(ResequenceStepDef),
DoTry {
steps: Vec<DeclarativeStep>,
catch: Vec<DoTryCatchClauseDef>,
finally: Option<DoTryFinallyDef>,
},
}
impl DeclarativeStep {
pub fn kind(&self) -> crate::contract::DeclarativeStepKind {
match self {
DeclarativeStep::To(_) => crate::contract::DeclarativeStepKind::To,
DeclarativeStep::Log(_) => crate::contract::DeclarativeStepKind::Log,
DeclarativeStep::SetHeader(_) => crate::contract::DeclarativeStepKind::SetHeader,
DeclarativeStep::SetProperty(_) => crate::contract::DeclarativeStepKind::SetProperty,
DeclarativeStep::SetBody(_) => crate::contract::DeclarativeStepKind::SetBody,
DeclarativeStep::ConvertBodyTo(_) => {
crate::contract::DeclarativeStepKind::ConvertBodyTo
}
DeclarativeStep::DynamicRouter(_) => {
crate::contract::DeclarativeStepKind::DynamicRouter
}
DeclarativeStep::Filter(_) => crate::contract::DeclarativeStepKind::Filter,
DeclarativeStep::Function(_) => crate::contract::DeclarativeStepKind::Function,
DeclarativeStep::LoadBalance(_) => crate::contract::DeclarativeStepKind::LoadBalance,
DeclarativeStep::Choice(_) => crate::contract::DeclarativeStepKind::Choice,
DeclarativeStep::Split(_) => crate::contract::DeclarativeStepKind::Split,
DeclarativeStep::Aggregate(_) => crate::contract::DeclarativeStepKind::Aggregate,
DeclarativeStep::WireTap(_) => crate::contract::DeclarativeStepKind::WireTap,
DeclarativeStep::Multicast(_) => crate::contract::DeclarativeStepKind::Multicast,
DeclarativeStep::RoutingSlip(_) => crate::contract::DeclarativeStepKind::RoutingSlip,
DeclarativeStep::RecipientList(_) => {
crate::contract::DeclarativeStepKind::RecipientList
}
DeclarativeStep::Stop => crate::contract::DeclarativeStepKind::Stop,
DeclarativeStep::Throttle(_) => crate::contract::DeclarativeStepKind::Throttle,
DeclarativeStep::Script(_) => crate::contract::DeclarativeStepKind::Script,
DeclarativeStep::StreamCache(_) => crate::contract::DeclarativeStepKind::StreamCache,
DeclarativeStep::Marshal(_) => crate::contract::DeclarativeStepKind::Marshal,
DeclarativeStep::Unmarshal(_) => crate::contract::DeclarativeStepKind::Unmarshal,
DeclarativeStep::Validate(_) => crate::contract::DeclarativeStepKind::Validate,
DeclarativeStep::Bean(_) => crate::contract::DeclarativeStepKind::Bean,
DeclarativeStep::Delay(_) => crate::contract::DeclarativeStepKind::Delay,
DeclarativeStep::Loop(_) => crate::contract::DeclarativeStepKind::Loop,
DeclarativeStep::Enrich(_) => crate::contract::DeclarativeStepKind::Enrich,
DeclarativeStep::PollEnrich(_) => crate::contract::DeclarativeStepKind::PollEnrich,
DeclarativeStep::IdempotentConsumer(_) => {
crate::contract::DeclarativeStepKind::IdempotentConsumer
}
DeclarativeStep::ClaimCheck(_) => crate::contract::DeclarativeStepKind::ClaimCheck,
DeclarativeStep::Sampling(_) => crate::contract::DeclarativeStepKind::Sampling,
DeclarativeStep::Sort(_) => crate::contract::DeclarativeStepKind::Sort,
DeclarativeStep::Resequence(_) => crate::contract::DeclarativeStepKind::Resequence,
DeclarativeStep::DoTry { .. } => crate::contract::DeclarativeStepKind::DoTry,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn to_step_def_new() {
let def = ToStepDef::new("direct:a");
assert_eq!(def.uri, "direct:a");
}
#[test]
fn log_step_def_info() {
let def = LogStepDef::info("hello");
assert_eq!(def.level, LogLevelDef::Info);
match def.message {
ValueSourceDef::Literal(v) => assert_eq!(v, serde_json::Value::String("hello".into())),
_ => panic!("expected literal"),
}
}
#[test]
fn set_header_literal() {
let def = SetHeaderStepDef::literal("key", "value");
assert_eq!(def.key, "key");
match def.value {
ValueSourceDef::Literal(v) => assert_eq!(v, serde_json::Value::String("value".into())),
_ => panic!("expected literal"),
}
}
#[test]
fn bean_step_def_new() {
let def = BeanStepDef::new("myBean", "process");
assert_eq!(def.name, "myBean");
assert_eq!(def.method, "process");
}
#[test]
fn throttle_strategy_default() {
assert_eq!(ThrottleStrategyDef::default(), ThrottleStrategyDef::Delay);
}
#[test]
fn load_balance_strategy_default() {
assert_eq!(
LoadBalanceStrategyDef::default(),
LoadBalanceStrategyDef::RoundRobin
);
}
#[test]
fn concurrency_variants_equality() {
assert_eq!(
DeclarativeConcurrency::Sequential,
DeclarativeConcurrency::Sequential
);
assert_ne!(
DeclarativeConcurrency::Sequential,
DeclarativeConcurrency::Concurrent { max: None }
);
}
#[test]
fn body_type_variants() {
assert_eq!(BodyTypeDef::Text, BodyTypeDef::Text);
assert_ne!(BodyTypeDef::Text, BodyTypeDef::Json);
}
#[test]
fn data_format_def() {
let def = DataFormatDef {
format: "protobuf".into(),
schema: None,
};
assert_eq!(def.format, "protobuf");
assert!(def.schema.is_none());
}
#[test]
fn stream_cache_step_def() {
let def = StreamCacheStepDef {
threshold: Some(1024),
};
assert_eq!(def.threshold, Some(1024));
}
#[test]
fn delay_step_def() {
let def = DelayStepDef {
delay_ms: 500,
dynamic_header: Some("X-Delay".into()),
};
assert_eq!(def.delay_ms, 500);
assert_eq!(def.dynamic_header.as_deref(), Some("X-Delay"));
}
#[test]
fn circuit_breaker_def() {
let cb = DeclarativeCircuitBreaker {
failure_threshold: 3,
open_duration_ms: 5000,
};
assert_eq!(cb.failure_threshold, 3);
assert_eq!(cb.open_duration_ms, 5000);
}
}