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.model;
018
019import java.util.function.Function;
020
021import javax.xml.bind.annotation.XmlTransient;
022
023import org.apache.camel.support.PatternHelper;
024import org.slf4j.Logger;
025import org.slf4j.LoggerFactory;
026
027/**
028 * Used for filtering routes to only include routes matching a function.
029 */
030@XmlTransient
031public final class RouteFilters implements Function<RouteDefinition, Boolean> {
032
033    private static final Logger LOG = LoggerFactory.getLogger(RouteFilters.class);
034
035    private final String includesText;
036    private final String excludesText;
037    private final String[] includes;
038    private final String[] excludes;
039
040    private RouteFilters(String include, String exclude) {
041        this.includesText = include;
042        this.excludesText = exclude;
043        this.includes = include != null ? include.split(",") : null;
044        this.excludes = exclude != null ? exclude.split(",") : null;
045    }
046
047    /**
048     * Used for filtering routes routes matching the given pattern, which
049     * follows the following rules: - Match by route id - Match by route input
050     * endpoint uri The matching is using exact match, by wildcard and regular
051     * expression as documented by
052     * {@link PatternHelper#matchPattern(String, String)}. For example to only
053     * include routes which starts with foo in their route id's, use:
054     * include=foo&#42; And to exclude routes which starts from JMS endpoints,
055     * use: exclude=jms:&#42; Multiple patterns can be separated by comma, for
056     * example to exclude both foo and bar routes, use:
057     * exclude=foo&#42;,bar&#42; Exclude takes precedence over include.
058     *
059     * @param include the include pattern
060     * @param exclude the exclude pattern
061     */
062    public static Function<RouteDefinition, Boolean> filterByPattern(String include, String exclude) {
063        return new RouteFilters(include, exclude);
064    }
065
066    @Override
067    public Boolean apply(RouteDefinition route) {
068        String id = route.getId();
069        String uri = route.getInput() != null ? route.getInput().getEndpointUri() : null;
070
071        boolean answer = filter(route, id, uri);
072        LOG.debug("Route filter: include={}, exclude={}, id={}, from={} -> {}", includesText, excludesText, id, uri, answer);
073        return answer;
074    }
075
076    private boolean filter(RouteDefinition route, String id, String uri) {
077        boolean match = false;
078
079        // exclude takes precedence
080        if (excludes != null) {
081            for (String part : excludes) {
082                if (PatternHelper.matchPattern(id, part) || PatternHelper.matchPattern(uri, part)) {
083                    return false;
084                }
085            }
086        }
087
088        if (includes != null) {
089            for (String part : includes) {
090                if (PatternHelper.matchPattern(id, part) || PatternHelper.matchPattern(uri, part)) {
091                    match = true;
092                    break;
093                }
094            }
095        } else {
096            // if include has not been set then, we assume its matched as it was
097            // not excluded
098            match = true;
099        }
100
101        return match;
102    }
103
104}