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.impl;
018
019import java.lang.reflect.Field;
020import java.util.SortedMap;
021import java.util.TreeMap;
022
023import org.apache.camel.CamelContext;
024import org.apache.camel.ComponentConfiguration;
025import org.apache.camel.Endpoint;
026import org.apache.camel.spi.UriParam;
027import org.apache.camel.spi.UriParams;
028import org.apache.camel.util.ObjectHelper;
029import org.apache.camel.util.ReflectionHelper;
030import org.slf4j.Logger;
031import org.slf4j.LoggerFactory;
032
033/**
034 * A component implementation for endpoints which are annotated with UriEndpoint to describe
035 * their configurable parameters via annotations
036 *
037 * @deprecated use {@link DefaultComponent}
038 */
039@Deprecated
040public abstract class UriEndpointComponent extends DefaultComponent {
041    private static final Logger LOG = LoggerFactory.getLogger(UriEndpointComponent.class);
042
043    private Class<? extends Endpoint> endpointClass;
044    private SortedMap<String, ParameterConfiguration> parameterConfigurationMap;
045
046    public UriEndpointComponent(Class<? extends Endpoint> endpointClass) {
047        this.endpointClass = endpointClass;
048    }
049
050    public UriEndpointComponent(CamelContext context, Class<? extends Endpoint> endpointClass) {
051        super(context);
052        this.endpointClass = endpointClass;
053    }
054
055    /**
056     * To use a specific endpoint class, instead of what has been provided by the constructors.
057     *
058     * @param endpointClass the endpoint class to use
059     */
060    public void setEndpointClass(Class<? extends Endpoint> endpointClass) {
061        this.endpointClass = endpointClass;
062    }
063
064    @Override
065    public ComponentConfiguration createComponentConfiguration() {
066        return new UriComponentConfiguration(this);
067    }
068
069    /**
070     * Returns a newly created sorted map, indexed by name of all the parameter configurations
071     * of the given endpoint class using introspection for the various annotations like
072     * {@link org.apache.camel.spi.UriEndpoint}, {@link org.apache.camel.spi.UriParam}, {@link org.apache.camel.spi.UriParams}
073     */
074    public static SortedMap<String, ParameterConfiguration> createParameterConfigurationMap(
075            Class<? extends Endpoint> endpointClass) {
076        SortedMap<String, ParameterConfiguration> answer = new TreeMap<String, ParameterConfiguration>();
077        populateParameterConfigurationMap(answer, endpointClass, "");
078        return answer;
079    }
080
081    protected static void populateParameterConfigurationMap(
082            final SortedMap<String, ParameterConfiguration> parameterMap, Class<?> aClass,
083            final String prefix) {
084        ReflectionHelper.doWithFields(aClass, new ReflectionHelper.FieldCallback() {
085            @Override
086            public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
087                UriParam uriParam = field.getAnnotation(UriParam.class);
088                if (uriParam != null) {
089                    String name = uriParam.name();
090                    if (ObjectHelper.isEmpty(name)) {
091                        name = field.getName();
092                    }
093                    String propertyName = prefix + name;
094
095                    // is the parameter a nested configuration object
096                    Class<?> fieldType = field.getType();
097                    UriParams uriParams = fieldType.getAnnotation(UriParams.class);
098                    if (uriParams != null) {
099                        String nestedPrefix = uriParams.prefix();
100                        if (nestedPrefix == null) {
101                            nestedPrefix = "";
102                        }
103                        nestedPrefix = (prefix + nestedPrefix).trim();
104                        populateParameterConfigurationMap(parameterMap, fieldType, nestedPrefix);
105                    } else {
106                        if (parameterMap.containsKey(propertyName)) {
107                            LOG.warn("Duplicate property name {} defined on field {}", propertyName, field);
108                        } else {
109                            parameterMap.put(propertyName,
110                                    ParameterConfiguration.newInstance(propertyName, field, uriParam));
111                        }
112                    }
113                }
114            }
115        });
116    }
117
118    public Class<? extends Endpoint> getEndpointClass() {
119        return endpointClass;
120    }
121
122    /**
123     * Returns the sorted map of all the URI query parameter names to their {@link ParameterConfiguration} objects
124     */
125    public SortedMap<String, ParameterConfiguration> getParameterConfigurationMap() {
126        if (parameterConfigurationMap == null) {
127            parameterConfigurationMap = createParameterConfigurationMap(getEndpointClass());
128        }
129        return new TreeMap<String, ParameterConfiguration>(parameterConfigurationMap);
130    }
131
132}