/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.camel.blueprint.handler;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;

import javax.xml.bind.Binder;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.apache.aries.blueprint.BeanProcessor;
import org.apache.aries.blueprint.ComponentDefinitionRegistry;
import org.apache.aries.blueprint.ComponentDefinitionRegistryProcessor;
import org.apache.aries.blueprint.NamespaceHandler;
import org.apache.aries.blueprint.ParserContext;
import org.apache.aries.blueprint.PassThroughMetadata;
import org.apache.aries.blueprint.mutable.MutableBeanMetadata;
import org.apache.aries.blueprint.mutable.MutablePassThroughMetadata;
import org.apache.aries.blueprint.mutable.MutableRefMetadata;
import org.apache.aries.blueprint.mutable.MutableReferenceMetadata;
import org.apache.camel.BeanInject;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.EndpointInject;
import org.apache.camel.Produce;
import org.apache.camel.PropertyInject;
import org.apache.camel.blueprint.BlueprintCamelContext;
import org.apache.camel.blueprint.BlueprintCamelStateService;
import org.apache.camel.blueprint.BlueprintModelJAXBContextFactory;
import org.apache.camel.blueprint.CamelContextFactoryBean;
import org.apache.camel.blueprint.CamelEndpointFactoryBean;
import org.apache.camel.blueprint.CamelRestContextFactoryBean;
import org.apache.camel.blueprint.CamelRouteContextFactoryBean;
import org.apache.camel.blueprint.CamelRouteTemplateContextFactoryBean;
import org.apache.camel.core.xml.AbstractCamelFactoryBean;
import org.apache.camel.impl.engine.CamelPostProcessorHelper;
import org.apache.camel.impl.engine.DefaultCamelContextNameStrategy;
import org.apache.camel.model.AggregateDefinition;
import org.apache.camel.model.CatchDefinition;
import org.apache.camel.model.DataFormatDefinition;
import org.apache.camel.model.ExpressionNode;
import org.apache.camel.model.ExpressionSubElementDefinition;
import org.apache.camel.model.FromDefinition;
import org.apache.camel.model.MarshalDefinition;
import org.apache.camel.model.Model;
import org.apache.camel.model.OnExceptionDefinition;
import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.model.ResequenceDefinition;
import org.apache.camel.model.RouteDefinition;
import org.apache.camel.model.SendDefinition;
import org.apache.camel.model.SortDefinition;
import org.apache.camel.model.ToDefinition;
import org.apache.camel.model.ToDynamicDefinition;
import org.apache.camel.model.UnmarshalDefinition;
import org.apache.camel.model.WireTapDefinition;
import org.apache.camel.model.language.ExpressionDefinition;
import org.apache.camel.model.rest.RestBindingMode;
import org.apache.camel.model.rest.RestDefinition;
import org.apache.camel.model.rest.VerbDefinition;
import org.apache.camel.spi.CamelContextNameStrategy;
import org.apache.camel.spi.ComponentResolver;
import org.apache.camel.spi.DataFormatResolver;
import org.apache.camel.spi.LanguageResolver;
import org.apache.camel.spi.NamespaceAware;
import org.apache.camel.spi.PropertiesComponent;
import org.apache.camel.support.ObjectHelper;
import org.apache.camel.support.builder.Namespaces;
import org.apache.camel.support.builder.xml.NamespacesHelper;
import org.apache.camel.support.jsse.KeyStoreParameters;
import org.apache.camel.support.jsse.SSLContextParameters;
import org.apache.camel.support.jsse.SecureRandomParameters;
import org.apache.camel.util.StringHelper;
import org.apache.camel.util.URISupport;
import org.apache.camel.util.blueprint.KeyStoreParametersFactoryBean;
import org.apache.camel.util.blueprint.SSLContextParametersFactoryBean;
import org.apache.camel.util.blueprint.SecureRandomParametersFactoryBean;
import org.osgi.framework.Bundle;
import org.osgi.service.blueprint.container.BlueprintContainer;
import org.osgi.service.blueprint.container.ComponentDefinitionException;
import org.osgi.service.blueprint.reflect.BeanMetadata;
import org.osgi.service.blueprint.reflect.ComponentMetadata;
import org.osgi.service.blueprint.reflect.Metadata;
import org.osgi.service.blueprint.reflect.RefMetadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import static org.osgi.service.blueprint.reflect.ComponentMetadata.ACTIVATION_LAZY;
import static org.osgi.service.blueprint.reflect.ServiceReferenceMetadata.AVAILABILITY_MANDATORY;
import static org.osgi.service.blueprint.reflect.ServiceReferenceMetadata.AVAILABILITY_OPTIONAL;

/**
 * Camel {@link NamespaceHandler} to parse the Camel related namespaces.
 */
public class CamelNamespaceHandler implements NamespaceHandler {

    public static final String BLUEPRINT_NS = "http://camel.apache.org/schema/blueprint";
    public static final String SPRING_NS = "http://camel.apache.org/schema/spring";

    private static final String CAMEL_CONTEXT = "camelContext";
    private static final String ROUTE_CONTEXT = "routeContext";
    private static final String ROUTE_TEMPLATE_CONTEXT = "routeTemplateContext";
    private static final String REST_CONTEXT = "restContext";
    private static final String ENDPOINT = "endpoint";
    private static final String KEY_STORE_PARAMETERS = "keyStoreParameters";
    private static final String SECURE_RANDOM_PARAMETERS = "secureRandomParameters";
    private static final String SSL_CONTEXT_PARAMETERS = "sslContextParameters";

    private static final Logger LOG = LoggerFactory.getLogger(CamelNamespaceHandler.class);

    private JAXBContext jaxbContext;

    /**
     * Prepares the nodes before parsing.
     */
    public static void doBeforeParse(Node node, String fromNamespace, String toNamespace) {
        if (node.getNodeType() == Node.ELEMENT_NODE) {
            Document doc = node.getOwnerDocument();
            if (node.getNamespaceURI().equals(fromNamespace)) {
                doc.renameNode(node, toNamespace, node.getLocalName());
            }

            // remove whitespace noise from uri, xxxUri attributes, eg new lines, and tabs etc, which allows end users to format
            // their Camel routes in more human readable format, but at runtime those attributes must be trimmed
            // the parser removes most of the noise, but keeps double spaces in the attribute values
            NamedNodeMap map = node.getAttributes();
            for (int i = 0; i < map.getLength(); i++) {
                Node att = map.item(i);
                if (att.getNodeName().equals("uri") || att.getNodeName().endsWith("Uri")) {
                    final String value = att.getNodeValue();
                    String before = StringHelper.before(value, "?");
                    String after = StringHelper.after(value, "?");

                    if (before != null && after != null) {
                        // remove all double spaces in the uri parameters
                        String changed = after.replaceAll("\\s{2,}", "");
                        if (!after.equals(changed)) {
                            String newAtr = before.trim() + "?" + changed.trim();
                            LOG.debug("Removed whitespace noise from attribute {} -> {}", value, newAtr);
                            att.setNodeValue(newAtr);
                        }
                    }
                }
            }
        }
        NodeList list = node.getChildNodes();
        for (int i = 0; i < list.getLength(); ++i) {
            doBeforeParse(list.item(i), fromNamespace, toNamespace);
        }
    }

    @Override
    public URL getSchemaLocation(String namespace) {
        if (BLUEPRINT_NS.equals(namespace)) {
            return getClass().getClassLoader().getResource("camel-blueprint.xsd");
        }
        return null;
    }

    @Override
    @SuppressWarnings({"rawtypes"})
    public Set<Class> getManagedClasses() {
        return new HashSet<>(Arrays.asList(BlueprintCamelContext.class));
    }

    @Override
    public Metadata parse(Element element, ParserContext context) {
        LOG.trace("Parsing element {}", element);

        try {
            // as the camel-core model namespace is Spring we need to rename from blueprint to spring
            doBeforeParse(element, BLUEPRINT_NS, SPRING_NS);

            if (element.getLocalName().equals(CAMEL_CONTEXT)) {
                return parseCamelContextNode(element, context);
            }
            if (element.getLocalName().equals(ROUTE_CONTEXT)) {
                return parseRouteContextNode(element, context);
            }
            if (element.getLocalName().equals(ROUTE_TEMPLATE_CONTEXT)) {
                return parseRouteTemplateContextNode(element, context);
            }
            if (element.getLocalName().equals(REST_CONTEXT)) {
                return parseRestContextNode(element, context);
            }
            if (element.getLocalName().equals(ENDPOINT)) {
                return parseEndpointNode(element, context);
            }
            if (element.getLocalName().equals(KEY_STORE_PARAMETERS)) {
                return parseKeyStoreParametersNode(element, context);
            }
            if (element.getLocalName().equals(SECURE_RANDOM_PARAMETERS)) {
                return parseSecureRandomParametersNode(element, context);
            }
            if (element.getLocalName().equals(SSL_CONTEXT_PARAMETERS)) {
                return parseSSLContextParametersNode(element, context);
            }
        } finally {
            // make sure to rename back so we leave the DOM as-is
            doBeforeParse(element, SPRING_NS, BLUEPRINT_NS);
        }

        return null;
    }

    private Metadata parseCamelContextNode(Element element, ParserContext context) {
        LOG.trace("Parsing CamelContext {}", element);
        // Find the id, generate one if needed
        String contextId = element.getAttribute("id");
        boolean implicitId = false;

        // let's avoid folks having to explicitly give an ID to a camel context
        if (org.apache.camel.util.ObjectHelper.isEmpty(contextId)) {
            // if no explicit id was set then use a default auto generated name
            CamelContextNameStrategy strategy = new DefaultCamelContextNameStrategy();
            contextId = strategy.getName();
            element.setAttributeNS(null, "id", contextId);
            implicitId = true;
        }

        // now let's parse the routes with JAXB
        Binder<Node> binder;
        try {
            binder = getJaxbContext().createBinder();
        } catch (JAXBException e) {
            throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e);
        }
        Object value = parseUsingJaxb(element, context, binder);
        if (!(value instanceof CamelContextFactoryBean)) {
            throw new ComponentDefinitionException("Expected an instance of " + CamelContextFactoryBean.class);
        }

        CamelContextFactoryBean ccfb = (CamelContextFactoryBean) value;
        ccfb.setImplicitId(implicitId);

        MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class);
        factory.setId(".camelBlueprint.passThrough." + contextId);
        factory.setObject(new PassThroughCallable<>(value));

        MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class);
        factory2.setId(".camelBlueprint.factory." + contextId);
        factory2.setFactoryComponent(factory);
        factory2.setFactoryMethod("call");
        factory2.setInitMethod("afterPropertiesSet");
        factory2.setDestroyMethod("destroy");
        factory2.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
        factory2.addProperty("bundleContext", createRef(context, "blueprintBundleContext"));
        // We need to add other components which the camel context dependsOn
        if (org.apache.camel.util.ObjectHelper.isNotEmpty(ccfb.getDependsOn())) {
            factory2.setDependsOn(Arrays.asList(ccfb.getDependsOn().split(" |,")));
        }
        context.getComponentDefinitionRegistry().registerComponentDefinition(factory2);

        MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class);
        ctx.setId(contextId);
        ctx.setRuntimeClass(BlueprintCamelContext.class);
        ctx.setFactoryComponent(factory2);
        ctx.setFactoryMethod("getContext");
        ctx.addProperty("bundleStateService", createRef(context, ".camelBlueprint.bundleStateService"));
        ctx.setInitMethod("build");
        ctx.setDestroyMethod("destroy");

        // Register factory beans
        registerBeans(context, contextId, ccfb.getThreadPools());
        registerBeans(context, contextId, ccfb.getEndpoints());
        registerBeans(context, contextId, ccfb.getRedeliveryPolicies());
        registerBeans(context, contextId, ccfb.getBeansFactory());

        // Register single CamelBundleStateService - shared for all bundles and all Blueprint Camel contexts
        registerBundleStateService(context);

        // Register processors
        MutablePassThroughMetadata beanProcessorFactory = context.createMetadata(MutablePassThroughMetadata.class);
        beanProcessorFactory.setId(".camelBlueprint.processor.bean.passThrough." + contextId);
        beanProcessorFactory.setObject(new PassThroughCallable<Object>(new CamelInjector(contextId)));

        MutableBeanMetadata beanProcessor = context.createMetadata(MutableBeanMetadata.class);
        beanProcessor.setId(".camelBlueprint.processor.bean." + contextId);
        beanProcessor.setRuntimeClass(CamelInjector.class);
        beanProcessor.setFactoryComponent(beanProcessorFactory);
        beanProcessor.setFactoryMethod("call");
        beanProcessor.setProcessor(true);
        beanProcessor.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
        context.getComponentDefinitionRegistry().registerComponentDefinition(beanProcessor);

        MutablePassThroughMetadata regProcessorFactory = context.createMetadata(MutablePassThroughMetadata.class);
        regProcessorFactory.setId(".camelBlueprint.processor.registry.passThrough." + contextId);
        regProcessorFactory.setObject(new PassThroughCallable<Object>(new CamelDependenciesFinder(contextId, context)));

        MutableBeanMetadata regProcessor = context.createMetadata(MutableBeanMetadata.class);
        regProcessor.setId(".camelBlueprint.processor.registry." + contextId);
        regProcessor.setRuntimeClass(CamelDependenciesFinder.class);
        regProcessor.setFactoryComponent(regProcessorFactory);
        regProcessor.setFactoryMethod("call");
        regProcessor.setProcessor(true);
        regProcessor.addDependsOn(".camelBlueprint.processor.bean." + contextId);
        regProcessor.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
        context.getComponentDefinitionRegistry().registerComponentDefinition(regProcessor);

        // lets inject the namespaces into any namespace aware POJOs
        injectNamespaces(element, binder);

        LOG.trace("Parsing CamelContext done, returning {}", ctx);
        return ctx;
    }

    protected void injectNamespaces(Element element, Binder<Node> binder) {
        NodeList list = element.getChildNodes();
        Namespaces namespaces = null;
        int size = list.getLength();
        for (int i = 0; i < size; i++) {
            Node child = list.item(i);
            if (child instanceof Element) {
                Element childElement = (Element) child;
                Object object = binder.getJAXBNode(child);
                if (object instanceof NamespaceAware) {
                    NamespaceAware namespaceAware = (NamespaceAware) object;
                    if (namespaces == null) {
                        namespaces = NamespacesHelper.namespaces(element);
                    }
                    namespaces.configure(namespaceAware);
                }
                injectNamespaces(childElement, binder);
            }
        }
    }

    private Metadata parseRouteContextNode(Element element, ParserContext context) {
        LOG.trace("Parsing RouteContext {}", element);
        // now parse the routes with JAXB
        Binder<Node> binder;
        try {
            binder = getJaxbContext().createBinder();
        } catch (JAXBException e) {

            throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e);
        }
        Object value = parseUsingJaxb(element, context, binder);
        if (!(value instanceof CamelRouteContextFactoryBean)) {
            throw new ComponentDefinitionException("Expected an instance of " + CamelRouteContextFactoryBean.class);
        }

        CamelRouteContextFactoryBean rcfb = (CamelRouteContextFactoryBean) value;
        String id = rcfb.getId();

        MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class);
        factory.setId(".camelBlueprint.passThrough." + id);
        factory.setObject(new PassThroughCallable<Object>(rcfb));

        MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class);
        factory2.setId(".camelBlueprint.factory." + id);
        factory2.setFactoryComponent(factory);
        factory2.setFactoryMethod("call");

        MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class);
        ctx.setId(id);
        ctx.setRuntimeClass(List.class);
        ctx.setFactoryComponent(factory2);
        ctx.setFactoryMethod("getRoutes");
        // must be lazy as we want CamelContext to be activated first
        ctx.setActivation(ACTIVATION_LAZY);

        // lets inject the namespaces into any namespace aware POJOs
        injectNamespaces(element, binder);

        LOG.trace("Parsing RouteContext {} done, returning {}", element, ctx);
        return ctx;
    }

    private Metadata parseRouteTemplateContextNode(Element element, ParserContext context) {
        LOG.trace("Parsing RouteTemplateContext {}", element);
        // now parse the routes with JAXB
        Binder<Node> binder;
        try {
            binder = getJaxbContext().createBinder();
        } catch (JAXBException e) {

            throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e);
        }
        Object value = parseUsingJaxb(element, context, binder);
        if (!(value instanceof CamelRouteTemplateContextFactoryBean)) {
            throw new ComponentDefinitionException("Expected an instance of " + CamelRouteTemplateContextFactoryBean.class);
        }

        CamelRouteTemplateContextFactoryBean rcfb = (CamelRouteTemplateContextFactoryBean) value;
        String id = rcfb.getId();

        MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class);
        factory.setId(".camelBlueprint.passThrough." + id);
        factory.setObject(new PassThroughCallable<Object>(rcfb));

        MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class);
        factory2.setId(".camelBlueprint.factory." + id);
        factory2.setFactoryComponent(factory);
        factory2.setFactoryMethod("call");

        MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class);
        ctx.setId(id);
        ctx.setRuntimeClass(List.class);
        ctx.setFactoryComponent(factory2);
        ctx.setFactoryMethod("getRouteTemplates");
        // must be lazy as we want CamelContext to be activated first
        ctx.setActivation(ACTIVATION_LAZY);

        // lets inject the namespaces into any namespace aware POJOs
        injectNamespaces(element, binder);

        LOG.trace("Parsing RouteTemplateContext {} done, returning {}", element, ctx);
        return ctx;
    }

    private Metadata parseRestContextNode(Element element, ParserContext context) {
        LOG.trace("Parsing RestContext {}", element);
        // now parse the rests with JAXB
        Binder<Node> binder;
        try {
            binder = getJaxbContext().createBinder();
        } catch (JAXBException e) {
            throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e);
        }
        Object value = parseUsingJaxb(element, context, binder);
        if (!(value instanceof CamelRestContextFactoryBean)) {
            throw new ComponentDefinitionException("Expected an instance of " + CamelRestContextFactoryBean.class);
        }

        CamelRestContextFactoryBean rcfb = (CamelRestContextFactoryBean) value;
        String id = rcfb.getId();

        MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class);
        factory.setId(".camelBlueprint.passThrough." + id);
        factory.setObject(new PassThroughCallable<Object>(rcfb));

        MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class);
        factory2.setId(".camelBlueprint.factory." + id);
        factory2.setFactoryComponent(factory);
        factory2.setFactoryMethod("call");

        MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class);
        ctx.setId(id);
        ctx.setRuntimeClass(List.class);
        ctx.setFactoryComponent(factory2);
        ctx.setFactoryMethod("getRests");
        // must be lazy as we want CamelContext to be activated first
        ctx.setActivation(ACTIVATION_LAZY);

        // lets inject the namespaces into any namespace aware POJOs
        injectNamespaces(element, binder);

        LOG.trace("Parsing RestContext {} done, returning {}", element, ctx);
        return ctx;
    }

    private Metadata parseEndpointNode(Element element, ParserContext context) {
        LOG.trace("Parsing Endpoint {}", element);
        // now parse the rests with JAXB
        Binder<Node> binder;
        try {
            binder = getJaxbContext().createBinder();
        } catch (JAXBException e) {
            throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e);
        }
        Object value = parseUsingJaxb(element, context, binder);
        if (!(value instanceof CamelEndpointFactoryBean)) {
            throw new ComponentDefinitionException("Expected an instance of " + CamelEndpointFactoryBean.class);
        }

        CamelEndpointFactoryBean rcfb = (CamelEndpointFactoryBean) value;
        String id = rcfb.getId();

        MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class);
        factory.setId(".camelBlueprint.passThrough." + id);
        factory.setObject(new PassThroughCallable<Object>(rcfb));

        MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class);
        factory2.setId(".camelBlueprint.factory." + id);
        factory2.setFactoryComponent(factory);
        factory2.setFactoryMethod("call");
        factory2.setInitMethod("afterPropertiesSet");
        factory2.setDestroyMethod("destroy");
        factory2.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));

        MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class);
        ctx.setId(id);
        ctx.setRuntimeClass(Endpoint.class);
        ctx.setFactoryComponent(factory2);
        ctx.setFactoryMethod("getObject");
        // must be lazy as we want CamelContext to be activated first
        ctx.setActivation(ACTIVATION_LAZY);

        LOG.trace("Parsing endpoint {} done, returning {}", element, ctx);
        return ctx;
    }

    private Metadata parseKeyStoreParametersNode(Element element, ParserContext context) {
        LOG.trace("Parsing KeyStoreParameters {}", element);
        // now parse the key store parameters with JAXB
        Binder<Node> binder;
        try {
            binder = getJaxbContext().createBinder();
        } catch (JAXBException e) {
            throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e);
        }
        Object value = parseUsingJaxb(element, context, binder);
        if (!(value instanceof KeyStoreParametersFactoryBean)) {
            throw new ComponentDefinitionException("Expected an instance of " + KeyStoreParametersFactoryBean.class);
        }

        KeyStoreParametersFactoryBean kspfb = (KeyStoreParametersFactoryBean) value;
        String id = kspfb.getId();

        MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class);
        factory.setId(".camelBlueprint.passThrough." + id);
        factory.setObject(new PassThroughCallable<Object>(kspfb));

        MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class);
        factory2.setId(".camelBlueprint.factory." + id);
        factory2.setFactoryComponent(factory);
        factory2.setFactoryMethod("call");
        factory2.setInitMethod("afterPropertiesSet");
        factory2.setDestroyMethod("destroy");
        factory2.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));

        MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class);
        ctx.setId(id);
        ctx.setRuntimeClass(KeyStoreParameters.class);
        ctx.setFactoryComponent(factory2);
        ctx.setFactoryMethod("getObject");
        // must be lazy as we want CamelContext to be activated first
        ctx.setActivation(ACTIVATION_LAZY);

        LOG.trace("Parsing KeyStoreParameters done, returning {}", ctx);
        return ctx;
    }

    private Metadata parseSecureRandomParametersNode(Element element, ParserContext context) {
        LOG.trace("Parsing SecureRandomParameters {}", element);
        // now parse the key store parameters with JAXB
        Binder<Node> binder;
        try {
            binder = getJaxbContext().createBinder();
        } catch (JAXBException e) {
            throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e);
        }
        Object value = parseUsingJaxb(element, context, binder);
        if (!(value instanceof SecureRandomParametersFactoryBean)) {
            throw new ComponentDefinitionException("Expected an instance of " + SecureRandomParametersFactoryBean.class);
        }

        SecureRandomParametersFactoryBean srfb = (SecureRandomParametersFactoryBean) value;
        String id = srfb.getId();

        MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class);
        factory.setId(".camelBlueprint.passThrough." + id);
        factory.setObject(new PassThroughCallable<Object>(srfb));

        MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class);
        factory2.setId(".camelBlueprint.factory." + id);
        factory2.setFactoryComponent(factory);
        factory2.setFactoryMethod("call");
        factory2.setInitMethod("afterPropertiesSet");
        factory2.setDestroyMethod("destroy");
        factory2.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));

        MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class);
        ctx.setId(id);
        ctx.setRuntimeClass(SecureRandomParameters.class);
        ctx.setFactoryComponent(factory2);
        ctx.setFactoryMethod("getObject");
        // must be lazy as we want CamelContext to be activated first
        ctx.setActivation(ACTIVATION_LAZY);

        LOG.trace("Parsing SecureRandomParameters done, returning {}", ctx);
        return ctx;
    }

    private Metadata parseSSLContextParametersNode(Element element, ParserContext context) {
        LOG.trace("Parsing SSLContextParameters {}", element);
        // now parse the key store parameters with JAXB
        Binder<Node> binder;
        try {
            binder = getJaxbContext().createBinder();
        } catch (JAXBException e) {
            throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e);
        }
        Object value = parseUsingJaxb(element, context, binder);
        if (!(value instanceof SSLContextParametersFactoryBean)) {
            throw new ComponentDefinitionException("Expected an instance of " + SSLContextParametersFactoryBean.class);
        }

        SSLContextParametersFactoryBean scpfb = (SSLContextParametersFactoryBean) value;
        String id = scpfb.getId();

        MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class);
        factory.setId(".camelBlueprint.passThrough." + id);
        factory.setObject(new PassThroughCallable<Object>(scpfb));

        MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class);
        factory2.setId(".camelBlueprint.factory." + id);
        factory2.setFactoryComponent(factory);
        factory2.setFactoryMethod("call");
        factory2.setInitMethod("afterPropertiesSet");
        factory2.setDestroyMethod("destroy");
        factory2.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));

        MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class);
        ctx.setId(id);
        ctx.setRuntimeClass(SSLContextParameters.class);
        ctx.setFactoryComponent(factory2);
        ctx.setFactoryMethod("getObject");
        // must be lazy as we want CamelContext to be activated first
        ctx.setActivation(ACTIVATION_LAZY);

        LOG.trace("Parsing SSLContextParameters done, returning {}", ctx);
        return ctx;
    }

    private void registerBeans(ParserContext context, String contextId, List<?> beans) {
        if (beans != null) {
            for (Object bean : beans) {
                if (bean instanceof AbstractCamelFactoryBean) {
                    registerBean(context, contextId, (AbstractCamelFactoryBean<?>) bean);
                }
            }
        }
    }

    protected void registerBean(ParserContext context, String contextId, AbstractCamelFactoryBean<?> fact) {
        String id = fact.getId();

        fact.setCamelContextId(contextId);

        MutablePassThroughMetadata eff = context.createMetadata(MutablePassThroughMetadata.class);
        eff.setId(".camelBlueprint.bean.passthrough." + id);
        eff.setObject(new PassThroughCallable<Object>(fact));

        MutableBeanMetadata ef = context.createMetadata(MutableBeanMetadata.class);
        ef.setId(".camelBlueprint.bean.factory." + id);
        ef.setFactoryComponent(eff);
        ef.setFactoryMethod("call");
        ef.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
        ef.setInitMethod("afterPropertiesSet");
        ef.setDestroyMethod("destroy");

        MutableBeanMetadata e = context.createMetadata(MutableBeanMetadata.class);
        e.setId(id);
        e.setRuntimeClass(fact.getObjectType());
        e.setFactoryComponent(ef);
        e.setFactoryMethod("getObject");
        e.addDependsOn(".camelBlueprint.processor.bean." + contextId);

        context.getComponentDefinitionRegistry().registerComponentDefinition(e);
    }

    /**
     * There's single instance of {@link BlueprintCamelStateService} that's used by all Blueprint Camel contexts
     * to inform about state of Camel contexts. If Karaf is available, this information will propagate to
     * <em>extended bundle info</em>.
     * See CAMEL-12980
     */
    private void registerBundleStateService(ParserContext context) {
        ComponentDefinitionRegistry componentDefinitionRegistry = context.getComponentDefinitionRegistry();
        ComponentMetadata cm = componentDefinitionRegistry.getComponentDefinition(".camelBlueprint.bundleStateService");
        if (cm == null) {
            MutableBeanMetadata ssm = context.createMetadata(MutableBeanMetadata.class);
            ssm.setId(".camelBlueprint.bundleStateService");
            ssm.setRuntimeClass(BlueprintCamelStateService.class);
            ssm.addProperty("bundleContext", createRef(context, "blueprintBundleContext"));
            ssm.setInitMethod("init");
            ssm.setDestroyMethod("destroy");
            componentDefinitionRegistry.registerComponentDefinition(ssm);
        }
    }

    protected BlueprintContainer getBlueprintContainer(ParserContext context) {
        PassThroughMetadata ptm = (PassThroughMetadata) context.getComponentDefinitionRegistry().getComponentDefinition("blueprintContainer");
        return (BlueprintContainer) ptm.getObject();
    }

    @Override
    public ComponentMetadata decorate(Node node, ComponentMetadata component, ParserContext context) {
        return null;
    }

    protected Object parseUsingJaxb(Element element, ParserContext parserContext, Binder<Node> binder) {
        try {
            return binder.unmarshal(element);
        } catch (JAXBException e) {
            throw new ComponentDefinitionException("Failed to parse JAXB element: " + e, e);
        }
    }

    public JAXBContext getJaxbContext() throws JAXBException {
        if (jaxbContext == null) {
            jaxbContext = new BlueprintModelJAXBContextFactory(getClass().getClassLoader()).newJAXBContext();
        }
        return jaxbContext;
    }

    private RefMetadata createRef(ParserContext context, String value) {
        MutableRefMetadata r = context.createMetadata(MutableRefMetadata.class);
        r.setComponentId(value);
        return r;
    }

    private static ComponentMetadata getDataformatResolverReference(ParserContext context, String dataformat) {
        // we cannot resolve dataformat names using property placeholders at this point in time
        if (dataformat.startsWith(PropertiesComponent.PREFIX_TOKEN)) {
            return null;
        }
        ComponentDefinitionRegistry componentDefinitionRegistry = context.getComponentDefinitionRegistry();
        ComponentMetadata cm = componentDefinitionRegistry.getComponentDefinition(".camelBlueprint.dataformatResolver." + dataformat);
        if (cm == null) {
            MutableReferenceMetadata svc = context.createMetadata(MutableReferenceMetadata.class);
            svc.setId(".camelBlueprint.dataformatResolver." + dataformat);
            svc.setFilter("(dataformat=" + dataformat + ")");
            svc.setAvailability(componentDefinitionRegistry.containsComponentDefinition(dataformat) ? AVAILABILITY_OPTIONAL : AVAILABILITY_MANDATORY);
            try {
                // Try to set the runtime interface (only with aries blueprint > 0.1
                svc.getClass().getMethod("setRuntimeInterface", Class.class).invoke(svc, DataFormatResolver.class);
            } catch (Throwable t) {
                // Check if the bundle can see the class
                try {
                    PassThroughMetadata ptm = (PassThroughMetadata) componentDefinitionRegistry.getComponentDefinition("blueprintBundle");
                    Bundle b = (Bundle) ptm.getObject();
                    if (b.loadClass(DataFormatResolver.class.getName()) != DataFormatResolver.class) {
                        throw new UnsupportedOperationException();
                    }
                    svc.setInterface(DataFormatResolver.class.getName());
                } catch (Throwable t2) {
                    throw new UnsupportedOperationException();
                }
            }
            componentDefinitionRegistry.registerComponentDefinition(svc);
            cm = svc;
        }
        return cm;
    }

    private static ComponentMetadata getLanguageResolverReference(ParserContext context, String language) {
        // we cannot resolve language names using property placeholders at this point in time
        if (language.startsWith(PropertiesComponent.PREFIX_TOKEN)) {
            return null;
        }
        ComponentDefinitionRegistry componentDefinitionRegistry = context.getComponentDefinitionRegistry();
        ComponentMetadata cm = componentDefinitionRegistry.getComponentDefinition(".camelBlueprint.languageResolver." + language);
        if (cm == null) {
            MutableReferenceMetadata svc = context.createMetadata(MutableReferenceMetadata.class);
            svc.setId(".camelBlueprint.languageResolver." + language);
            svc.setFilter("(language=" + language + ")");
            svc.setAvailability(componentDefinitionRegistry.containsComponentDefinition(language) ? AVAILABILITY_OPTIONAL : AVAILABILITY_MANDATORY);
            try {
                // Try to set the runtime interface (only with aries blueprint > 0.1
                svc.getClass().getMethod("setRuntimeInterface", Class.class).invoke(svc, LanguageResolver.class);
            } catch (Throwable t) {
                // Check if the bundle can see the class
                try {
                    PassThroughMetadata ptm = (PassThroughMetadata) componentDefinitionRegistry.getComponentDefinition("blueprintBundle");
                    Bundle b = (Bundle) ptm.getObject();
                    if (b.loadClass(LanguageResolver.class.getName()) != LanguageResolver.class) {
                        throw new UnsupportedOperationException();
                    }
                    svc.setInterface(LanguageResolver.class.getName());
                } catch (Throwable t2) {
                    throw new UnsupportedOperationException();
                }
            }
            componentDefinitionRegistry.registerComponentDefinition(svc);
            cm = svc;
        }
        return cm;
    }

    private static ComponentMetadata getComponentResolverReference(ParserContext context, String component) {
        // we cannot resolve component names using property placeholders at this point in time
        if (component.startsWith(PropertiesComponent.PREFIX_TOKEN)) {
            return null;
        }
        ComponentDefinitionRegistry componentDefinitionRegistry = context.getComponentDefinitionRegistry();
        ComponentMetadata cm = componentDefinitionRegistry.getComponentDefinition(".camelBlueprint.componentResolver." + component);
        if (cm == null) {
            MutableReferenceMetadata svc = context.createMetadata(MutableReferenceMetadata.class);
            svc.setId(".camelBlueprint.componentResolver." + component);
            svc.setFilter("(component=" + component + ")");
            svc.setAvailability(componentDefinitionRegistry.containsComponentDefinition(component) ? AVAILABILITY_OPTIONAL : AVAILABILITY_MANDATORY);
            try {
                // Try to set the runtime interface (only with aries blueprint > 0.1
                svc.getClass().getMethod("setRuntimeInterface", Class.class).invoke(svc, ComponentResolver.class);
            } catch (Throwable t) {
                // Check if the bundle can see the class
                try {
                    PassThroughMetadata ptm = (PassThroughMetadata) componentDefinitionRegistry.getComponentDefinition("blueprintBundle");
                    Bundle b = (Bundle) ptm.getObject();
                    if (b.loadClass(ComponentResolver.class.getName()) != ComponentResolver.class) {
                        throw new UnsupportedOperationException();
                    }
                    svc.setInterface(ComponentResolver.class.getName());
                } catch (Throwable t2) {
                    throw new UnsupportedOperationException();
                }
            }
            componentDefinitionRegistry.registerComponentDefinition(svc);
            cm = svc;
        }
        return cm;
    }

    public static class PassThroughCallable<T> implements Callable<T> {

        private T value;

        public PassThroughCallable(T value) {
            this.value = value;
        }

        @Override
        public T call() throws Exception {
            return value;
        }
    }

    public static class CamelInjector extends CamelPostProcessorHelper implements BeanProcessor {

        private final String camelContextName;
        private BlueprintContainer blueprintContainer;

        public CamelInjector(String camelContextName) {
            this.camelContextName = camelContextName;
        }

        public void setBlueprintContainer(BlueprintContainer blueprintContainer) {
            this.blueprintContainer = blueprintContainer;
        }

        @Override
        public CamelContext getCamelContext() {
            if (blueprintContainer != null) {
                CamelContext answer = (CamelContext) blueprintContainer.getComponentInstance(camelContextName);
                return answer;
            }
            return null;
        }

        @Override
        public Object beforeInit(Object bean, String beanName, BeanCreator beanCreator, BeanMetadata beanMetadata) {
            LOG.trace("Before init of bean: {} -> {}", beanName, bean);
            // prefer to inject later in afterInit
            return bean;
        }

        /**
         * A strategy method to allow implementations to perform some custom JBI
         * based injection of the POJO
         *
         * @param bean the bean to be injected
         */
        protected void injectFields(final Object bean, final String beanName) {
            Class<?> clazz = bean.getClass();
            do {
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    PropertyInject propertyInject = field.getAnnotation(PropertyInject.class);
                    if (propertyInject != null) {
                        injectFieldProperty(field, propertyInject.value(), propertyInject.defaultValue(), bean, beanName);
                    }

                    BeanInject beanInject = field.getAnnotation(BeanInject.class);
                    if (beanInject != null) {
                        injectFieldBean(field, beanInject.value(), bean, beanName);
                    }

                    EndpointInject endpointInject = field.getAnnotation(EndpointInject.class);
                    if (endpointInject != null) {
                        String uri = endpointInject.value().isEmpty() ? endpointInject.uri() : endpointInject.value();
                        injectField(field, uri, endpointInject.property(), bean, beanName);
                    }

                    Produce produce = field.getAnnotation(Produce.class);
                    if (produce != null) {
                        String uri = produce.value().isEmpty() ? produce.uri() : produce.value();
                        injectField(field, uri, produce.property(), bean, beanName);
                    }
                }
                clazz = clazz.getSuperclass();
            } while (clazz != null && clazz != Object.class);
        }

        protected void injectField(Field field, String endpointUri, String endpointProperty, Object bean, String beanName) {
            setField(field, bean, getInjectionValue(field.getType(), endpointUri, endpointProperty, field.getName(), bean, beanName));
        }

        protected void injectFieldProperty(Field field, String propertyName, String propertyDefaultValue, Object bean, String beanName) {
            setField(field, bean, getInjectionPropertyValue(field.getType(), propertyName, propertyDefaultValue, field.getName(), bean, beanName));
        }

        public void injectFieldBean(Field field, String name, Object bean, String beanName) {
            setField(field, bean, getInjectionBeanValue(field.getType(), name));
        }

        protected static void setField(Field field, Object instance, Object value) {
            try {
                boolean oldAccessible = field.isAccessible();
                boolean shouldSetAccessible = !Modifier.isPublic(field.getModifiers()) && !oldAccessible;
                if (shouldSetAccessible) {
                    field.setAccessible(true);
                }
                field.set(instance, value);
                if (shouldSetAccessible) {
                    field.setAccessible(oldAccessible);
                }
            } catch (IllegalArgumentException ex) {
                throw new UnsupportedOperationException("Cannot inject value of class: " + value.getClass() + " into: " + field);
            } catch (IllegalAccessException ex) {
                throw new IllegalStateException("Could not access method: " + ex.getMessage());
            }
        }

        protected void injectMethods(final Object bean, final String beanName) {
            Class<?> clazz = bean.getClass();
            do {
                Method[] methods = clazz.getDeclaredMethods();
                for (Method method : methods) {
                    setterInjection(method, bean, beanName);
                    consumerInjection(method, bean, beanName);
                }
                clazz = clazz.getSuperclass();
            } while (clazz != null && clazz != Object.class);
        }

        protected void setterInjection(Method method, Object bean, String beanName) {
            PropertyInject propertyInject = method.getAnnotation(PropertyInject.class);
            if (propertyInject != null) {
                setterPropertyInjection(method, propertyInject.value(), propertyInject.defaultValue(), bean, beanName);
            }

            BeanInject beanInject = method.getAnnotation(BeanInject.class);
            if (beanInject != null) {
                setterBeanInjection(method, beanInject.value(), bean, beanName);
            }

            EndpointInject endpointInject = method.getAnnotation(EndpointInject.class);
            if (endpointInject != null) {
                String uri = endpointInject.value().isEmpty() ? endpointInject.uri() : endpointInject.value();
                setterInjection(method, bean, beanName, uri, endpointInject.property());
            }

            Produce produce = method.getAnnotation(Produce.class);
            if (produce != null) {
                String uri = produce.value().isEmpty() ? produce.uri() : produce.value();
                setterInjection(method, bean, beanName, uri, produce.property());
            }
        }

        protected void setterPropertyInjection(Method method, String propertyValue, String propertyDefaultValue, Object bean, String beanName) {
            Class<?>[] parameterTypes = method.getParameterTypes();
            if (parameterTypes.length != 1) {
                LOG.warn("Ignoring badly annotated method for injection due to incorrect number of parameters: {}", method);
            } else {
                String propertyName = org.apache.camel.util.ObjectHelper.getPropertyName(method);
                Object value = getInjectionPropertyValue(parameterTypes[0], propertyValue, propertyDefaultValue, propertyName, bean, beanName);
                ObjectHelper.invokeMethod(method, bean, value);
            }
        }

        protected void setterBeanInjection(Method method, String name, Object bean, String beanName) {
            Class<?>[] parameterTypes = method.getParameterTypes();
            if (parameterTypes.length != 1) {
                LOG.warn("Ignoring badly annotated method for injection due to incorrect number of parameters: {}", method);
            } else {
                Object value = getInjectionBeanValue(parameterTypes[0], name);
                ObjectHelper.invokeMethod(method, bean, value);
            }
        }

        protected void setterInjection(Method method, Object bean, String beanName, String endpointUri, String endpointProperty) {
            Class<?>[] parameterTypes = method.getParameterTypes();
            if (parameterTypes.length != 1) {
                LOG.warn("Ignoring badly annotated method for injection due to incorrect number of parameters: {}", method);
            } else {
                String propertyName = org.apache.camel.util.ObjectHelper.getPropertyName(method);
                Object value = getInjectionValue(parameterTypes[0], endpointUri, endpointProperty, propertyName, bean, beanName);
                ObjectHelper.invokeMethod(method, bean, value);
            }
        }

        @Override
        public Object afterInit(Object bean, String beanName, BeanCreator beanCreator, BeanMetadata beanMetadata) {
            LOG.trace("After init of bean: {} -> {}", beanName, bean);
            // we cannot inject CamelContextAware beans as the CamelContext may not be ready
            // TODO: use bean post processor instead
            injectFields(bean, beanName);
            injectMethods(bean, beanName);
            return bean;
        }

        @Override
        public void beforeDestroy(Object bean, String beanName) {
        }

        @Override
        public void afterDestroy(Object bean, String beanName) {
        }

        @Override
        protected boolean isSingleton(Object bean, String beanName) {
            if (beanName != null) {
                ComponentMetadata meta = blueprintContainer.getComponentMetadata(beanName);
                if (meta instanceof BeanMetadata) {
                    String scope = ((BeanMetadata) meta).getScope();
                    if (scope != null) {
                        return BeanMetadata.SCOPE_SINGLETON.equals(scope);
                    }
                }
            }
            // fallback to super, which will assume singleton
            // for beans not implementing Camel's IsSingleton interface
            return super.isSingleton(bean, beanName);
        }
    }

    public static class CamelDependenciesFinder implements ComponentDefinitionRegistryProcessor {

        private final String camelContextName;
        private final ParserContext context;
        private BlueprintContainer blueprintContainer;

        public CamelDependenciesFinder(String camelContextName, ParserContext context) {
            this.camelContextName = camelContextName;
            this.context = context;
        }

        public void setBlueprintContainer(BlueprintContainer blueprintContainer) {
            this.blueprintContainer = blueprintContainer;
        }

        @Override
        public void process(ComponentDefinitionRegistry componentDefinitionRegistry) {
            CamelContextFactoryBean ccfb = (CamelContextFactoryBean) blueprintContainer.getComponentInstance(".camelBlueprint.factory." + camelContextName);
            CamelContext camelContext = ccfb.getContext();

            Set<String> components = new HashSet<>();
            Set<String> languages = new HashSet<>();
            Set<String> dataformats = new HashSet<>();

            // regular camel routes
            for (RouteDefinition rd : camelContext.getExtension(Model.class).getRouteDefinitions()) {
                findInputComponents(rd.getInput(), components, languages, dataformats);
                findOutputComponents(rd.getOutputs(), components, languages, dataformats);
            }

            // rest services can have embedded routes or a singular to
            for (RestDefinition rd : camelContext.getExtension(Model.class).getRestDefinitions()) {
                for (VerbDefinition vd : rd.getVerbs()) {
                    Object o = vd.getToOrRoute();
                    if (o instanceof RouteDefinition) {
                        RouteDefinition route = (RouteDefinition) o;
                        findInputComponents(route.getInput(), components, languages, dataformats);
                        findOutputComponents(route.getOutputs(), components, languages, dataformats);
                    } else if (o instanceof ToDefinition) {
                        findUriComponent(((ToDefinition) o).getUri(), components);
                    } else if (o instanceof ToDynamicDefinition) {
                        findUriComponent(((ToDynamicDefinition) o).getUri(), components);
                    }
                }
            }

            if (ccfb.getRestConfiguration() != null) {
                // rest configuration may refer to a component to use
                String component = ccfb.getRestConfiguration().getComponent();
                if (component != null) {
                    components.add(component);
                }
                component = ccfb.getRestConfiguration().getApiComponent();
                if (component != null) {
                    components.add(component);
                }

                // check what data formats are used in binding mode
                RestBindingMode mode = ccfb.getRestConfiguration().getBindingMode();
                String json = ccfb.getRestConfiguration().getJsonDataFormat();
                if (json == null && mode != null) {
                    if (RestBindingMode.json.equals(mode) || RestBindingMode.json_xml.equals(mode)) {
                        // jackson is the default json data format
                        json = "json-jackson";
                    }
                }
                if (json != null) {
                    dataformats.add(json);
                }
                String xml = ccfb.getRestConfiguration().getXmlDataFormat();
                if (xml == null && mode != null) {
                    if (RestBindingMode.xml.equals(mode) || RestBindingMode.json_xml.equals(mode)) {
                        // jaxb is the default xml data format
                        dataformats.add("jaxb");
                    }
                }
                if (xml != null) {
                    dataformats.add(xml);
                }
            }

            // We can only add service references to resolvers, but we can't make the factory depends on those
            // because the factory has already been instantiated
            try {
                for (String component : components) {
                    if (camelContext.getComponent(component, false) == null) {
                        // component not already in camel-context so resolve an OSGi reference to it
                        getComponentResolverReference(context, component);
                    } else {
                        LOG.debug("Not creating a service reference for component {} because a component already exists in the Camel Context", component);
                    }
                }
                for (String language : languages) {
                    getLanguageResolverReference(context, language);
                }
                for (String dataformat : dataformats) {
                    getDataformatResolverReference(context, dataformat);
                }
            } catch (UnsupportedOperationException e) {
                LOG.warn("Unable to add dependencies to Camel components OSGi services. "
                    + "The Apache Aries blueprint implementation used is too old and the blueprint bundle cannot see the org.apache.camel.spi package.");
                components.clear();
                languages.clear();
                dataformats.clear();
            }

        }

        private void findInputComponents(FromDefinition from, Set<String> components, Set<String> languages, Set<String> dataformats) {
            if (from != null) {
                findUriComponent(from.getUri(), components);
                findSchedulerUriComponent(from.getUri(), components);
            }
        }

        @SuppressWarnings({"rawtypes"})
        private void findOutputComponents(List<ProcessorDefinition<?>> defs, Set<String> components, Set<String> languages, Set<String> dataformats) {
            if (defs != null) {
                for (ProcessorDefinition<?> def : defs) {
                    if (def instanceof SendDefinition) {
                        findUriComponent(((SendDefinition) def).getUri(), components);
                    }
                    if (def instanceof MarshalDefinition) {
                        findDataFormat(((MarshalDefinition) def).getDataFormatType(), dataformats);
                    }
                    if (def instanceof UnmarshalDefinition) {
                        findDataFormat(((UnmarshalDefinition) def).getDataFormatType(), dataformats);
                    }
                    if (def instanceof ExpressionNode) {
                        findLanguage(((ExpressionNode) def).getExpression(), languages);
                    }
                    if (def instanceof ResequenceDefinition) {
                        findLanguage(((ResequenceDefinition) def).getExpression(), languages);
                    }
                    if (def instanceof AggregateDefinition) {
                        findLanguage(((AggregateDefinition) def).getExpression(), languages);
                        findLanguage(((AggregateDefinition) def).getCorrelationExpression(), languages);
                        findLanguage(((AggregateDefinition) def).getCompletionPredicate(), languages);
                        findLanguage(((AggregateDefinition) def).getCompletionTimeoutExpression(), languages);
                        findLanguage(((AggregateDefinition) def).getCompletionSizeExpression(), languages);
                    }
                    if (def instanceof CatchDefinition) {
                        CatchDefinition doCatch = (CatchDefinition) def;
                        if (doCatch.getOnWhen() != null) {
                            findLanguage(doCatch.getOnWhen().getExpression(), languages);
                        }
                    }
                    if (def instanceof OnExceptionDefinition) {
                        findLanguage(((OnExceptionDefinition) def).getRetryWhile(), languages);
                        findLanguage(((OnExceptionDefinition) def).getHandled(), languages);
                        findLanguage(((OnExceptionDefinition) def).getContinued(), languages);
                    }
                    if (def instanceof SortDefinition) {
                        findLanguage(((SortDefinition) def).getExpression(), languages);
                    }
                    if (def instanceof WireTapDefinition) {
                        findLanguage(((WireTapDefinition<?>) def).getNewExchangeExpression(), languages);
                    }
                    findOutputComponents(def.getOutputs(), components, languages, dataformats);
                }
            }
        }

        private void findLanguage(ExpressionDefinition expression, Set<String> languages) {
            if (expression != null) {
                String lang = expression.getLanguage();
                if (lang != null && lang.length() > 0) {
                    languages.add(lang);
                }
            }
        }

        private void findLanguage(ExpressionSubElementDefinition expression, Set<String> languages) {
            if (expression != null) {
                findLanguage(expression.getExpressionType(), languages);
            }
        }

        private void findDataFormat(DataFormatDefinition dfd, Set<String> dataformats) {
            if (dfd != null && dfd.getDataFormatName() != null) {
                dataformats.add(dfd.getDataFormatName());
            }
        }

        private void findUriComponent(String uri, Set<String> components) {
            // if the uri is a placeholder then skip it
            if (uri == null || uri.startsWith(PropertiesComponent.PREFIX_TOKEN)) {
                return;
            }

            // validate uri here up-front so a meaningful error can be logged for blueprint
            // it will also speed up tests in case of failure
            if (!validateUri(uri)) {
                return;
            }

            String splitURI[] = StringHelper.splitOnCharacter(uri, ":", 2);
            if (splitURI[1] != null) {
                String scheme = splitURI[0];
                components.add(scheme);
            }
        }

        private void findSchedulerUriComponent(String uri, Set<String> components) {

            // the input may use a scheduler which can be quartz or spring
            if (uri != null) {
                try {
                    URI u = new URI(uri);
                    Map<String, Object> parameters = URISupport.parseParameters(u);
                    Object value = parameters.get("scheduler");
                    if (value != null) {
                        // the scheduler can be quartz or spring based, so add reference to camel component
                        // from these components os blueprint knows about the requirement
                        String name = value.toString();
                        if ("quartz".equals(name)) {
                            components.add("quartz");
                        } else if ("spring".equals(name)) {
                            components.add("spring-event");
                        }
                    }
                } catch (URISyntaxException e) {
                    // ignore as uri should be already validated at findUriComponent method
                }
            }
        }

        private static boolean validateUri(String uri) {
            try {
                // the same validation as done in DefaultCamelContext#normalizeEndpointUri(String)
                URISupport.normalizeUri(uri);
            } catch (URISyntaxException | UnsupportedEncodingException e) {
                LOG.error("Endpoint URI '" + uri + "' is not valid due to: " + e.getMessage(), e);
                return false;
            }
            return true;
        }
    }

}
