< prev index next >

src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/main/CommandLine.java

Print this page




   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.jpackage.main;
  27 

  28 import java.io.IOException;

  29 import java.io.Reader;
  30 import java.nio.charset.Charset;
  31 import java.nio.file.Files;

  32 import java.nio.file.Paths;
  33 import java.util.ArrayList;
  34 import java.util.Arrays;
  35 import java.util.List;
  36 
  37 /**






  38  * Various utility methods for processing Java tool command line arguments.
  39  *
  40  *  <p><b>This is NOT part of any supported API.
  41  *  If you write code that depends on this, you do so at your own risk.
  42  *  This code and its internal interfaces are subject to change or
  43  *  deletion without notice.</b>
  44  */
  45 public class CommandLine {
  46     /**
  47      * Process Win32-style command files for the specified command line
  48      * arguments and return the resulting arguments. A command file argument
  49      * is of the form '@file' where 'file' is the name of the file whose
  50      * contents are to be parsed for additional arguments. The contents of
  51      * the command file are parsed using StreamTokenizer and the original
  52      * '@file' argument replaced with the resulting tokens. Recursive command
  53      * files are not supported. The '@' character itself can be quoted with
  54      * the sequence '@@'.
  55      * @param args the arguments that may contain @files
  56      * @return the arguments, with @files expanded
  57      * @throws IOException if there is a problem reading any of the @files
  58      */
  59     public static String[] parse(String[] args) throws IOException {
  60         List<String> newArgs = new ArrayList<>();
  61         appendParsedCommandArgs(newArgs, Arrays.asList(args));
  62         return newArgs.toArray(new String[newArgs.size()]);
  63     }
  64 
  65     private static void appendParsedCommandArgs(List<String> newArgs, List<String> args) throws IOException {

  66         for (String arg : args) {
  67             if (arg.length() > 1 && arg.charAt(0) == '@') {
  68                 arg = arg.substring(1);
  69                 if (arg.charAt(0) == '@') {
  70                     newArgs.add(arg);
  71                 } else {
  72                     loadCmdFile(arg, newArgs);
  73                 }
  74             } else {
  75                 newArgs.add(arg);
  76             }
  77         }
  78     }
  79 
  80     /**
  81      * Process the given environment variable and appends any Win32-style
  82      * command files for the specified command line arguments and return
  83      * the resulting arguments. A command file argument
  84      * is of the form '@file' where 'file' is the name of the file whose
  85      * contents are to be parsed for additional arguments. The contents of
  86      * the command file are parsed using StreamTokenizer and the original
  87      * '@file' argument replaced with the resulting tokens. Recursive command
  88      * files are not supported. The '@' character itself can be quoted with
  89      * the sequence '@@'.
  90      * @param envVariable the env variable to process
  91      * @param args the arguments that may contain @files
  92      * @return the arguments, with environment variable's content and expansion of @files
  93      * @throws IOException if there is a problem reading any of the @files
  94      * @throws com.sun.tools.javac.main.CommandLine.UnmatchedQuote
  95      */
  96     public static List<String> parse(String envVariable, List<String> args)
  97             throws IOException, UnmatchedQuote {
  98 
  99         List<String> inArgs = new ArrayList<>();
 100         appendParsedEnvVariables(inArgs, envVariable);
 101         inArgs.addAll(args);
 102         List<String> newArgs = new ArrayList<>();
 103         appendParsedCommandArgs(newArgs, inArgs);
 104         return newArgs;
 105     }
 106 
 107     /**
 108      * Process the given environment variable and appends any Win32-style
 109      * command files for the specified command line arguments and return
 110      * the resulting arguments. A command file argument
 111      * is of the form '@file' where 'file' is the name of the file whose
 112      * contents are to be parsed for additional arguments. The contents of
 113      * the command file are parsed using StreamTokenizer and the original
 114      * '@file' argument replaced with the resulting tokens. Recursive command
 115      * files are not supported. The '@' character itself can be quoted with
 116      * the sequence '@@'.
 117      * @param envVariable the env variable to process
 118      * @param args the arguments that may contain @files
 119      * @return the arguments, with environment variable's content and expansion of @files
 120      * @throws IOException if there is a problem reading any of the @files
 121      * @throws com.sun.tools.javac.main.CommandLine.UnmatchedQuote
 122      */
 123     public static String[] parse(String envVariable, String[] args) throws IOException, UnmatchedQuote {
 124         List<String> out = parse(envVariable, Arrays.asList(args));
 125         return out.toArray(new String[out.size()]);
 126     }
 127 
 128     private static void loadCmdFile(String name, List<String> args) throws IOException {
 129         try (Reader r = Files.newBufferedReader(Paths.get(name), Charset.defaultCharset())) {
 130             Tokenizer t = new Tokenizer(r);
 131             String s;
 132             while ((s = t.nextToken()) != null) {
 133                 args.add(s);
 134             }
 135         }
 136     }
 137 
 138     public static class Tokenizer {
 139         private final Reader in;
 140         private int ch;
 141 
 142         public Tokenizer(Reader in) throws IOException {
 143             this.in = in;
 144             ch = in.read();
 145         }
 146 
 147         public String nextToken() throws IOException {
 148             skipWhite();
 149             if (ch == -1) {


 168                     case '\r':
 169                         return sb.toString();
 170 
 171                     case '\'':
 172                     case '"':
 173                         if (quoteChar == 0) {
 174                             quoteChar = (char) ch;
 175                         } else if (quoteChar == ch) {
 176                             quoteChar = 0;
 177                         } else {
 178                             sb.append((char) ch);
 179                         }
 180                         break;
 181 
 182                     case '\\':
 183                         if (quoteChar != 0) {
 184                             ch = in.read();
 185                             switch (ch) {
 186                                 case '\n':
 187                                 case '\r':
 188                                     while (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\f') {


 189                                         ch = in.read();
 190                                     }
 191                                     continue;
 192 
 193                                 case 'n':
 194                                     ch = '\n';
 195                                     break;
 196                                 case 'r':
 197                                     ch = '\r';
 198                                     break;
 199                                 case 't':
 200                                     ch = '\t';
 201                                     break;
 202                                 case 'f':
 203                                     ch = '\f';
 204                                     break;
 205                             }
 206                         }
 207                         sb.append((char) ch);
 208                         break;


 223                     case ' ':
 224                     case '\t':
 225                     case '\n':
 226                     case '\r':
 227                     case '\f':
 228                         break;
 229 
 230                     case '#':
 231                         ch = in.read();
 232                         while (ch != '\n' && ch != '\r' && ch != -1) {
 233                             ch = in.read();
 234                         }
 235                         break;
 236 
 237                     default:
 238                         return;
 239                 }
 240 
 241                 ch = in.read();
 242             }
 243         }
 244     }
 245 
 246     @SuppressWarnings("fallthrough")
 247     private static void appendParsedEnvVariables(List<String> newArgs, String envVariable)
 248             throws UnmatchedQuote {
 249 
 250         if (envVariable == null) {
 251             return;
 252         }
 253         String in = System.getenv(envVariable);
 254         if (in == null || in.trim().isEmpty()) {
 255             return;
 256         }
 257 
 258         final char NUL = (char)0;
 259         final int len = in.length();
 260 
 261         int pos = 0;
 262         StringBuilder sb = new StringBuilder();
 263         char quote = NUL;
 264         char ch;
 265 
 266         loop:
 267         while (pos < len) {
 268             ch = in.charAt(pos);
 269             switch (ch) {
 270                 case '\"': case '\'':
 271                     if (quote == NUL) {
 272                         quote = ch;
 273                     } else if (quote == ch) {
 274                         quote = NUL;
 275                     } else {
 276                         sb.append(ch);
 277                     }
 278                     pos++;
 279                     break;
 280                 case '\f': case '\n': case '\r': case '\t': case ' ':
 281                     if (quote == NUL) {
 282                         newArgs.add(sb.toString());
 283                         sb.setLength(0);
 284                         while (ch == '\f' || ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') {
 285                             pos++;
 286                             if (pos >= len) {
 287                                 break loop;
 288                             }
 289                             ch = in.charAt(pos);
 290                         }
 291                         break;
 292                     }
 293                     // fall through
 294                 default:
 295                     sb.append(ch);
 296                     pos++;
 297             }
 298         }
 299         if (sb.length() != 0) {
 300             newArgs.add(sb.toString());
 301         }
 302         if (quote != NUL) {
 303             throw new UnmatchedQuote(envVariable);
 304         }
 305     }
 306 
 307     public static class UnmatchedQuote extends Exception {
 308         private static final long serialVersionUID = 0;
 309 
 310         public final String variableName;
 311 
 312         UnmatchedQuote(String variable) {
 313             this.variableName = variable;
 314         }
 315     }
 316 }


   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.incubator.jpackage.main;
  27 
  28 import java.io.FileNotFoundException;
  29 import java.io.IOException;
  30 import java.io.File;
  31 import java.io.Reader;
  32 import java.nio.charset.Charset;
  33 import java.nio.file.Files;
  34 import java.nio.file.Path;
  35 import java.nio.file.Paths;
  36 import java.util.ArrayList;
  37 import java.util.Arrays;
  38 import java.util.List;
  39 
  40 /**
  41  * This file was originally a copy of CommandLine.java in
  42  * com.sun.tools.javac.main.
  43  * It should track changes made to that file.
  44  */
  45 
  46 /**
  47  * Various utility methods for processing Java tool command line arguments.
  48  *
  49  *  <p><b>This is NOT part of any supported API.
  50  *  If you write code that depends on this, you do so at your own risk.
  51  *  This code and its internal interfaces are subject to change or
  52  *  deletion without notice.</b>
  53  */
  54 class CommandLine {
  55     /**
  56      * Process Win32-style command files for the specified command line
  57      * arguments and return the resulting arguments. A command file argument
  58      * is of the form '@file' where 'file' is the name of the file whose
  59      * contents are to be parsed for additional arguments. The contents of
  60      * the command file are parsed using StreamTokenizer and the original
  61      * '@file' argument replaced with the resulting tokens. Recursive command
  62      * files are not supported. The '@' character itself can be quoted with
  63      * the sequence '@@'.
  64      * @param args the arguments that may contain @files
  65      * @return the arguments, with @files expanded
  66      * @throws IOException if there is a problem reading any of the @files
  67      */
  68     public static String[] parse(String[] args) throws IOException {
  69         List<String> newArgs = new ArrayList<>();
  70         appendParsedCommandArgs(newArgs, Arrays.asList(args));
  71         return newArgs.toArray(new String[newArgs.size()]);
  72     }
  73 
  74     private static void appendParsedCommandArgs(List<String> newArgs,
  75             List<String> args) throws IOException {
  76         for (String arg : args) {
  77             if (arg.length() > 1 && arg.charAt(0) == '@') {
  78                 arg = arg.substring(1);
  79                 if (arg.charAt(0) == '@') {
  80                     newArgs.add(arg);
  81                 } else {
  82                     loadCmdFile(arg, newArgs);
  83                 }
  84             } else {
  85                 newArgs.add(arg);
  86             }
  87         }
  88     }
  89 
  90     private static void loadCmdFile(String name, List<String> args)
  91             throws IOException {
  92         if (!Files.isReadable(Path.of(name))) {
  93             throw new FileNotFoundException(name);





















  94         }
  95         try (Reader r = Files.newBufferedReader(Paths.get(name),
  96                 Charset.defaultCharset())) {






















  97             Tokenizer t = new Tokenizer(r);
  98             String s;
  99             while ((s = t.nextToken()) != null) {
 100                 args.add(s);
 101             }
 102         }
 103     }
 104 
 105     public static class Tokenizer {
 106         private final Reader in;
 107         private int ch;
 108 
 109         public Tokenizer(Reader in) throws IOException {
 110             this.in = in;
 111             ch = in.read();
 112         }
 113 
 114         public String nextToken() throws IOException {
 115             skipWhite();
 116             if (ch == -1) {


 135                     case '\r':
 136                         return sb.toString();
 137 
 138                     case '\'':
 139                     case '"':
 140                         if (quoteChar == 0) {
 141                             quoteChar = (char) ch;
 142                         } else if (quoteChar == ch) {
 143                             quoteChar = 0;
 144                         } else {
 145                             sb.append((char) ch);
 146                         }
 147                         break;
 148 
 149                     case '\\':
 150                         if (quoteChar != 0) {
 151                             ch = in.read();
 152                             switch (ch) {
 153                                 case '\n':
 154                                 case '\r':
 155                                     while (ch == ' ' || ch == '\n'
 156                                             || ch == '\r' || ch == '\t'
 157                                             || ch == '\f') {
 158                                         ch = in.read();
 159                                     }
 160                                     continue;
 161 
 162                                 case 'n':
 163                                     ch = '\n';
 164                                     break;
 165                                 case 'r':
 166                                     ch = '\r';
 167                                     break;
 168                                 case 't':
 169                                     ch = '\t';
 170                                     break;
 171                                 case 'f':
 172                                     ch = '\f';
 173                                     break;
 174                             }
 175                         }
 176                         sb.append((char) ch);
 177                         break;


 192                     case ' ':
 193                     case '\t':
 194                     case '\n':
 195                     case '\r':
 196                     case '\f':
 197                         break;
 198 
 199                     case '#':
 200                         ch = in.read();
 201                         while (ch != '\n' && ch != '\r' && ch != -1) {
 202                             ch = in.read();
 203                         }
 204                         break;
 205 
 206                     default:
 207                         return;
 208                 }
 209 
 210                 ch = in.read();
 211             }







































































 212         }
 213     }
 214 }
< prev index next >