|
17 | 17 |
|
18 | 18 | import java.io.IOException; |
19 | 19 | import java.io.InputStream; |
| 20 | +import java.io.OutputStream; |
| 21 | +import java.nio.ByteBuffer; |
| 22 | +import java.nio.charset.StandardCharsets; |
20 | 23 | import java.nio.file.Files; |
21 | 24 | import java.nio.file.NoSuchFileException; |
22 | 25 | import java.nio.file.Path; |
| 26 | +import java.nio.file.StandardCopyOption; |
23 | 27 | import java.util.HashMap; |
24 | 28 | import java.util.LinkedHashSet; |
25 | 29 | import java.util.List; |
26 | 30 | import java.util.Map; |
| 31 | +import java.util.concurrent.ThreadLocalRandom; |
27 | 32 |
|
| 33 | +import org.codehaus.plexus.components.secdispatcher.SecDispatcher; |
28 | 34 | import org.codehaus.plexus.components.secdispatcher.SecDispatcherException; |
29 | 35 | import org.codehaus.plexus.components.secdispatcher.model.Config; |
30 | 36 | import org.codehaus.plexus.components.secdispatcher.model.ConfigProperty; |
31 | 37 | import org.codehaus.plexus.components.secdispatcher.model.SettingsSecurity; |
32 | 38 | import org.codehaus.plexus.components.secdispatcher.model.io.stax.SecurityConfigurationStaxReader; |
| 39 | +import org.codehaus.plexus.components.secdispatcher.model.io.stax.SecurityConfigurationStaxWriter; |
33 | 40 |
|
34 | 41 | import static java.util.Objects.requireNonNull; |
35 | 42 |
|
@@ -102,4 +109,64 @@ public static Map<String, String> getConfig(SettingsSecurity sec, String name) { |
102 | 109 | } |
103 | 110 | return null; |
104 | 111 | } |
| 112 | + |
| 113 | + public static void write(Path target, SettingsSecurity configuration) throws IOException { |
| 114 | + requireNonNull(target, "file must not be null"); |
| 115 | + requireNonNull(configuration, "sec must not be null"); |
| 116 | + configuration.setModelVersion(SecDispatcher.class.getPackage().getImplementationVersion()); |
| 117 | + configuration.setModelEncoding(StandardCharsets.UTF_8.name()); |
| 118 | + writeFile(target, configuration, false); |
| 119 | + } |
| 120 | + |
| 121 | + public static void writeWithBackup(Path target, SettingsSecurity configuration) throws IOException { |
| 122 | + requireNonNull(target, "file must not be null"); |
| 123 | + requireNonNull(configuration, "sec must not be null"); |
| 124 | + configuration.setModelVersion(SecDispatcher.class.getPackage().getImplementationVersion()); |
| 125 | + configuration.setModelEncoding(StandardCharsets.UTF_8.name()); |
| 126 | + writeFile(target, configuration, true); |
| 127 | + } |
| 128 | + |
| 129 | + private static final boolean IS_WINDOWS = |
| 130 | + System.getProperty("os.name", "unknown").startsWith("Windows"); |
| 131 | + |
| 132 | + private static void writeFile(Path target, SettingsSecurity configuration, boolean doBackup) throws IOException { |
| 133 | + requireNonNull(target, "target is null"); |
| 134 | + Path parent = requireNonNull(target.getParent(), "target must have parent"); |
| 135 | + Files.createDirectories(parent); |
| 136 | + Path tempFile = parent.resolve(target.getFileName() + "." |
| 137 | + + Long.toUnsignedString(ThreadLocalRandom.current().nextLong()) + ".tmp"); |
| 138 | + try (OutputStream out = Files.newOutputStream(tempFile)) { |
| 139 | + new SecurityConfigurationStaxWriter().write(out, configuration); |
| 140 | + if (doBackup && Files.isRegularFile(target)) { |
| 141 | + Files.copy(target, parent.resolve(target.getFileName() + ".bak"), StandardCopyOption.REPLACE_EXISTING); |
| 142 | + } |
| 143 | + if (IS_WINDOWS) { |
| 144 | + copy(tempFile, target); |
| 145 | + } else { |
| 146 | + Files.move(tempFile, target, StandardCopyOption.REPLACE_EXISTING); |
| 147 | + } |
| 148 | + } catch (XMLStreamException e) { |
| 149 | + throw new IOException("XML Processing error", e); |
| 150 | + } finally { |
| 151 | + Files.deleteIfExists(tempFile); |
| 152 | + } |
| 153 | + } |
| 154 | + |
| 155 | + /** |
| 156 | + * On Windows we use pre-NIO2 way to copy files, as for some reason it works. Beat me why. |
| 157 | + */ |
| 158 | + private static void copy(Path source, Path target) throws IOException { |
| 159 | + ByteBuffer buffer = ByteBuffer.allocate(1024 * 32); |
| 160 | + byte[] array = buffer.array(); |
| 161 | + try (InputStream is = Files.newInputStream(source); |
| 162 | + OutputStream os = Files.newOutputStream(target)) { |
| 163 | + while (true) { |
| 164 | + int bytes = is.read(array); |
| 165 | + if (bytes < 0) { |
| 166 | + break; |
| 167 | + } |
| 168 | + os.write(array, 0, bytes); |
| 169 | + } |
| 170 | + } |
| 171 | + } |
105 | 172 | } |
0 commit comments