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.io.IOException; 020import java.util.Collections; 021import java.util.List; 022import java.util.Map; 023import java.util.Map.Entry; 024import java.util.Optional; 025import java.util.Set; 026import java.util.stream.Collectors; 027 028import javax.management.openmbean.CompositeData; 029import javax.management.openmbean.CompositeDataSupport; 030import javax.management.openmbean.CompositeType; 031import javax.management.openmbean.TabularData; 032import javax.management.openmbean.TabularDataSupport; 033 034import org.apache.camel.CatalogCamelContext; 035import org.apache.camel.Component; 036import org.apache.camel.RuntimeCamelException; 037import org.apache.camel.ServiceStatus; 038import org.apache.camel.StatefulService; 039import org.apache.camel.api.management.ManagedInstance; 040import org.apache.camel.api.management.ManagedResource; 041import org.apache.camel.api.management.mbean.CamelOpenMBeanTypes; 042import org.apache.camel.api.management.mbean.ComponentVerifierExtension; 043import org.apache.camel.api.management.mbean.ComponentVerifierExtension.Result; 044import org.apache.camel.api.management.mbean.ComponentVerifierExtension.Result.Status; 045import org.apache.camel.api.management.mbean.ComponentVerifierExtension.Scope; 046import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError; 047import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError.ExceptionAttribute; 048import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError.GroupAttribute; 049import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError.HttpAttribute; 050import org.apache.camel.api.management.mbean.ComponentVerifierExtension.VerificationError.StandardCode; 051import org.apache.camel.api.management.mbean.ManagedComponentMBean; 052import org.apache.camel.spi.ManagementStrategy; 053import org.apache.camel.support.JSonSchemaHelper; 054import org.apache.camel.util.CastUtils; 055 056@ManagedResource(description = "Managed Component") 057public class ManagedComponent implements ManagedInstance, ManagedComponentMBean { 058 private final Component component; 059 private final String name; 060 061 public ManagedComponent(String name, Component component) { 062 this.name = name; 063 this.component = component; 064 } 065 066 public void init(ManagementStrategy strategy) { 067 // do nothing 068 } 069 070 public Component getComponent() { 071 return component; 072 } 073 074 public String getComponentName() { 075 return name; 076 } 077 078 public String getState() { 079 // must use String type to be sure remote JMX can read the attribute without requiring Camel classes. 080 if (component instanceof StatefulService) { 081 ServiceStatus status = ((StatefulService) component).getStatus(); 082 return status.name(); 083 } 084 085 // assume started if not a ServiceSupport instance 086 return ServiceStatus.Started.name(); 087 } 088 089 public String getCamelId() { 090 return component.getCamelContext().getName(); 091 } 092 093 public String getCamelManagementName() { 094 return component.getCamelContext().getManagementName(); 095 } 096 097 public Object getInstance() { 098 return component; 099 } 100 101 public String informationJson() { 102 try { 103 // a component may have been given a different name, so resolve its default name by its java type 104 // as we can find the component json information from the default component name 105 String defaultName = component.getCamelContext().adapt(CatalogCamelContext.class).resolveComponentDefaultName(component.getClass().getName()); 106 String target = defaultName != null ? defaultName : name; 107 return component.getCamelContext().adapt(CatalogCamelContext.class).getComponentParameterJsonSchema(target); 108 } catch (IOException e) { 109 throw RuntimeCamelException.wrapRuntimeCamelException(e); 110 } 111 } 112 113 public TabularData explain(boolean allOptions) { 114 try { 115 // a component may have been given a different name, so resolve its default name by its java type 116 // as we can find the component json information from the default component name 117 String defaultName = component.getCamelContext().adapt(CatalogCamelContext.class).resolveComponentDefaultName(component.getClass().getName()); 118 String target = defaultName != null ? defaultName : name; 119 String json = component.getCamelContext().adapt(CatalogCamelContext.class).explainComponentJson(target, allOptions); 120 121 List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("componentProperties", json, true); 122 123 TabularData answer = new TabularDataSupport(CamelOpenMBeanTypes.explainComponentTabularType()); 124 125 for (Map<String, String> row : rows) { 126 String name = row.get("name"); 127 String kind = row.get("kind"); 128 String group = row.get("group") != null ? row.get("group") : ""; 129 String label = row.get("label") != null ? row.get("label") : ""; 130 String type = row.get("type"); 131 String javaType = row.get("javaType"); 132 String deprecated = row.get("deprecated") != null ? row.get("deprecated") : ""; 133 String secret = row.get("secret") != null ? row.get("secret") : ""; 134 String value = row.get("value") != null ? row.get("value") : ""; 135 String defaultValue = row.get("defaultValue") != null ? row.get("defaultValue") : ""; 136 String description = row.get("description") != null ? row.get("description") : ""; 137 138 CompositeType ct = CamelOpenMBeanTypes.explainComponentCompositeType(); 139 CompositeData data = new CompositeDataSupport(ct, 140 new String[]{"option", "kind", "group", "label", "type", "java type", "deprecated", "secret", "value", "default value", "description"}, 141 new Object[]{name, kind, group, label, type, javaType, deprecated, secret, value, defaultValue, description}); 142 answer.put(data); 143 } 144 145 return answer; 146 } catch (Exception e) { 147 throw RuntimeCamelException.wrapRuntimeCamelException(e); 148 } 149 } 150 151 @Override 152 public boolean isVerifySupported() { 153 return component.getExtension(org.apache.camel.component.extension.ComponentVerifierExtension.class).isPresent(); 154 } 155 156 @Override 157 public ComponentVerifierExtension.Result verify(String scope, Map<String, String> options) { 158 try { 159 org.apache.camel.component.extension.ComponentVerifierExtension.Scope scopeEnum = org.apache.camel.component.extension.ComponentVerifierExtension.Scope.fromString(scope); 160 Optional<org.apache.camel.component.extension.ComponentVerifierExtension> verifier = component.getExtension(org.apache.camel.component.extension.ComponentVerifierExtension.class); 161 if (verifier.isPresent()) { 162 org.apache.camel.component.extension.ComponentVerifierExtension.Result result = verifier.get().verify(scopeEnum, CastUtils.cast(options)); 163 String rstatus = result.getStatus().toString(); 164 String rscope = result.getScope().toString(); 165 return new ResultImpl(Scope.valueOf(rscope), Status.valueOf(rstatus), 166 result.getErrors().stream().map(this::translate).collect(Collectors.toList())); 167 168 } else { 169 return new ResultImpl(Scope.PARAMETERS, Status.UNSUPPORTED, Collections.emptyList()); 170 } 171 } catch (IllegalArgumentException e) { 172 return new ResultImpl(Scope.PARAMETERS, Status.UNSUPPORTED, Collections.singletonList( 173 new VerificationErrorImpl(StandardCode.UNSUPPORTED_SCOPE, "Unsupported scope: " + scope))); 174 } 175 } 176 177 private VerificationError translate(org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError error) { 178 return new VerificationErrorImpl(translate(error.getCode()), error.getDescription(), 179 error.getParameterKeys(), translate(error.getDetails())); 180 } 181 182 private Map<VerificationError.Attribute, Object> translate(Map<org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.Attribute, Object> details) { 183 return details.entrySet().stream().collect(Collectors.toMap(e -> translate(e.getKey()), Entry::getValue)); 184 } 185 186 private VerificationError.Attribute translate(org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.Attribute attribute) { 187 if (attribute == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.GroupAttribute.GROUP_NAME) { 188 return GroupAttribute.GROUP_NAME; 189 } else if (attribute == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.GroupAttribute.GROUP_OPTIONS) { 190 return GroupAttribute.GROUP_OPTIONS; 191 } else if (attribute == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_CODE) { 192 return HttpAttribute.HTTP_CODE; 193 } else if (attribute == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_REDIRECT) { 194 return HttpAttribute.HTTP_REDIRECT; 195 } else if (attribute == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.HttpAttribute.HTTP_TEXT) { 196 return HttpAttribute.HTTP_TEXT; 197 } else if (attribute == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_CLASS) { 198 return ExceptionAttribute.EXCEPTION_CLASS; 199 } else if (attribute == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) { 200 return ExceptionAttribute.EXCEPTION_INSTANCE; 201 } else if (attribute != null) { 202 return VerificationError.asAttribute(attribute.getName()); 203 } else { 204 return null; 205 } 206 } 207 208 private VerificationError.Code translate(org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.Code code) { 209 if (code == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.AUTHENTICATION) { 210 return StandardCode.AUTHENTICATION; 211 } else if (code == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.EXCEPTION) { 212 return StandardCode.EXCEPTION; 213 } else if (code == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.INTERNAL) { 214 return StandardCode.INTERNAL; 215 } else if (code == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.MISSING_PARAMETER) { 216 return StandardCode.MISSING_PARAMETER; 217 } else if (code == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.UNKNOWN_PARAMETER) { 218 return StandardCode.UNKNOWN_PARAMETER; 219 } else if (code == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.ILLEGAL_PARAMETER) { 220 return StandardCode.ILLEGAL_PARAMETER; 221 } else if (code == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.ILLEGAL_PARAMETER_GROUP_COMBINATION) { 222 return StandardCode.ILLEGAL_PARAMETER_GROUP_COMBINATION; 223 } else if (code == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.ILLEGAL_PARAMETER_VALUE) { 224 return StandardCode.ILLEGAL_PARAMETER_VALUE; 225 } else if (code == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP) { 226 return StandardCode.ILLEGAL_PARAMETER_GROUP_COMBINATION; 227 } else if (code == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.UNSUPPORTED) { 228 return StandardCode.UNSUPPORTED; 229 } else if (code == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.UNSUPPORTED_SCOPE) { 230 return StandardCode.UNSUPPORTED_SCOPE; 231 } else if (code == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.UNSUPPORTED_COMPONENT) { 232 return StandardCode.UNSUPPORTED_COMPONENT; 233 } else if (code == org.apache.camel.component.extension.ComponentVerifierExtension.VerificationError.StandardCode.GENERIC) { 234 return StandardCode.GENERIC; 235 } else if (code != null) { 236 return VerificationError.asCode(code.getName()); 237 } else { 238 return null; 239 } 240 } 241 242 public static class VerificationErrorImpl implements VerificationError { 243 private final Code code; 244 private final String description; 245 private final Set<String> parameterKeys; 246 private final Map<Attribute, Object> details; 247 248 public VerificationErrorImpl(Code code, String description) { 249 this.code = code; 250 this.description = description; 251 this.parameterKeys = Collections.emptySet(); 252 this.details = Collections.emptyMap(); 253 } 254 255 public VerificationErrorImpl(Code code, String description, Set<String> parameterKeys, Map<Attribute, Object> details) { 256 this.code = code; 257 this.description = description; 258 this.parameterKeys = parameterKeys; 259 this.details = details; 260 } 261 262 @Override 263 public Code getCode() { 264 return code; 265 } 266 267 @Override 268 public String getDescription() { 269 return description; 270 } 271 272 @Override 273 public Set<String> getParameterKeys() { 274 return parameterKeys; 275 } 276 277 @Override 278 public Map<Attribute, Object> getDetails() { 279 return details; 280 } 281 } 282 283 public static class ResultImpl implements Result { 284 private final Scope scope; 285 private final Status status; 286 private final List<VerificationError> errors; 287 288 public ResultImpl(Scope scope, Status status, List<VerificationError> errors) { 289 this.scope = scope; 290 this.status = status; 291 this.errors = errors; 292 } 293 294 @Override 295 public Scope getScope() { 296 return scope; 297 } 298 299 @Override 300 public Status getStatus() { 301 return status; 302 } 303 304 @Override 305 public List<VerificationError> getErrors() { 306 return errors; 307 } 308 } 309}