xref: /JGit/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ZipFormat.java (revision 6f82690aaf2be783be6d77f0903788ff0832472a)
156276d05SJonathan Nieder /*
25c5f7c6bSMatthias Sohn  * Copyright (C) 2012 Google Inc. and others
356276d05SJonathan Nieder  *
45c5f7c6bSMatthias Sohn  * This program and the accompanying materials are made available under the
55c5f7c6bSMatthias Sohn  * terms of the Eclipse Distribution License v. 1.0 which is available at
65c5f7c6bSMatthias Sohn  * https://www.eclipse.org/org/documents/edl-v10.php.
756276d05SJonathan Nieder  *
85c5f7c6bSMatthias Sohn  * SPDX-License-Identifier: BSD-3-Clause
956276d05SJonathan Nieder  */
1056276d05SJonathan Nieder package org.eclipse.jgit.archive;
1156276d05SJonathan Nieder 
1256276d05SJonathan Nieder import java.io.IOException;
1356276d05SJonathan Nieder import java.io.OutputStream;
142ecc27dbSJonathan Nieder import java.text.MessageFormat;
1556cb2d92SJonathan Nieder import java.util.Arrays;
1656cb2d92SJonathan Nieder import java.util.Collections;
1756cb2d92SJonathan Nieder import java.util.List;
18c0c4c6f0SDavid Ostrovsky import java.util.Map;
1956276d05SJonathan Nieder 
2056276d05SJonathan Nieder import org.apache.commons.compress.archivers.ArchiveOutputStream;
2156276d05SJonathan Nieder import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
2256276d05SJonathan Nieder import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
2356276d05SJonathan Nieder import org.eclipse.jgit.api.ArchiveCommand;
242ecc27dbSJonathan Nieder import org.eclipse.jgit.archive.internal.ArchiveText;
2556276d05SJonathan Nieder import org.eclipse.jgit.lib.FileMode;
261448ec37SNaoki Takezoe import org.eclipse.jgit.lib.ObjectId;
2756276d05SJonathan Nieder import org.eclipse.jgit.lib.ObjectLoader;
281448ec37SNaoki Takezoe import org.eclipse.jgit.revwalk.RevCommit;
2956276d05SJonathan Nieder 
30659cadf0SJonathan Nieder /**
31659cadf0SJonathan Nieder  * PKWARE's ZIP format.
32659cadf0SJonathan Nieder  */
33c0c4c6f0SDavid Ostrovsky public final class ZipFormat extends BaseFormat implements
34c0c4c6f0SDavid Ostrovsky 		ArchiveCommand.Format<ArchiveOutputStream> {
354ceb25b6SRobin Rosenberg 	private static final List<String> SUFFIXES = Collections
364ceb25b6SRobin Rosenberg 			.unmodifiableList(Arrays.asList(".zip")); //$NON-NLS-1$
3756cb2d92SJonathan Nieder 
3832022e97SMatthias Sohn 	/** {@inheritDoc} */
3930628e3bSMatthias Sohn 	@Override
createArchiveOutputStream(OutputStream s)40c0c4c6f0SDavid Ostrovsky 	public ArchiveOutputStream createArchiveOutputStream(OutputStream s)
41c0c4c6f0SDavid Ostrovsky 			throws IOException {
42c0c4c6f0SDavid Ostrovsky 		return createArchiveOutputStream(s,
43c0c4c6f0SDavid Ostrovsky 				Collections.<String, Object> emptyMap());
44c0c4c6f0SDavid Ostrovsky 	}
45c0c4c6f0SDavid Ostrovsky 
4632022e97SMatthias Sohn 	/** {@inheritDoc} */
4730628e3bSMatthias Sohn 	@Override
createArchiveOutputStream(OutputStream s, Map<String, Object> o)48c0c4c6f0SDavid Ostrovsky 	public ArchiveOutputStream createArchiveOutputStream(OutputStream s,
49c0c4c6f0SDavid Ostrovsky 			Map<String, Object> o) throws IOException {
50*6f82690aSYoussef Elghareeb 		ZipArchiveOutputStream out = new ZipArchiveOutputStream(s);
51*6f82690aSYoussef Elghareeb 		int compressionLevel = getCompressionLevel(o);
52*6f82690aSYoussef Elghareeb 		if (compressionLevel != -1) {
53*6f82690aSYoussef Elghareeb 			out.setLevel(compressionLevel);
54*6f82690aSYoussef Elghareeb 		}
55*6f82690aSYoussef Elghareeb 		return applyFormatOptions(out, o);
5656276d05SJonathan Nieder 	}
5756276d05SJonathan Nieder 
5832022e97SMatthias Sohn 	/** {@inheritDoc} */
591448ec37SNaoki Takezoe 	@Override
putEntry(ArchiveOutputStream out, ObjectId tree, String path, FileMode mode, ObjectLoader loader)601448ec37SNaoki Takezoe 	public void putEntry(ArchiveOutputStream out,
611448ec37SNaoki Takezoe 			ObjectId tree, String path, FileMode mode, ObjectLoader loader)
621448ec37SNaoki Takezoe 			throws IOException {
632ecc27dbSJonathan Nieder 		// ZipArchiveEntry detects directories by checking
642ecc27dbSJonathan Nieder 		// for '/' at the end of the filename.
650bc98f17SRobin Rosenberg 		if (path.endsWith("/") && mode != FileMode.TREE) //$NON-NLS-1$
662ecc27dbSJonathan Nieder 			throw new IllegalArgumentException(MessageFormat.format(
672ecc27dbSJonathan Nieder 					ArchiveText.get().pathDoesNotMatchMode, path, mode));
680bc98f17SRobin Rosenberg 		if (!path.endsWith("/") && mode == FileMode.TREE) //$NON-NLS-1$
690bc98f17SRobin Rosenberg 			path = path + "/"; //$NON-NLS-1$
702ecc27dbSJonathan Nieder 
7156276d05SJonathan Nieder 		final ZipArchiveEntry entry = new ZipArchiveEntry(path);
721448ec37SNaoki Takezoe 
731448ec37SNaoki Takezoe 		if (tree instanceof RevCommit) {
74ff6e6c22SShawn Pearce 			long t = ((RevCommit) tree).getCommitTime() * 1000L;
75ff6e6c22SShawn Pearce 			entry.setTime(t);
761448ec37SNaoki Takezoe 		}
771448ec37SNaoki Takezoe 
782ecc27dbSJonathan Nieder 		if (mode == FileMode.TREE) {
792ecc27dbSJonathan Nieder 			out.putArchiveEntry(entry);
802ecc27dbSJonathan Nieder 			out.closeArchiveEntry();
812ecc27dbSJonathan Nieder 			return;
822ecc27dbSJonathan Nieder 		}
8356276d05SJonathan Nieder 
8456276d05SJonathan Nieder 		if (mode == FileMode.REGULAR_FILE) {
8556276d05SJonathan Nieder 			// ok
8656276d05SJonathan Nieder 		} else if (mode == FileMode.EXECUTABLE_FILE
8756276d05SJonathan Nieder 				|| mode == FileMode.SYMLINK) {
8856276d05SJonathan Nieder 			entry.setUnixMode(mode.getBits());
8956276d05SJonathan Nieder 		} else {
902ecc27dbSJonathan Nieder 			// Unsupported mode (e.g., GITLINK).
912ecc27dbSJonathan Nieder 			throw new IllegalArgumentException(MessageFormat.format(
922ecc27dbSJonathan Nieder 					ArchiveText.get().unsupportedMode, mode));
9356276d05SJonathan Nieder 		}
9456276d05SJonathan Nieder 		entry.setSize(loader.getSize());
9556276d05SJonathan Nieder 		out.putArchiveEntry(entry);
9656276d05SJonathan Nieder 		loader.copyTo(out);
9756276d05SJonathan Nieder 		out.closeArchiveEntry();
9856276d05SJonathan Nieder 	}
9956cb2d92SJonathan Nieder 
10032022e97SMatthias Sohn 	/** {@inheritDoc} */
10130628e3bSMatthias Sohn 	@Override
suffixes()10256cb2d92SJonathan Nieder 	public Iterable<String> suffixes() {
10356cb2d92SJonathan Nieder 		return SUFFIXES;
10456cb2d92SJonathan Nieder 	}
1050a14909bSJonathan Nieder 
10632022e97SMatthias Sohn 	/** {@inheritDoc} */
1070a14909bSJonathan Nieder 	@Override
equals(Object other)1080a14909bSJonathan Nieder 	public boolean equals(Object other) {
1090a14909bSJonathan Nieder 		return (other instanceof ZipFormat);
1100a14909bSJonathan Nieder 	}
1110a14909bSJonathan Nieder 
11232022e97SMatthias Sohn 	/** {@inheritDoc} */
1130a14909bSJonathan Nieder 	@Override
hashCode()1140a14909bSJonathan Nieder 	public int hashCode() {
1150a14909bSJonathan Nieder 		return getClass().hashCode();
1160a14909bSJonathan Nieder 	}
11756276d05SJonathan Nieder }
118