View Javadoc
1   /*
2    * Copyright (C) 2012 Google Inc. and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  package org.eclipse.jgit.archive;
11  
12  import java.io.IOException;
13  import java.io.OutputStream;
14  import java.text.MessageFormat;
15  import java.util.Arrays;
16  import java.util.Collections;
17  import java.util.List;
18  import java.util.Map;
19  
20  import org.apache.commons.compress.archivers.ArchiveOutputStream;
21  import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
22  import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
23  import org.eclipse.jgit.api.ArchiveCommand;
24  import org.eclipse.jgit.archive.internal.ArchiveText;
25  import org.eclipse.jgit.lib.FileMode;
26  import org.eclipse.jgit.lib.ObjectId;
27  import org.eclipse.jgit.lib.ObjectLoader;
28  import org.eclipse.jgit.revwalk.RevCommit;
29  
30  /**
31   * PKWARE's ZIP format.
32   */
33  public final class ZipFormat extends BaseFormat implements
34  		ArchiveCommand.Format<ArchiveOutputStream> {
35  	private static final List<String> SUFFIXES = Collections
36  			.unmodifiableList(Arrays.asList(".zip")); //$NON-NLS-1$
37  
38  	/** {@inheritDoc} */
39  	@Override
40  	public ArchiveOutputStream createArchiveOutputStream(OutputStream s)
41  			throws IOException {
42  		return createArchiveOutputStream(s,
43  				Collections.<String, Object> emptyMap());
44  	}
45  
46  	/** {@inheritDoc} */
47  	@Override
48  	public ArchiveOutputStream createArchiveOutputStream(OutputStream s,
49  			Map<String, Object> o) throws IOException {
50  		ZipArchiveOutputStream out = new ZipArchiveOutputStream(s);
51  		int compressionLevel = getCompressionLevel(o);
52  		if (compressionLevel != -1) {
53  			out.setLevel(compressionLevel);
54  		}
55  		return applyFormatOptions(out, o);
56  	}
57  
58  	/** {@inheritDoc} */
59  	@Override
60  	public void putEntry(ArchiveOutputStream out,
61  			ObjectId tree, String path, FileMode mode, ObjectLoader loader)
62  			throws IOException {
63  		// ZipArchiveEntry detects directories by checking
64  		// for '/' at the end of the filename.
65  		if (path.endsWith("/") && mode != FileMode.TREE) //$NON-NLS-1$
66  			throw new IllegalArgumentException(MessageFormat.format(
67  					ArchiveText.get().pathDoesNotMatchMode, path, mode));
68  		if (!path.endsWith("/") && mode == FileMode.TREE) //$NON-NLS-1$
69  			path = path + "/"; //$NON-NLS-1$
70  
71  		final ZipArchiveEntry entry = new ZipArchiveEntry(path);
72  
73  		if (tree instanceof RevCommit) {
74  			long t = ((RevCommit) tree).getCommitTime() * 1000L;
75  			entry.setTime(t);
76  		}
77  
78  		if (mode == FileMode.TREE) {
79  			out.putArchiveEntry(entry);
80  			out.closeArchiveEntry();
81  			return;
82  		}
83  
84  		if (mode == FileMode.REGULAR_FILE) {
85  			// ok
86  		} else if (mode == FileMode.EXECUTABLE_FILE
87  				|| mode == FileMode.SYMLINK) {
88  			entry.setUnixMode(mode.getBits());
89  		} else {
90  			// Unsupported mode (e.g., GITLINK).
91  			throw new IllegalArgumentException(MessageFormat.format(
92  					ArchiveText.get().unsupportedMode, mode));
93  		}
94  		entry.setSize(loader.getSize());
95  		out.putArchiveEntry(entry);
96  		loader.copyTo(out);
97  		out.closeArchiveEntry();
98  	}
99  
100 	/** {@inheritDoc} */
101 	@Override
102 	public Iterable<String> suffixes() {
103 		return SUFFIXES;
104 	}
105 
106 	/** {@inheritDoc} */
107 	@Override
108 	public boolean equals(Object other) {
109 		return (other instanceof ZipFormat);
110 	}
111 
112 	/** {@inheritDoc} */
113 	@Override
114 	public int hashCode() {
115 		return getClass().hashCode();
116 	}
117 }