GlobExpander.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:5k
源码类别:

网格计算

开发平台:

Java

  1. /**
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  *     http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing, software
  13.  * distributed under the License is distributed on an "AS IS" BASIS,
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  * See the License for the specific language governing permissions and
  16.  * limitations under the License.
  17.  */
  18. package org.apache.hadoop.fs;
  19. import java.io.IOException;
  20. import java.util.ArrayList;
  21. import java.util.List;
  22. class GlobExpander {
  23.   
  24.   static class StringWithOffset {
  25.     String string;
  26.     int offset;
  27.     public StringWithOffset(String string, int offset) {
  28.       super();
  29.       this.string = string;
  30.       this.offset = offset;
  31.     }
  32.   }
  33.   
  34.   /**
  35.    * Expand globs in the given <code>filePattern</code> into a collection of 
  36.    * file patterns so that in the expanded set no file pattern has a
  37.    * slash character ("/") in a curly bracket pair.
  38.    * @param filePattern
  39.    * @return expanded file patterns
  40.    * @throws IOException 
  41.    */
  42.   public static List<String> expand(String filePattern) throws IOException {
  43.     List<String> fullyExpanded = new ArrayList<String>();
  44.     List<StringWithOffset> toExpand = new ArrayList<StringWithOffset>();
  45.     toExpand.add(new StringWithOffset(filePattern, 0));
  46.     while (!toExpand.isEmpty()) {
  47.       StringWithOffset path = toExpand.remove(0);
  48.       List<StringWithOffset> expanded = expandLeftmost(path);
  49.       if (expanded == null) {
  50.         fullyExpanded.add(path.string);
  51.       } else {
  52.         toExpand.addAll(0, expanded);
  53.       }
  54.     }
  55.     return fullyExpanded;
  56.   }
  57.   
  58.   /**
  59.    * Expand the leftmost outer curly bracket pair containing a
  60.    * slash character ("/") in <code>filePattern</code>.
  61.    * @param filePattern
  62.    * @return expanded file patterns
  63.    * @throws IOException 
  64.    */
  65.   private static List<StringWithOffset> expandLeftmost(StringWithOffset
  66.       filePatternWithOffset) throws IOException {
  67.     
  68.     String filePattern = filePatternWithOffset.string;
  69.     int leftmost = leftmostOuterCurlyContainingSlash(filePattern,
  70.         filePatternWithOffset.offset);
  71.     if (leftmost == -1) {
  72.       return null;
  73.     }
  74.     int curlyOpen = 0;
  75.     StringBuilder prefix = new StringBuilder(filePattern.substring(0, leftmost));
  76.     StringBuilder suffix = new StringBuilder();
  77.     List<String> alts = new ArrayList<String>();
  78.     StringBuilder alt = new StringBuilder();
  79.     StringBuilder cur = prefix;
  80.     for (int i = leftmost; i < filePattern.length(); i++) {
  81.       char c = filePattern.charAt(i);
  82.       if (cur == suffix) {
  83.         cur.append(c);
  84.       } else if (c == '\') {
  85.         i++;
  86.         if (i >= filePattern.length()) {
  87.           throw new IOException("Illegal file pattern: "
  88.               + "An escaped character does not present for glob "
  89.               + filePattern + " at " + i);
  90.         }
  91.         c = filePattern.charAt(i);
  92.         cur.append(c);
  93.       } else if (c == '{') {
  94.         if (curlyOpen++ == 0) {
  95.           alt.setLength(0);
  96.           cur = alt;
  97.         } else {
  98.           cur.append(c);
  99.         }
  100.       } else if (c == '}' && curlyOpen > 0) {
  101.         if (--curlyOpen == 0) {
  102.           alts.add(alt.toString());
  103.           alt.setLength(0);
  104.           cur = suffix;
  105.         } else {
  106.           cur.append(c);
  107.         }
  108.       } else if (c == ',') {
  109.         if (curlyOpen == 1) {
  110.           alts.add(alt.toString());
  111.           alt.setLength(0);
  112.         } else {
  113.           cur.append(c);
  114.         }
  115.       } else {
  116.         cur.append(c);
  117.       }
  118.     }
  119.     List<StringWithOffset> exp = new ArrayList<StringWithOffset>();
  120.     for (String string : alts) {
  121.       exp.add(new StringWithOffset(prefix + string + suffix, prefix.length()));
  122.     }
  123.     return exp;
  124.   }
  125.   
  126.   /**
  127.    * Finds the index of the leftmost opening curly bracket containing a
  128.    * slash character ("/") in <code>filePattern</code>.
  129.    * @param filePattern
  130.    * @return the index of the leftmost opening curly bracket containing a
  131.    * slash character ("/"), or -1 if there is no such bracket
  132.    * @throws IOException 
  133.    */
  134.   private static int leftmostOuterCurlyContainingSlash(String filePattern,
  135.       int offset) throws IOException {
  136.     int curlyOpen = 0;
  137.     int leftmost = -1;
  138.     boolean seenSlash = false;
  139.     for (int i = offset; i < filePattern.length(); i++) {
  140.       char c = filePattern.charAt(i);
  141.       if (c == '\') {
  142.         i++;
  143.         if (i >= filePattern.length()) {
  144.           throw new IOException("Illegal file pattern: "
  145.               + "An escaped character does not present for glob "
  146.               + filePattern + " at " + i);
  147.         }
  148.       } else if (c == '{') {
  149.         if (curlyOpen++ == 0) {
  150.           leftmost = i;
  151.         }
  152.       } else if (c == '}' && curlyOpen > 0) {
  153.         if (--curlyOpen == 0 && leftmost != -1 && seenSlash) {
  154.           return leftmost;
  155.         }
  156.       } else if (c == '/' && curlyOpen > 0) {
  157.         seenSlash = true;
  158.       }
  159.     }
  160.     return -1;
  161.   }
  162. }