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 */ 037public final class ComponentVerifierExtension { 038 039 /** 040 * The result of a verification 041 */ 042 public interface Result extends Serializable { 043 044 /** 045 * Status of the verification 046 */ 047 enum Status { 048 /** 049 * Verification succeeded 050 */ 051 OK, 052 /** 053 * Error occurred during the verification 054 */ 055 ERROR, 056 /** 057 * Verification is not supported. This can depend on the given scope. 058 */ 059 UNSUPPORTED 060 } 061 062 /** 063 * Scope of the verification. This is the scope given to the call to {@link ManagedComponentMBean#verify(String, Map)} and 064 * can be used for correlation. 065 * 066 * @return the scope against which the parameters have been validated. 067 */ 068 Scope getScope(); 069 070 /** 071 * Result of the validation as status. This should be the first datum to check after a verification 072 * happened. 073 * 074 * @return the status 075 */ 076 Status getStatus(); 077 078 /** 079 * Collection of errors happened for the verification. This list is empty (but non null) if the verification 080 * succeeded. 081 * 082 * @return a list of errors. Can be empty when verification was successful 083 */ 084 List<VerificationError> getErrors(); 085 } 086 087 /** 088 * The scope defines how the parameters should be verified. 089 */ 090 public enum Scope { 091 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 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 /** 293 * Name of the attribute. All uppercase for standard attributes and all lower case for custom attributes. 294 * Separator between words is an underscore. 295 * 296 * @return attribute name 297 */ 298 String name(); 299 300 /** 301 * Bean style accessor to name; 302 * This is required for framework like Jackson using bean convention for object serialization. 303 * 304 * @return attribute name 305 */ 306 default String getName() { 307 return name(); 308 } 309 } 310 311 /** 312 * Attributes for details about an exception that was raised 313 */ 314 interface ExceptionAttribute extends Attribute { 315 316 /** 317 * The exception object that has been thrown. Note that this can be a complex 318 * object and can cause large content when e.g. serialized as JSON 319 */ 320 ExceptionAttribute EXCEPTION_INSTANCE = new ExceptionErrorAttribute("EXCEPTION_INSTANCE"); 321 322 /** 323 * The exception class 324 */ 325 ExceptionAttribute EXCEPTION_CLASS = new ExceptionErrorAttribute("EXCEPTION_CLASS"); 326 } 327 328 /** 329 * HTTP related error details 330 */ 331 interface HttpAttribute extends Attribute { 332 333 /** 334 * The erroneous HTTP code that occurred 335 */ 336 HttpAttribute HTTP_CODE = new HttpErrorAttribute("HTTP_CODE"); 337 338 /** 339 * HTTP response's body 340 */ 341 HttpAttribute HTTP_TEXT = new HttpErrorAttribute("HTTP_TEXT"); 342 343 /** 344 * If given as details, specifies that a redirect happened and the 345 * content of this detail is the redirect URL 346 */ 347 HttpAttribute HTTP_REDIRECT = new HttpErrorAttribute("HTTP_REDIRECT"); 348 } 349 350 /** 351 * Group related details 352 */ 353 interface GroupAttribute extends Attribute { 354 355 /** 356 * Group name 357 */ 358 GroupAttribute GROUP_NAME = new GroupErrorAttribute("GROUP_NAME"); 359 360 /** 361 * Options for the group 362 */ 363 GroupAttribute GROUP_OPTIONS = new GroupErrorAttribute("GROUP_OPTIONS"); 364 } 365 } 366 367 /** 368 * Custom class for error codes 369 */ 370 static class ErrorCode implements Code { 371 372 private final String name; 373 374 ErrorCode(String name) { 375 if (name == null) { 376 throw new IllegalArgumentException("Name of an error code must not be null"); 377 } 378 this.name = name; 379 } 380 381 @Override 382 public String name() { 383 return name; 384 } 385 386 @Override 387 public boolean equals(Object o) { 388 if (this == o) { 389 return true; 390 } 391 if (!(o instanceof Code)) { 392 return false; 393 } 394 395 Code errorCode = (Code) o; 396 397 return name.equals(errorCode.name()); 398 } 399 400 @Override 401 public int hashCode() { 402 return name.hashCode(); 403 } 404 405 @Override 406 public String toString() { 407 return name(); 408 } 409 } 410 411 static class ErrorAttribute implements Attribute { 412 413 private final String name; 414 415 ErrorAttribute(String name) { 416 if (name == null) { 417 throw new IllegalArgumentException("Name of an error attribute must not be null"); 418 } 419 this.name = name; 420 } 421 422 @Override 423 public String name() { 424 return name; 425 } 426 427 428 @Override 429 public boolean equals(Object o) { 430 if (this == o) { 431 return true; 432 } 433 if (!(o instanceof Attribute)) { 434 return false; 435 } 436 437 Attribute that = (Attribute) o; 438 439 return name.equals(that.name()); 440 } 441 442 @Override 443 public int hashCode() { 444 return name.hashCode(); 445 } 446 447 @Override 448 public String toString() { 449 return name(); 450 } 451 } 452 453 // =========================================================================================================== 454 // Helper classes for implementing the constants in ComponentVerifier: 455 456 static class StandardErrorCode extends ErrorCode implements StandardCode { 457 StandardErrorCode(String name) { 458 super(name); 459 } 460 } 461 462 static class ExceptionErrorAttribute extends ErrorAttribute implements ExceptionAttribute { 463 ExceptionErrorAttribute(String name) { 464 super(name); 465 } 466 } 467 468 static class HttpErrorAttribute extends ErrorAttribute implements HttpAttribute { 469 HttpErrorAttribute(String name) { 470 super(name); 471 } 472 } 473 474 static class GroupErrorAttribute extends ErrorAttribute implements GroupAttribute { 475 GroupErrorAttribute(String name) { 476 super(name); 477 } 478 } 479}