001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.management.mbean; 018 019import java.util.Collections; 020import java.util.List; 021import java.util.Map; 022import java.util.Map.Entry; 023import java.util.Optional; 024import java.util.Set; 025import java.util.stream.Collectors; 026 027import org.apache.camel.Component; 028import org.apache.camel.ServiceStatus; 029import org.apache.camel.StatefulService; 030import org.apache.camel.api.management.ManagedInstance; 031import org.apache.camel.api.management.ManagedResource; 032import org.apache.camel.api.management.mbean.ComponentVerifierExtension; 033import org.apache.camel.api.management.mbean.ComponentVerifierExtension.Result; 034import org.apache.camel.api.management.mbean.ComponentVerifierExtension.Result.Status; 035import org.apache.camel.api.management.mbean.ComponentVerifierExtension.Scope; 036import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError; 037import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError.ExceptionAttribute; 038import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError.GroupAttribute; 039import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError.HttpAttribute; 040import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError.StandardCode; 041import org.apache.camel.api.management.mbean.ManagedComponentMBean; 042import org.apache.camel.spi.ManagementStrategy; 043import org.apache.camel.support.HealthCheckComponent; 044import org.apache.camel.util.CastUtils; 045 046@ManagedResource(description = "Managed Component") 047public class ManagedComponent implements ManagedInstance, ManagedComponentMBean { 048 private final Component component; 049 private final String name; 050 051 public ManagedComponent(String name, Component component) { 052 this.name = name; 053 this.component = component; 054 } 055 056 public void init(ManagementStrategy strategy) { 057 // do nothing 058 } 059 060 public Component getComponent() { 061 return component; 062 } 063 064 @Override 065 public String getComponentName() { 066 return name; 067 } 068 069 @Override 070 public String getState() { 071 // must use String type to be sure remote JMX can read the attribute without requiring Camel classes. 072 if (component instanceof StatefulService statefulService) { 073 ServiceStatus status = statefulService.getStatus(); 074 return status.name(); 075 } 076 077 // assume started if not a ServiceSupport instance 078 return ServiceStatus.Started.name(); 079 } 080 081 @Override 082 public String getCamelId() { 083 return component.getCamelContext().getName(); 084 } 085 086 @Override 087 public String getCamelManagementName() { 088 return component.getCamelContext().getManagementName(); 089 } 090 091 @Override 092 public Object getInstance() { 093 return component; 094 } 095 096 @Override 097 public boolean isHealthCheckSupported() { 098 return component instanceof HealthCheckComponent; 099 } 100 101 @Override 102 public boolean isHealthCheckConsumerEnabled() { 103 if (component instanceof HealthCheckComponent healthCheckComponent) { 104 return healthCheckComponent.isHealthCheckConsumerEnabled(); 105 } 106 return false; 107 } 108 109 @Override 110 public boolean isHealthCheckProducerEnabled() { 111 if (component instanceof HealthCheckComponent healthCheckComponent) { 112 return healthCheckComponent.isHealthCheckProducerEnabled(); 113 } 114 return false; 115 } 116 117 @Override 118 public boolean isVerifySupported() { 119 return component.getExtension(org.apache.camel.component.extension.ComponentVerifierExtension.class).isPresent(); 120 } 121 122 @Override 123 public ComponentVerifierExtension.Result verify(String scope, Map<String, String> options) { 124 try { 125 org.apache.camel.component.extension.ComponentVerifierExtension.Scope scopeEnum 126 = org.apache.camel.component.extension.ComponentVerifierExtension.Scope.fromString(scope); 127 Optional<org.apache.camel.component.extension.ComponentVerifierExtension> verifier 128 = component.getExtension(org.apache.camel.component.extension.ComponentVerifierExtension.class); 129 if (verifier.isPresent()) { 130 org.apache.camel.component.extension.ComponentVerifierExtension.Result result 131 = verifier.get().verify(scopeEnum, CastUtils.cast(options)); 132 String rstatus = result.getStatus().toString(); 133 String rscope = result.getScope().toString(); 134 return new ResultImpl( 135 Scope.valueOf(rscope), Status.valueOf(rstatus), 136 result.getErrors().stream().map(this::translate).toList()); 137 138 } else { 139 return new ResultImpl(Scope.PARAMETERS, Status.UNSUPPORTED, Collections.emptyList()); 140 } 141 } catch (IllegalArgumentException e) { 142 return new ResultImpl( 143 Scope.PARAMETERS, Status.UNSUPPORTED, Collections.singletonList( 144 new VerificationErrorImpl(StandardCode.UNSUPPORTED_SCOPE, "Unsupported scope: " + scope))); 145 } 146 } 147 148 private VerificationError translate( 149 org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError error) { 150 return new VerificationErrorImpl( 151 translate(error.getCode()), error.getDescription(), 152 error.getParameterKeys(), translate(error.getDetails())); 153 } 154 155 private Map<VerificationError.Attribute, Object> translate( 156 Map<org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.Attribute, Object> details) { 157 return details.entrySet().stream().collect(Collectors.toMap(e -> translate(e.getKey()), Entry::getValue)); 158 } 159 160 private VerificationError.Attribute translate( 161 org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.Attribute attribute) { 162 if (attribute 163 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.GroupAttribute.GROUP_NAME) { 164 return GroupAttribute.GROUP_NAME; 165 } else if (attribute 166 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.GroupAttribute.GROUP_OPTIONS) { 167 return GroupAttribute.GROUP_OPTIONS; 168 } else if (attribute 169 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_CODE) { 170 return HttpAttribute.HTTP_CODE; 171 } else if (attribute 172 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_REDIRECT) { 173 return HttpAttribute.HTTP_REDIRECT; 174 } else if (attribute 175 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_TEXT) { 176 return HttpAttribute.HTTP_TEXT; 177 } else if (attribute 178 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_CLASS) { 179 return ExceptionAttribute.EXCEPTION_CLASS; 180 } else if (attribute 181 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) { 182 return ExceptionAttribute.EXCEPTION_INSTANCE; 183 } else if (attribute != null) { 184 return VerificationError.asAttribute(attribute.getName()); 185 } else { 186 return null; 187 } 188 } 189 190 private VerificationError.Code translate( 191 org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.Code code) { 192 if (code 193 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.AUTHENTICATION) { 194 return StandardCode.AUTHENTICATION; 195 } else if (code 196 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION) { 197 return StandardCode.EXCEPTION; 198 } else if (code 199 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.INTERNAL) { 200 return StandardCode.INTERNAL; 201 } else if (code 202 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER) { 203 return StandardCode.MISSING_PARAMETER; 204 } else if (code 205 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.UNKNOWN_PARAMETER) { 206 return StandardCode.UNKNOWN_PARAMETER; 207 } else if (code 208 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.ILLEGAL_PARAMETER) { 209 return StandardCode.ILLEGAL_PARAMETER; 210 } else if (code 211 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.ILLEGAL_PARAMETER_GROUP_COMBINATION) { 212 return StandardCode.ILLEGAL_PARAMETER_GROUP_COMBINATION; 213 } else if (code 214 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.ILLEGAL_PARAMETER_VALUE) { 215 return StandardCode.ILLEGAL_PARAMETER_VALUE; 216 } else if (code 217 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP) { 218 return StandardCode.ILLEGAL_PARAMETER_GROUP_COMBINATION; 219 } else if (code 220 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.UNSUPPORTED) { 221 return StandardCode.UNSUPPORTED; 222 } else if (code 223 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.UNSUPPORTED_SCOPE) { 224 return StandardCode.UNSUPPORTED_SCOPE; 225 } else if (code 226 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.UNSUPPORTED_COMPONENT) { 227 return StandardCode.UNSUPPORTED_COMPONENT; 228 } else if (code 229 == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.GENERIC) { 230 return StandardCode.GENERIC; 231 } else if (code != null) { 232 return VerificationError.asCode(code.getName()); 233 } else { 234 return null; 235 } 236 } 237 238 public static class VerificationErrorImpl implements VerificationError { 239 private final Code code; 240 private final String description; 241 private final Set<String> parameterKeys; 242 private final Map<Attribute, Object> details; 243 244 public VerificationErrorImpl(Code code, String description) { 245 this.code = code; 246 this.description = description; 247 this.parameterKeys = Collections.emptySet(); 248 this.details = Collections.emptyMap(); 249 } 250 251 public VerificationErrorImpl(Code code, String description, Set<String> parameterKeys, Map<Attribute, Object> details) { 252 this.code = code; 253 this.description = description; 254 this.parameterKeys = parameterKeys; 255 this.details = details; 256 } 257 258 @Override 259 public Code getCode() { 260 return code; 261 } 262 263 @Override 264 public String getDescription() { 265 return description; 266 } 267 268 @Override 269 public Set<String> getParameterKeys() { 270 return parameterKeys; 271 } 272 273 @Override 274 public Map<Attribute, Object> getDetails() { 275 return details; 276 } 277 } 278 279 public static class ResultImpl implements Result { 280 private final Scope scope; 281 private final Status status; 282 private final List<VerificationError> errors; 283 284 public ResultImpl(Scope scope, Status status, List<VerificationError> errors) { 285 this.scope = scope; 286 this.status = status; 287 this.errors = errors; 288 } 289 290 @Override 291 public Scope getScope() { 292 return scope; 293 } 294 295 @Override 296 public Status getStatus() { 297 return status; 298 } 299 300 @Override 301 public List<VerificationError> getErrors() { 302 return errors; 303 } 304 } 305}