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.api.management.mbean; 018 019import java.io.Serializable; 020import java.util.List; 021import java.util.Map; 022import java.util.Set; 023 024import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError.Attribute; 025import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError.Code; 026import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError.ExceptionAttribute; 027import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError.GroupAttribute; 028import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError.HttpAttribute; 029import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError.StandardCode; 030 031/** 032 * Defines the interface used for validating component/endpoint parameters. The central method of this 033 * interface is {@link ManagedComponentMBean#verify(String, Map)} which takes a scope and a set of parameters which should be verified. 034 * <p/> 035 * The return value is a {@link ComponentVerifierExtension.Result} of the verification 036 * 037 */ 038public final class ComponentVerifierExtension { 039 040 /** 041 * The result of a verification 042 */ 043 public interface Result extends Serializable { 044 045 /** 046 * Status of the verification 047 */ 048 enum Status { 049 /** 050 * Verification succeeded 051 */ 052 OK, 053 /** 054 * Error occurred during the verification 055 */ 056 ERROR, 057 /** 058 * Verification is not supported. This can depend on the given scope. 059 */ 060 UNSUPPORTED 061 } 062 063 /** 064 * Scope of the verification. This is the scope given to the call to {@link ManagedComponentMBean#verify(String, Map)} and 065 * can be used for correlation. 066 * 067 * @return the scope against which the parameters have been validated. 068 */ 069 Scope getScope(); 070 071 /** 072 * Result of the validation as status. This should be the first datum to check after a verification 073 * happened. 074 * 075 * @return the status 076 */ 077 Status getStatus(); 078 079 /** 080 * Collection of errors happened for the verification. This list is empty (but non null) if the verification 081 * succeeded. 082 * 083 * @return a list of errors. Can be empty when verification was successful 084 */ 085 List<VerificationError> getErrors(); 086 } 087 088 /** 089 * The scope defines how the parameters should be verified. 090 */ 091 public enum Scope { 092 /** 093 * Only validate the parameters for their <em>syntactic</em> soundness. Verifications in this scope should 094 * be as fast as possible 095 */ 096 PARAMETERS, 097 098 /** 099 * Reach out to the backend and verify that a connection can be established. This means, if the verification 100 * in this scope succeeds, then it can safely be assumed that the component can be used. 101 */ 102 CONNECTIVITY; 103 104 /** 105 * Get an instance of this scope from a string representation 106 * 107 * @param scope the scope as string, which can be in any case 108 * @return the scope enum represented by this string 109 */ 110 public static Scope fromString(String scope) { 111 return Scope.valueOf(scope != null ? scope.toUpperCase() : null); 112 } 113 } 114 115 // ============================================================================================= 116 117 /** 118 * This interface represents a detailed error in case when the verification fails. 119 */ 120 public interface VerificationError extends Serializable { 121 122 /** 123 * The overall error code, which can be either a {@link StandardCode} or a custom code. It is 124 * recommended to stick to the predefined standard codes 125 * 126 * @return the general error code. 127 */ 128 Code getCode(); 129 130 /** 131 * A human readable description of the error in plain english 132 * 133 * @return the error description (if available) 134 */ 135 String getDescription(); 136 137 /** 138 * A set of input parameter names which fails the verification. These are keys to the parameter provided 139 * to {@link ManagedComponentMBean#verify(String, Map)}. 140 * 141 * @return the parameter names which are malformed and caused the failure of the validation 142 */ 143 Set<String> getParameterKeys(); 144 145 /** 146 * Details about the failed verification. The keys can be either predefined values 147 * ({@link ExceptionAttribute}, {@link HttpAttribute}, {@link GroupAttribute}) or it can be free-form 148 * custom keys specific to a component. The standard attributes are defined as enums in all uppercase (with 149 * underscore as separator), custom attributes are supposed to be in all lower case (also with underscores 150 * as separators) 151 * 152 * @return a number of key/value pair with additional information related to the verification. 153 */ 154 Map<Attribute, Object> getDetails(); 155 156 /** 157 * Get a single detail for a given attribute 158 * 159 * @param attribute the attribute to lookup 160 * @return the detail value or null if no such attribute exists 161 */ 162 default Object getDetail(Attribute attribute) { 163 Map<Attribute, Object> details = getDetails(); 164 if (details != null) { 165 return details.get(attribute); 166 } 167 return null; 168 } 169 170 /** 171 * Get a single detail for a given attribute 172 * 173 * @param attribute the attribute to lookup 174 * @return the detail value or null if no such attribute exists 175 */ 176 default Object getDetail(String attribute) { 177 return getDetail(asAttribute(attribute)); 178 } 179 180 /** 181 * Convert a string to an {@link Code} 182 * 183 * @param code the code to convert. It should be in all lower case (with 184 * underscore as a separator) to avoid overlap with {@link StandardCode} 185 * @return error code 186 */ 187 static Code asCode(String code) { 188 return new ErrorCode(code); 189 } 190 191 /** 192 * Convert a string to an {@link Attribute} 193 * 194 * @param attribute the string representation of an attribute to convert. It should be in all lower case (with 195 * underscore as a separator) to avoid overlap with standard attributes like {@link ExceptionAttribute}, 196 * {@link HttpAttribute} or {@link GroupAttribute} 197 * @return generated attribute 198 */ 199 static Attribute asAttribute(String attribute) { 200 return new ErrorAttribute(attribute); 201 } 202 203 /** 204 * Interface defining an error code. This is implemented by the {@link StandardCode} but also 205 * own code can be generated by implementing this interface. This is best done via {@link #asCode(String)} 206 * If possible, the standard codes should be reused 207 */ 208 interface Code extends Serializable { 209 /** 210 * Name of the code. All uppercase for standard codes, all lower case for custom codes. 211 * Separator between two words is an underscore. 212 * 213 * @return code name 214 */ 215 String name(); 216 217 /** 218 * Bean style accessor to name. 219 * This is required for framework like Jackson using bean convention for object serialization. 220 * 221 * @return code name 222 */ 223 default String getName() { 224 return name(); 225 } 226 } 227 228 /** 229 * Standard set of error codes 230 */ 231 interface StandardCode extends Code { 232 /** 233 * Authentication failed 234 */ 235 StandardCode AUTHENTICATION = new StandardErrorCode("AUTHENTICATION"); 236 /** 237 * An exception occurred 238 */ 239 StandardCode EXCEPTION = new StandardErrorCode("EXCEPTION"); 240 /** 241 * Internal error while performing the verification 242 */ 243 StandardCode INTERNAL = new StandardErrorCode("INTERNAL"); 244 /** 245 * A mandatory parameter is missing 246 */ 247 StandardCode MISSING_PARAMETER = new StandardErrorCode("MISSING_PARAMETER"); 248 /** 249 * A given parameter is not known to the component 250 */ 251 StandardCode UNKNOWN_PARAMETER = new StandardErrorCode("UNKNOWN_PARAMETER"); 252 /** 253 * A given parameter is illegal 254 */ 255 StandardCode ILLEGAL_PARAMETER = new StandardErrorCode("ILLEGAL_PARAMETER"); 256 /** 257 * A combination of parameters is illegal. See {@link VerificationError#getParameterKeys()} for the set 258 * of affected parameters 259 */ 260 StandardCode ILLEGAL_PARAMETER_GROUP_COMBINATION = new StandardErrorCode("ILLEGAL_PARAMETER_GROUP_COMBINATION"); 261 /** 262 * A parameter <em>value</em> is not valid 263 */ 264 StandardCode ILLEGAL_PARAMETER_VALUE = new StandardErrorCode("ILLEGAL_PARAMETER_VALUE"); 265 /** 266 * A group of parameters is not complete in order to be valid 267 */ 268 StandardCode INCOMPLETE_PARAMETER_GROUP = new StandardErrorCode("INCOMPLETE_PARAMETER_GROUP"); 269 /** 270 * The verification is not supported 271 */ 272 StandardCode UNSUPPORTED = new StandardErrorCode("UNSUPPORTED"); 273 /** 274 * The requested {@link Scope} is not supported 275 */ 276 StandardCode UNSUPPORTED_SCOPE = new StandardErrorCode("UNSUPPORTED_SCOPE"); 277 /** 278 * The requested {@link Component} is not supported 279 */ 280 StandardCode UNSUPPORTED_COMPONENT = new StandardErrorCode("UNSUPPORTED_COMPONENT"); 281 /** 282 * Generic error which is explained in more details with {@link VerificationError#getDetails()} 283 */ 284 StandardCode GENERIC = new StandardErrorCode("GENERIC"); 285 } 286 287 /** 288 * Interface defining an attribute which is a key for the detailed error messages. 289 */ 290 interface Attribute extends Serializable { 291 /** 292 * Name of the attribute. All uppercase for standard attributes and all lower case for custom attributes. 293 * Separator between words is an underscore. 294 * 295 * @return attribute name 296 */ 297 String name(); 298 299 /** 300 * Bean style accessor to name; 301 * This is required for framework like Jackson using bean convention for object serialization. 302 * 303 * @return attribute name 304 */ 305 default String getName() { 306 return name(); 307 } 308 } 309 310 /** 311 * Attributes for details about an exception that was raised 312 */ 313 interface ExceptionAttribute extends Attribute { 314 /** 315 * The exception object that has been thrown. Note that this can be a complex 316 * object and can cause large content when e.g. serialized as JSON 317 */ 318 ExceptionAttribute EXCEPTION_INSTANCE = new ExceptionErrorAttribute("EXCEPTION_INSTANCE"); 319 /** 320 * The exception class 321 */ 322 ExceptionAttribute EXCEPTION_CLASS = new ExceptionErrorAttribute("EXCEPTION_CLASS"); 323 } 324 325 /** 326 * HTTP related error details 327 */ 328 interface HttpAttribute extends Attribute { 329 /** 330 * The erroneous HTTP code that occurred 331 */ 332 HttpAttribute HTTP_CODE = new HttpErrorAttribute("HTTP_CODE"); 333 /** 334 * HTTP response's body 335 */ 336 HttpAttribute HTTP_TEXT = new HttpErrorAttribute("HTTP_TEXT"); 337 /** 338 * If given as details, specifies that a redirect happened and the 339 * content of this detail is the redirect URL 340 */ 341 HttpAttribute HTTP_REDIRECT = new HttpErrorAttribute("HTTP_REDIRECT"); 342 } 343 344 /** 345 * Group related details 346 */ 347 interface GroupAttribute extends Attribute { 348 /** 349 * Group name 350 */ 351 GroupAttribute GROUP_NAME = new GroupErrorAttribute("GROUP_NAME"); 352 /** 353 * Options for the group 354 */ 355 GroupAttribute GROUP_OPTIONS = new GroupErrorAttribute("GROUP_OPTIONS"); 356 } 357 } 358 359 /** 360 * Custom class for error codes 361 */ 362 static class ErrorCode implements Code { 363 364 private final String name; 365 366 ErrorCode(String name) { 367 if (name == null) { 368 throw new IllegalArgumentException("Name of an error code must not be null"); 369 } 370 this.name = name; 371 } 372 373 @Override 374 public String name() { 375 return name; 376 } 377 378 @Override 379 public boolean equals(Object o) { 380 if (this == o) { 381 return true; 382 } 383 if (!(o instanceof Code)) { 384 return false; 385 } 386 387 Code errorCode = (Code) o; 388 389 return name.equals(errorCode.name()); 390 } 391 392 @Override 393 public int hashCode() { 394 return name.hashCode(); 395 } 396 397 @Override 398 public String toString() { 399 return name(); 400 } 401 } 402 403 static class ErrorAttribute implements Attribute { 404 405 private final String name; 406 407 ErrorAttribute(String name) { 408 if (name == null) { 409 throw new IllegalArgumentException("Name of an error attribute must not be null"); 410 } 411 this.name = name; 412 } 413 414 @Override 415 public String name() { 416 return name; 417 } 418 419 420 @Override 421 public boolean equals(Object o) { 422 if (this == o) { 423 return true; 424 } 425 if (!(o instanceof Attribute)) { 426 return false; 427 } 428 429 Attribute that = (Attribute) o; 430 431 return name.equals(that.name()); 432 } 433 434 @Override 435 public int hashCode() { 436 return name.hashCode(); 437 } 438 439 @Override 440 public String toString() { 441 return name(); 442 } 443 } 444 445 // =========================================================================================================== 446 // Helper classes for implementing the constants in ComponentVerifier: 447 448 static class StandardErrorCode extends ErrorCode implements StandardCode { 449 StandardErrorCode(String name) { 450 super(name); 451 } 452 } 453 454 static class ExceptionErrorAttribute extends ErrorAttribute implements ExceptionAttribute { 455 ExceptionErrorAttribute(String name) { 456 super(name); 457 } 458 } 459 460 static class HttpErrorAttribute extends ErrorAttribute implements HttpAttribute { 461 HttpErrorAttribute(String name) { 462 super(name); 463 } 464 } 465 466 static class GroupErrorAttribute extends ErrorAttribute implements GroupAttribute { 467 GroupErrorAttribute(String name) { 468 super(name); 469 } 470 } 471}