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       * @param place Target file path
42       * @param args Tokens to write
43       */
44      public Argfile(final File place, final List<String> args) {
45          this.place = place;
46          this.args = args;
47      }
48  
49      /**
50       * Write the argfile and return its path.
51       * @return The path of the just-written argfile
52       */
53      public File save() {
54          final StringBuilder content = new StringBuilder(this.args.size() * 64);
55          for (final String arg : this.args) {
56              content.append('"');
57              for (int idx = 0; idx < arg.length(); idx += 1) {
58                  final char chr = arg.charAt(idx);
59                  if (chr == '\\' || chr == '"') {
60                      content.append('\\');
61                  }
62                  content.append(chr);
63              }
64              content.append('"').append(System.lineSeparator());
65          }
66          try {
67              Files.writeString(
68                  this.place.toPath(),
69                  content.toString(),
70                  StandardCharsets.UTF_8
71              );
72          } catch (final IOException ex) {
73              throw new UncheckedIOException(
74                  String.format("Unable to write argfile %s", this.place), ex
75              );
76          }
77          return this.place;
78      }
79  }