View Javadoc
1   /*
2    * SPDX-FileCopyrightText: Copyright (c) 2011-2026 Yegor Bugayenko
3    * SPDX-License-Identifier: MIT
4    */
5   package com.qulice.errorprone;
6   
7   import java.io.File;
8   import java.io.IOException;
9   import java.io.UncheckedIOException;
10  import java.nio.charset.StandardCharsets;
11  import java.nio.file.Files;
12  import java.util.List;
13  
14  /**
15   * A {@code javac} argfile materialised on disk.
16   *
17   * <p>Wraps a list of command-line tokens and writes them to a single
18   * file in {@code javac}'s argfile format — one double-quoted token per
19   * line with backslashes and double quotes escaped — so even very long
20   * classpaths and source lists stay below the Windows
21   * {@code CreateProcess} command-line limit when passed to {@code javac}
22   * as {@code @path}. The {@code -J} launcher flags must NOT be included
23   * here; {@code javac} forbids them inside argfiles.</p>
24   *
25   * @since 1.0
26   */
27  public final class Argfile {
28  
29      /**
30       * Where the argfile will be written.
31       */
32      private final File place;
33  
34      /**
35       * Tokens to write, in order, one per line.
36       */
37      private final List<String> args;
38  
39      /**
40       * Constructor.
41       *
42       * @param place Target file path
43       * @param args Tokens to write
44       */
45      public Argfile(final File place, final List<String> args) {
46          this.place = place;
47          this.args = args;
48      }
49  
50      /**
51       * Write the argfile and return its path.
52       *
53       * @return The path of the just-written argfile
54       */
55      public File save() {
56          final StringBuilder content = new StringBuilder(this.args.size() * 64);
57          for (final String arg : this.args) {
58              content.append('"');
59              for (int idx = 0; idx < arg.length(); idx += 1) {
60                  final char chr = arg.charAt(idx);
61                  if (chr == '\\' || chr == '"') {
62                      content.append('\\');
63                  }
64                  content.append(chr);
65              }
66              content.append('"').append(System.lineSeparator());
67          }
68          try {
69              Files.writeString(
70                  this.place.toPath(),
71                  content.toString(),
72                  StandardCharsets.UTF_8
73              );
74          } catch (final IOException ex) {
75              throw new UncheckedIOException(
76                  String.format("Unable to write argfile %s", this.place), ex
77              );
78          }
79          return this.place;
80      }
81  }