Writes a map to an archive. @param compress Enable zip compression. @param output File location of jar. @param content Contents to write to location. @throws IOException When the jar file cannot be written to.
(boolean compress, File output, Map<String, byte[]> content)
| 137 | * When the jar file cannot be written to. |
| 138 | */ |
| 139 | public static void writeArchive(boolean compress, File output, Map<String, byte[]> content) throws IOException { |
| 140 | String extension = IOUtil.getExtension(output.toPath()); |
| 141 | // Use buffered streams, reduce overall file write operations |
| 142 | OutputStream os = new BufferedOutputStream(Files.newOutputStream(output.toPath()), 1048576); |
| 143 | try (ZipOutputStream jos = ("zip".equals(extension)) ? new ZipOutputStream(os) : |
| 144 | /* Let's assume it's a jar */ new JarOutputStream(os)) { |
| 145 | VMUtil.patchZipOutput(jos); |
| 146 | PluginsManager pluginsManager = PluginsManager.getInstance(); |
| 147 | Set<String> dirsVisited = new HashSet<>(); |
| 148 | // Contents is iterated in sorted order (because 'archiveContent' is TreeMap). |
| 149 | // This allows us to insert directory entries before file entries of that directory occur. |
| 150 | CRC32 crc = new CRC32(); |
| 151 | for (Map.Entry<String, byte[]> entry : content.entrySet()) { |
| 152 | String key = entry.getKey(); |
| 153 | byte[] out = entry.getValue(); |
| 154 | for (ExportInterceptorPlugin interceptor : pluginsManager.ofType(ExportInterceptorPlugin.class)) { |
| 155 | out = interceptor.intercept(key, out); |
| 156 | } |
| 157 | // Write directories for upcoming entries if necessary |
| 158 | // - Ugly, but does the job. |
| 159 | if (key.contains("/")) { |
| 160 | // Record directories |
| 161 | String parent = key; |
| 162 | List<String> toAdd = new ArrayList<>(); |
| 163 | do { |
| 164 | parent = parent.substring(0, parent.lastIndexOf('/')); |
| 165 | if (dirsVisited.add(parent)) { |
| 166 | toAdd.add(0, parent + '/'); |
| 167 | } else break; |
| 168 | } while (parent.contains("/")); |
| 169 | // Put directories in order of depth |
| 170 | for (String dir : toAdd) { |
| 171 | jos.putNextEntry(new JarEntry(dir)); |
| 172 | jos.closeEntry(); |
| 173 | } |
| 174 | } |
| 175 | // Write entry content |
| 176 | crc.reset(); |
| 177 | crc.update(out, 0, out.length); |
| 178 | JarEntry outEntry = new JarEntry(key); |
| 179 | outEntry.setMethod(compress ? ZipEntry.DEFLATED : ZipEntry.STORED); |
| 180 | if (!compress) { |
| 181 | outEntry.setSize(out.length); |
| 182 | outEntry.setCompressedSize(out.length); |
| 183 | } |
| 184 | outEntry.setCrc(crc.getValue()); |
| 185 | jos.putNextEntry(outEntry); |
| 186 | jos.write(out); |
| 187 | jos.closeEntry(); |
| 188 | } |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | private void put(Map<String, byte[]> content, JavaResource res) { |
| 193 | content.putAll(res.getFiles()); |
no test coverage detected