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  		return applyFormatOptions(new ZipArchiveOutputStream(s), o);
51  	}
52  
53  	/** {@inheritDoc} */
54  	@Override
55  	public void putEntry(ArchiveOutputStream out,
56  			ObjectId tree, String path, FileMode mode, ObjectLoader loader)
57  			throws IOException {
58  		// ZipArchiveEntry detects directories by checking
59  		// for '/' at the end of the filename.
60  		if (path.endsWith("/") && mode != FileMode.TREE) //$NON-NLS-1$
61  			throw new IllegalArgumentException(MessageFormat.format(
62  					ArchiveText.get().pathDoesNotMatchMode, path, mode));
63  		if (!path.endsWith("/") && mode == FileMode.TREE) //$NON-NLS-1$
64  			path = path + "/"; //$NON-NLS-1$
65  
66  		final ZipArchiveEntry entry = new ZipArchiveEntry(path);
67  
68  		if (tree instanceof RevCommit) {
69  			long t = ((RevCommit) tree).getCommitTime() * 1000L;
70  			entry.setTime(t);
71  		}
72  
73  		if (mode == FileMode.TREE) {
74  			out.putArchiveEntry(entry);
75  			out.closeArchiveEntry();
76  			return;
77  		}
78  
79  		if (mode == FileMode.REGULAR_FILE) {
80  			// ok
81  		} else if (mode == FileMode.EXECUTABLE_FILE
82  				|| mode == FileMode.SYMLINK) {
83  			entry.setUnixMode(mode.getBits());
84  		} else {
85  			// Unsupported mode (e.g., GITLINK).
86  			throw new IllegalArgumentException(MessageFormat.format(
87  					ArchiveText.get().unsupportedMode, mode));
88  		}
89  		entry.setSize(loader.getSize());
90  		out.putArchiveEntry(entry);
91  		loader.copyTo(out);
92  		out.closeArchiveEntry();
93  	}
94  
95  	/** {@inheritDoc} */
96  	@Override
97  	public Iterable<String> suffixes() {
98  		return SUFFIXES;
99  	}
100 
101 	/** {@inheritDoc} */
102 	@Override
103 	public boolean equals(Object other) {
104 		return (other instanceof ZipFormat);
105 	}
106 
107 	/** {@inheritDoc} */
108 	@Override
109 	public int hashCode() {
110 		return getClass().hashCode();
111 	}
112 }