jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtUtils.java
author chegar
Wed, 03 Dec 2014 14:22:58 +0000
changeset 27565 729f9700483a
child 36511 9d0388c6b336
permissions -rw-r--r--
8049367: Modular Run-Time Images Reviewed-by: chegar, dfuchs, ihse, joehw, mullan, psandoz, wetmore Contributed-by: alan.bateman@oracle.com, alex.buckley@oracle.com, bradford.wetmore@oracle.com, chris.hegarty@oracle.com, erik.joelsson@oracle.com, james.laskey@oracle.com, jonathan.gibbons@oracle.com, karen.kinnear@oracle.com, magnus.ihse.bursie@oracle.com, mandy.chung@oracle.com, mark.reinhold@oracle.com, paul.sandoz@oracle.com, sundararajan.athijegannathan@oracle.com
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
27565
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     1
/*
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     2
 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     4
 *
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    10
 *
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    15
 * accompanied this code).
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    16
 *
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    20
 *
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    23
 * questions.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    24
 */
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    25
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    26
package jdk.internal.jrtfs;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    27
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    28
import java.util.regex.PatternSyntaxException;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    29
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    30
final class JrtUtils {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    31
    private JrtUtils() {}
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    32
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    33
    private static final String regexMetaChars = ".^$+{[]|()";
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    34
    private static final String globMetaChars = "\\*?[{";
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    35
    private static boolean isRegexMeta(char c) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    36
        return regexMetaChars.indexOf(c) != -1;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    37
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    38
    private static boolean isGlobMeta(char c) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    39
        return globMetaChars.indexOf(c) != -1;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    40
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    41
    private static final char EOL = 0;  //TBD
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    42
    private static char next(String glob, int i) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    43
        if (i < glob.length()) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    44
            return glob.charAt(i);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    45
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    46
        return EOL;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    47
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    48
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    49
    /*
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    50
     * Creates a regex pattern from the given glob expression.
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    51
     *
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    52
     * @throws  PatternSyntaxException
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    53
     */
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    54
    public static String toRegexPattern(String globPattern) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    55
        boolean inGroup = false;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    56
        StringBuilder regex = new StringBuilder("^");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    57
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    58
        int i = 0;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    59
        while (i < globPattern.length()) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    60
            char c = globPattern.charAt(i++);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    61
            switch (c) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    62
                case '\\':
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    63
                    // escape special characters
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    64
                    if (i == globPattern.length()) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    65
                        throw new PatternSyntaxException("No character to escape",
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    66
                                globPattern, i - 1);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    67
                    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    68
                    char next = globPattern.charAt(i++);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    69
                    if (isGlobMeta(next) || isRegexMeta(next)) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    70
                        regex.append('\\');
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    71
                    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    72
                    regex.append(next);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    73
                    break;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    74
                case '/':
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    75
                    regex.append(c);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    76
                    break;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    77
                case '[':
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    78
                    // don't match name separator in class
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    79
                    regex.append("[[^/]&&[");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    80
                    if (next(globPattern, i) == '^') {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    81
                        // escape the regex negation char if it appears
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    82
                        regex.append("\\^");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    83
                        i++;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    84
                    } else {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    85
                        // negation
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    86
                        if (next(globPattern, i) == '!') {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    87
                            regex.append('^');
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    88
                            i++;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    89
                        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    90
                        // hyphen allowed at start
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    91
                        if (next(globPattern, i) == '-') {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    92
                            regex.append('-');
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    93
                            i++;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    94
                        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    95
                    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    96
                    boolean hasRangeStart = false;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    97
                    char last = 0;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    98
                    while (i < globPattern.length()) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
    99
                        c = globPattern.charAt(i++);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   100
                        if (c == ']') {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   101
                            break;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   102
                        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   103
                        if (c == '/') {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   104
                            throw new PatternSyntaxException("Explicit 'name separator' in class",
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   105
                                    globPattern, i - 1);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   106
                        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   107
                        // TBD: how to specify ']' in a class?
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   108
                        if (c == '\\' || c == '[' ||
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   109
                                c == '&' && next(globPattern, i) == '&') {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   110
                            // escape '\', '[' or "&&" for regex class
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   111
                            regex.append('\\');
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   112
                        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   113
                        regex.append(c);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   114
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   115
                        if (c == '-') {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   116
                            if (!hasRangeStart) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   117
                                throw new PatternSyntaxException("Invalid range",
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   118
                                        globPattern, i - 1);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   119
                            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   120
                            if ((c = next(globPattern, i++)) == EOL || c == ']') {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   121
                                break;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   122
                            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   123
                            if (c < last) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   124
                                throw new PatternSyntaxException("Invalid range",
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   125
                                        globPattern, i - 3);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   126
                            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   127
                            regex.append(c);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   128
                            hasRangeStart = false;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   129
                        } else {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   130
                            hasRangeStart = true;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   131
                            last = c;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   132
                        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   133
                    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   134
                    if (c != ']') {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   135
                        throw new PatternSyntaxException("Missing ']", globPattern, i - 1);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   136
                    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   137
                    regex.append("]]");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   138
                    break;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   139
                case '{':
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   140
                    if (inGroup) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   141
                        throw new PatternSyntaxException("Cannot nest groups",
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   142
                                globPattern, i - 1);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   143
                    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   144
                    regex.append("(?:(?:");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   145
                    inGroup = true;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   146
                    break;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   147
                case '}':
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   148
                    if (inGroup) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   149
                        regex.append("))");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   150
                        inGroup = false;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   151
                    } else {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   152
                        regex.append('}');
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   153
                    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   154
                    break;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   155
                case ',':
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   156
                    if (inGroup) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   157
                        regex.append(")|(?:");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   158
                    } else {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   159
                        regex.append(',');
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   160
                    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   161
                    break;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   162
                case '*':
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   163
                    if (next(globPattern, i) == '*') {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   164
                        // crosses directory boundaries
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   165
                        regex.append(".*");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   166
                        i++;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   167
                    } else {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   168
                        // within directory boundary
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   169
                        regex.append("[^/]*");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   170
                    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   171
                    break;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   172
                case '?':
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   173
                   regex.append("[^/]");
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   174
                   break;
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   175
                default:
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   176
                    if (isRegexMeta(c)) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   177
                        regex.append('\\');
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   178
                    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   179
                    regex.append(c);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   180
            }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   181
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   182
        if (inGroup) {
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   183
            throw new PatternSyntaxException("Missing '}", globPattern, i - 1);
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   184
        }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   185
        return regex.append('$').toString();
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   186
    }
729f9700483a 8049367: Modular Run-Time Images
chegar
parents:
diff changeset
   187
}