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