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.component.rest; 018 019import java.util.HashMap; 020import java.util.Map; 021 022import org.apache.camel.Component; 023import org.apache.camel.ComponentVerifier; 024import org.apache.camel.VerifiableComponent; 025import org.apache.camel.impl.verifier.CatalogVerifierCustomizer; 026import org.apache.camel.impl.verifier.DefaultComponentVerifier; 027import org.apache.camel.impl.verifier.ResultBuilder; 028import org.apache.camel.impl.verifier.ResultErrorBuilder; 029import org.apache.camel.runtimecatalog.JSonSchemaHelper; 030import org.apache.camel.runtimecatalog.RuntimeCamelCatalog; 031import org.apache.camel.spi.RestConsumerFactory; 032import org.apache.camel.spi.RestProducerFactory; 033import org.apache.camel.util.ObjectHelper; 034import org.apache.camel.util.function.Suppliers; 035 036public class RestComponentVerifier extends DefaultComponentVerifier { 037 private static final CatalogVerifierCustomizer CUSTOMIZER = new CatalogVerifierCustomizer().excludeUnknown(); 038 private final RestComponent component; 039 040 RestComponentVerifier(RestComponent component) { 041 super("rest", component.getCamelContext()); 042 043 this.component = component; 044 } 045 046 // ********************************* 047 // Parameters validation 048 // ********************************* 049 050 @Override 051 protected Result verifyParameters(Map<String, Object> parameters) { 052 ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS); 053 054 // Validate using the catalog but do not report unknown options as error 055 // as the may be used to customize the underlying component 056 super.verifyParametersAgainstCatalog(builder, parameters, CUSTOMIZER); 057 058 verifyUnderlyingComponent(Scope.PARAMETERS, builder, parameters); 059 060 return builder.build(); 061 } 062 063 // ********************************* 064 // Connectivity validation 065 // ********************************* 066 067 @Override 068 protected Result verifyConnectivity(Map<String, Object> parameters) { 069 ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY); 070 071 verifyUnderlyingComponent(Scope.CONNECTIVITY, builder, parameters); 072 073 return builder.build(); 074 } 075 076 // ********************************* 077 // Helpers 078 // ********************************* 079 080 protected void verifyUnderlyingComponent(Scope scope, ResultBuilder builder, Map<String, Object> parameters) { 081 // componentName is required for validation even at runtime camel might 082 // be able to find a suitable component at runtime. 083 String componentName = (String)parameters.get("componentName"); 084 if (ObjectHelper.isNotEmpty(componentName)) { 085 try { 086 Component component = getTransportComponent(componentName); 087 if (component instanceof VerifiableComponent) { 088 final RuntimeCamelCatalog catalog = getCamelContext().getRuntimeCamelCatalog(); 089 final String json = catalog.componentJSonSchema("rest"); 090 final Map<String, Object> restParameters = new HashMap<>(parameters); 091 092 for (Map<String, String> m : JSonSchemaHelper.parseJsonSchema("componentProperties", json, true)) { 093 String name = m.get("name"); 094 Object val = restParameters.remove(name); 095 if (val != null) { 096 // Add rest prefix to properties belonging to the rest 097 // component so the underlying component know we want 098 // to validate rest-related stuffs. 099 restParameters.put("rest." + name, parameters.get(name)); 100 } 101 } 102 for (Map<String, String> m : JSonSchemaHelper.parseJsonSchema("properties", json, true)) { 103 String name = m.get("name"); 104 Object val = restParameters.remove(name); 105 if (val != null) { 106 // Add rest prefix to properties belonging to the rest 107 // component so the underlying component know we want 108 // to validate rest-related stuffs. 109 restParameters.put("rest." + name, parameters.get(name)); 110 } 111 } 112 113 ComponentVerifier verifier = ((VerifiableComponent)component).getVerifier(); 114 115 // restParameters now should contains rest-component related 116 // properties with "rest." prefix and all the remaining can 117 // be used to customize the underlying component (i.e. http 118 // proxies, auth, etc) 119 Result result = verifier.verify(scope, restParameters); 120 121 // Combine errors and add an information about the component 122 // they comes from 123 for (VerificationError error : result.getErrors()) { 124 builder.error( 125 ResultErrorBuilder.fromError(error) 126 .detail("component", componentName) 127 .build() 128 ); 129 } 130 } else { 131 builder.error( 132 ResultErrorBuilder.withUnsupportedComponent(componentName).build() 133 ); 134 } 135 } catch (Exception e) { 136 builder.error( 137 ResultErrorBuilder.withException(e).build() 138 ); 139 } 140 } else { 141 builder.error(ResultErrorBuilder.withMissingOption("componentName").build()); 142 } 143 } 144 145 private Component getTransportComponent(String componentName) throws Exception { 146 return Suppliers.firstMatching( 147 comp -> comp != null && (comp instanceof RestConsumerFactory || comp instanceof RestProducerFactory), 148 () -> getCamelContext().getRegistry().lookupByNameAndType(componentName, Component.class), 149 () -> getCamelContext().getComponent(componentName, true, false) 150 ).orElse(null); 151 } 152}