All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.bloodshura.x.utilities.compactor.JarCompactor Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2013-2018, João Vitor Verona Biazibetti - All Rights Reserved
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see .
 *
 * https://www.github.com/BloodShura
 */

package com.github.bloodshura.x.utilities.compactor;

import com.github.bloodshura.x.collection.map.XMap;
import com.github.bloodshura.x.collection.map.impl.XLinkedMap;
import com.github.bloodshura.x.io.file.File;
import com.github.bloodshura.x.io.file.zip.ZipEntry;
import com.github.bloodshura.x.io.file.zip.ZipFile;
import com.github.bloodshura.x.memory.Bufferer;
import com.github.bloodshura.x.worker.StreamWorker;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.jar.Attributes;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;

public class JarCompactor extends Compactor {
	private final XMap manifest;

	public JarCompactor() {
		this.manifest = new XLinkedMap<>();
	}

	@Override
	public void compact(@Nonnull File output) throws IOException {
		try (OutputStream outStream = output.newOutputStream(); JarOutputStream jarOutStream = new JarOutputStream(outStream, createManifest())) {
			byte[] buffer = new byte[Bufferer.COMMON_SIZE];

			for (File file : getFiles()) {
				if (ZipFile.is(file)) {
					try (ZipFile content = new ZipFile(file)) {
						for (ZipEntry entry : content.getEntries()) {
							String name = entry.getName();

							if (!entry.isDirectory() && !name.toUpperCase().startsWith("META-INF")) {
								// Yes, there is a reason for this \/. 22-10-2015
								// BUT WHAT REASON MTHRFCKR???? 04-02-2016
								// Oh ok. I found the reason. 04-02-2016
								// Apparently, if I re-use the 'entry', in the close() of the JarOutputStream,
								// it will give a Exception saying that got X bytes when it expected Y. (???)
								// Creating a new ZipEntry with the original entry's name works properly.
								// Next time, comment it properly you fucking melancholic piece of shit.
								ZipEntry tempEntry = new ZipEntry(entry.getName());

								try (InputStream input = content.newInputStream(tempEntry)) {
									jarOutStream.putNextEntry(tempEntry.getHandle());
									StreamWorker.write(input, jarOutStream, buffer);
									jarOutStream.closeEntry();
								}
								catch (IOException exception) {
									if (!exception.getMessage().startsWith("duplicate entry")) {
										throw exception;
									}
								}
							}
						}
					}
				}
				else {
					throw new IOException("File \"" + file.getPath() + "\" is not a valid ZIP file");
				}
			}

			for (ContentEntry entry : getEntries()) {
				try (InputStream input = entry.newInputStream()) {
					jarOutStream.putNextEntry(new ZipEntry(entry.getName()).getHandle());
					StreamWorker.write(input, jarOutStream, buffer);
					jarOutStream.closeEntry();
				}
				catch (IOException exception) {
					if (!exception.getMessage().startsWith("duplicate entry")) {
						throw exception;
					}
				}
			}
		}
	}

	@Nonnull
	public XMap getManifest() {
		return manifest;
	}

	@Nonnull
	protected Manifest createManifest() {
		Manifest manifest = new Manifest();
		Attributes attributes = manifest.getMainAttributes();

		attributes.putValue("Manifest-Version", "1.0");
		getManifest().forEach(pair -> attributes.putValue(pair.getLeft(), pair.getRight()));

		return manifest;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy