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.util.component;
018
019import java.lang.reflect.Field;
020import java.util.Collections;
021import java.util.HashMap;
022import java.util.HashSet;
023import java.util.Map;
024import java.util.Set;
025
026import org.apache.camel.Exchange;
027import org.apache.camel.util.IntrospectionSupport;
028import org.slf4j.Logger;
029import org.slf4j.LoggerFactory;
030
031/**
032 * Helper class to work with ApiMethod arguments to be extended by components.
033 */
034public abstract class ApiMethodPropertiesHelper<C> {
035
036    protected static final Logger LOG = LoggerFactory.getLogger(ApiMethodPropertiesHelper.class);
037
038    // set of field names which are specific to the api, to be excluded from method argument considerations
039    protected final Set<String> componentConfigFields = new HashSet<String>();
040
041    protected final Class<?> componentConfigClass;
042    protected final String propertyPrefix;
043
044    private final int prefixLength;
045    private final String camelCasePrefix;
046
047    protected ApiMethodPropertiesHelper(Class<C> componentConfiguration, String propertyPrefix) {
048
049        this.componentConfigClass = componentConfiguration;
050        this.propertyPrefix = propertyPrefix;
051
052        this.prefixLength = propertyPrefix.length();
053        if (!Character.isLetterOrDigit(propertyPrefix.charAt(prefixLength - 1))) {
054            this.camelCasePrefix = propertyPrefix.substring(0, prefixLength - 1);
055        } else {
056            this.camelCasePrefix = null;
057        }
058
059        for (Field field : componentConfiguration.getDeclaredFields()) {
060            componentConfigFields.add(field.getName());
061        }
062    }
063
064    /**
065     * Gets exchange header properties that start with propertyPrefix.
066     *
067     * @param exchange Camel exchange
068     * @param properties map to collect properties with required prefix
069     */
070    public Map<String, Object> getExchangeProperties(Exchange exchange, Map<String, Object> properties) {
071
072        int nProperties = 0;
073        for (Map.Entry<String, Object> entry : exchange.getIn().getHeaders().entrySet()) {
074            final String key = entry.getKey();
075            if (key.startsWith(propertyPrefix)) {
076                properties.put(key.substring(prefixLength),
077                    entry.getValue());
078                nProperties++;
079            } else if (camelCasePrefix != null && key.startsWith(camelCasePrefix)) {
080                // assuming all property names start with a lowercase character
081                final String propertyName = String.valueOf(Character.toLowerCase(key.charAt(prefixLength - 1)))
082                    + key.substring(prefixLength);
083                properties.put(propertyName, entry.getValue());
084                nProperties++;
085            }
086        }
087        LOG.debug("Found {} properties in exchange", nProperties);
088        return properties;
089    }
090
091    public void getEndpointProperties(Object endpointConfiguration, Map<String, Object> properties) {
092
093        Set<String> names = null;
094        if (IntrospectionSupport.getProperties(endpointConfiguration, properties, null, false)) {
095            names = properties.keySet();
096            // remove component config properties so we only have endpoint properties
097            names.removeAll(componentConfigFields);
098        }
099        LOG.debug("Found endpoint properties {}", names);
100    }
101
102    public Set<String> getEndpointPropertyNames(Object endpointConfiguration) {
103        Map<String, Object> properties = new HashMap<String, Object>();
104        getEndpointProperties(endpointConfiguration, properties);
105        return Collections.unmodifiableSet(properties.keySet());
106    }
107
108    public Set<String> getValidEndpointProperties(Object endpointConfiguration) {
109        Set<String> fields = new HashSet<String>();
110        for (Field field : endpointConfiguration.getClass().getDeclaredFields()) {
111            fields.add(field.getName());
112        }
113        return Collections.unmodifiableSet(fields);
114    }
115
116}