| /* |
| * Copyright 2012-present Facebook, Inc. |
| * |
| * Licensed 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 com.facebook.buck.android; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableSet; |
| |
| /** |
| * Filter for internal class names. |
| * |
| * <p>We use this to determine if a class must be placed in our primary dex. |
| * It supports prefix, suffix, substring, and exact matches. |
| */ |
| public class ClassNameFilter { |
| // We use naive algorithms for prefix, suffix, and substring, but these could easily be |
| // optimzied using RE2 or some other more specialized search algorithms. |
| private final ImmutableList<String> prefixes; |
| private final ImmutableList<String> suffixes; |
| private final ImmutableList<String> substrings; |
| private final ImmutableSet<String> exactMatches; |
| |
| private ClassNameFilter( |
| Iterable<String> prefixes, |
| Iterable<String> suffixes, |
| Iterable<String> substrings, |
| Iterable<String> exactMatches) { |
| this.prefixes = ImmutableList.copyOf(prefixes); |
| this.suffixes = ImmutableList.copyOf(suffixes); |
| this.substrings = ImmutableList.copyOf(substrings); |
| this.exactMatches = ImmutableSet.copyOf(exactMatches); |
| } |
| |
| /** |
| * Convenience factory to produce a filter from a very simple pattern language. |
| * |
| * <p>patterns are substrings by default, but {@code ^} at the start or end of a pattern |
| * anchors it to the start or end of the class name. |
| * |
| * @param patterns Patterns to include in the filter. |
| * @return A new filter. |
| */ |
| public static ClassNameFilter fromConfiguration(Iterable<String> patterns) { |
| ImmutableList.Builder<String> prefixes = ImmutableList.builder(); |
| ImmutableList.Builder<String> suffixes = ImmutableList.builder(); |
| ImmutableList.Builder<String> substrings = ImmutableList.builder(); |
| ImmutableSet.Builder<String> exactMatches = ImmutableSet.builder(); |
| |
| for (String pattern : patterns) { |
| boolean isPrefix = pattern.charAt(0) == '^'; |
| boolean isSuffix = pattern.charAt(pattern.length() - 1) == '^'; |
| if (isPrefix && isSuffix) { |
| exactMatches.add(pattern.substring(1, pattern.length() - 1)); |
| } else if (isPrefix) { |
| prefixes.add(pattern.substring(1)); |
| } else if (isSuffix) { |
| suffixes.add(pattern.substring(0, pattern.length() - 1)); |
| } else { |
| substrings.add(pattern); |
| } |
| } |
| |
| return new ClassNameFilter( |
| prefixes.build(), |
| suffixes.build(), |
| substrings.build(), |
| exactMatches.build()); |
| } |
| |
| public boolean matches(String internalClassName) { |
| if (exactMatches.contains(internalClassName)) { |
| return true; |
| } |
| |
| for (String prefix : prefixes) { |
| if (internalClassName.startsWith(prefix)) { |
| return true; |
| } |
| } |
| |
| for (String suffix : suffixes) { |
| if (internalClassName.endsWith(suffix)) { |
| return true; |
| } |
| } |
| |
| for (String substring : substrings) { |
| if (internalClassName.contains(substring)) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| } |