/** * Copyright (C) 2008 Mathieu Carbou <mathieu.carbou@gmail.com> * * 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.mycila.testing.plugins.jetty.locator; import static com.google.common.base.Predicates.in; import static com.google.common.base.Predicates.not; import static com.google.common.collect.Iterables.concat; import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Lists.newArrayList; import java.util.Collection; import java.util.List; import java.util.ListIterator; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Splitter; /** * <ul> * <li>? matches one character * <li>* matches zero or more characters * <li>** matches zero or more 'directories' in a path * </ul> */ class AntPath { public AntPath( final String antPath) { this.antPath = antPath; } public boolean matches( final String path) { final boolean matches = path.matches(this.toRegex()); return matches; } String toRegex() { final Iterable<String> splits = this.split(); final String joined = Joiner.on("").skipNulls().join(transform(splits, new Function<String, String>() { public String apply( final String input) { final String regex; if (input.length() == 0) { regex = null; } else if ("?".equals(input)) { regex = "[^/]"; } else if ("*".equals(input)) { regex = "[^/]*"; } else if ("**".equals(input)) { regex = ".*?"; } else if ("**/".equals(input)) { regex = "([^/]+?/)*?"; } else { regex = "\\Q" + input + "\\E"; } return regex; } })); return joined; } private Iterable<String> split() { // pat?/**/t*t/** => pat,?,/,**/,t,*,t/,** // pat,[^/],/,([^/]+?/)*?,t,[^/]*,t/,([^/]+?/)*? Iterable<String> splits = newArrayList(this.antPath); splits = concat(transform(splits, new MultiSplitFunction("?", "**/", "**", "*"))); return splits; } private final String antPath; static class MultiSplitFunction implements Function<String, Iterable<String>> { public MultiSplitFunction( final Iterable<String> separators) { this.separators = separators; } public MultiSplitFunction( final String... separators) { this(newArrayList(separators)); } public Iterable<String> apply( final String input) { final Collection<String> toIgnores = newArrayList(); Iterable<String> splits = newArrayList(input); for (final String separator : this.separators) { splits = this.split(splits, separator, toIgnores); toIgnores.add(separator); } return splits; } private Iterable<String> split( final Iterable<String> inputs, final String separator, final Iterable<String> toIgnore) { final Function<String, Iterable<String>> splitter = new BooleanSwitchFunction<String, Iterable<String>>( not(in(newArrayList(toIgnore))), new SplitFunction(separator), new InputAsIterableFunction()); final Iterable<String> splits = concat(transform(inputs, splitter)); return splits; } private final Iterable<String> separators; } static class SplitFunction implements Function<String, Iterable<String>> { public SplitFunction( final String separator) { this.separator = separator; } public Iterable<String> apply( final String input) { final Iterable<String> parts = Splitter.on(this.separator).split(input); final Iterable<String> splits = insertBetweenEach(parts, this.separator); return splits; } private static Iterable<String> insertBetweenEach( final Iterable<String> elements, final String separator) { final List<String> list = newArrayList(elements); for (final ListIterator<String> iter = list.listIterator(); iter.hasNext();) { if ((iter.nextIndex() > 0) && iter.hasNext()) { iter.add(separator); } iter.next(); } return list; } private final String separator; } static class InputAsIterableFunction implements Function<String, Iterable<String>> { public Iterable<String> apply( final String input) { return newArrayList(input); } } }