GlobExpander.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:5k
- /**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 org.apache.hadoop.fs;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
- class GlobExpander {
-
- static class StringWithOffset {
- String string;
- int offset;
- public StringWithOffset(String string, int offset) {
- super();
- this.string = string;
- this.offset = offset;
- }
- }
-
- /**
- * Expand globs in the given <code>filePattern</code> into a collection of
- * file patterns so that in the expanded set no file pattern has a
- * slash character ("/") in a curly bracket pair.
- * @param filePattern
- * @return expanded file patterns
- * @throws IOException
- */
- public static List<String> expand(String filePattern) throws IOException {
- List<String> fullyExpanded = new ArrayList<String>();
- List<StringWithOffset> toExpand = new ArrayList<StringWithOffset>();
- toExpand.add(new StringWithOffset(filePattern, 0));
- while (!toExpand.isEmpty()) {
- StringWithOffset path = toExpand.remove(0);
- List<StringWithOffset> expanded = expandLeftmost(path);
- if (expanded == null) {
- fullyExpanded.add(path.string);
- } else {
- toExpand.addAll(0, expanded);
- }
- }
- return fullyExpanded;
- }
-
- /**
- * Expand the leftmost outer curly bracket pair containing a
- * slash character ("/") in <code>filePattern</code>.
- * @param filePattern
- * @return expanded file patterns
- * @throws IOException
- */
- private static List<StringWithOffset> expandLeftmost(StringWithOffset
- filePatternWithOffset) throws IOException {
-
- String filePattern = filePatternWithOffset.string;
- int leftmost = leftmostOuterCurlyContainingSlash(filePattern,
- filePatternWithOffset.offset);
- if (leftmost == -1) {
- return null;
- }
- int curlyOpen = 0;
- StringBuilder prefix = new StringBuilder(filePattern.substring(0, leftmost));
- StringBuilder suffix = new StringBuilder();
- List<String> alts = new ArrayList<String>();
- StringBuilder alt = new StringBuilder();
- StringBuilder cur = prefix;
- for (int i = leftmost; i < filePattern.length(); i++) {
- char c = filePattern.charAt(i);
- if (cur == suffix) {
- cur.append(c);
- } else if (c == '\') {
- i++;
- if (i >= filePattern.length()) {
- throw new IOException("Illegal file pattern: "
- + "An escaped character does not present for glob "
- + filePattern + " at " + i);
- }
- c = filePattern.charAt(i);
- cur.append(c);
- } else if (c == '{') {
- if (curlyOpen++ == 0) {
- alt.setLength(0);
- cur = alt;
- } else {
- cur.append(c);
- }
- } else if (c == '}' && curlyOpen > 0) {
- if (--curlyOpen == 0) {
- alts.add(alt.toString());
- alt.setLength(0);
- cur = suffix;
- } else {
- cur.append(c);
- }
- } else if (c == ',') {
- if (curlyOpen == 1) {
- alts.add(alt.toString());
- alt.setLength(0);
- } else {
- cur.append(c);
- }
- } else {
- cur.append(c);
- }
- }
- List<StringWithOffset> exp = new ArrayList<StringWithOffset>();
- for (String string : alts) {
- exp.add(new StringWithOffset(prefix + string + suffix, prefix.length()));
- }
- return exp;
- }
-
- /**
- * Finds the index of the leftmost opening curly bracket containing a
- * slash character ("/") in <code>filePattern</code>.
- * @param filePattern
- * @return the index of the leftmost opening curly bracket containing a
- * slash character ("/"), or -1 if there is no such bracket
- * @throws IOException
- */
- private static int leftmostOuterCurlyContainingSlash(String filePattern,
- int offset) throws IOException {
- int curlyOpen = 0;
- int leftmost = -1;
- boolean seenSlash = false;
- for (int i = offset; i < filePattern.length(); i++) {
- char c = filePattern.charAt(i);
- if (c == '\') {
- i++;
- if (i >= filePattern.length()) {
- throw new IOException("Illegal file pattern: "
- + "An escaped character does not present for glob "
- + filePattern + " at " + i);
- }
- } else if (c == '{') {
- if (curlyOpen++ == 0) {
- leftmost = i;
- }
- } else if (c == '}' && curlyOpen > 0) {
- if (--curlyOpen == 0 && leftmost != -1 && seenSlash) {
- return leftmost;
- }
- } else if (c == '/' && curlyOpen > 0) {
- seenSlash = true;
- }
- }
- return -1;
- }
- }