1 /*******************************************************************************
2  * Copyright (c) 2000, 2015 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.ui.internal.wizards.datatransfer;
15 
16 import java.io.FileOutputStream;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.util.zip.CRC32;
20 import java.util.zip.ZipEntry;
21 import java.util.zip.ZipOutputStream;
22 
23 import org.eclipse.core.resources.IContainer;
24 import org.eclipse.core.resources.IFile;
25 import org.eclipse.core.resources.IResource;
26 import org.eclipse.core.runtime.CoreException;
27 
28 
29 /**
30  *	Exports resources to a .zip file
31  */
32 public class ZipFileExporter implements IFileExporter {
33 	private ZipOutputStream outputStream;
34 
35 	private boolean useCompression = true;
36 
37 	private boolean resolveLinks;
38 
39 	/**
40 	 * Create an instance of this class.
41 	 *
42 	 * @param filename
43 	 *            java.lang.String
44 	 * @param compress
45 	 *            boolean
46 	 * @param resolveLinks
47 	 *            boolean
48 	 * @exception java.io.IOException
49 	 */
ZipFileExporter(String filename, boolean compress, boolean resolveLinks)50 	public ZipFileExporter(String filename, boolean compress, boolean resolveLinks) throws IOException {
51 		this.resolveLinks = resolveLinks;
52 		outputStream = new ZipOutputStream(new FileOutputStream(filename));
53 		useCompression = compress;
54 	}
55 
56 	/**
57 	 *	Do all required cleanup now that we're finished with the
58 	 *	currently-open .zip
59 	 *
60 	 *	@exception java.io.IOException
61 	 */
62 	@Override
finished()63 	public void finished() throws IOException {
64 		outputStream.close();
65 	}
66 
67 	/**
68 	 *	Write the contents of the file to the tar archive.
69 	 *
70 	 *	@param entry
71 	 *	@param contents
72 	 *  @exception java.io.IOException
73 	 *  @exception org.eclipse.core.runtime.CoreException
74 	 */
write(ZipEntry entry, IFile contents)75 	private void write(ZipEntry entry, IFile contents) throws IOException, CoreException {
76 		byte[] readBuffer = new byte[4096];
77 
78 		// If the contents are being compressed then we get the below for free.
79 		if (!useCompression) {
80 			entry.setMethod(ZipEntry.STORED);
81 			InputStream contentStream = contents.getContents(false);
82 			int length = 0;
83 			CRC32 checksumCalculator = new CRC32();
84 			try {
85 				int n;
86 				while ((n = contentStream.read(readBuffer)) > 0) {
87 					checksumCalculator.update(readBuffer, 0, n);
88 					length += n;
89 				}
90 			} finally {
91 				if (contentStream != null) {
92 					contentStream.close();
93 				}
94 			}
95 
96 			entry.setSize(length);
97 			entry.setCrc(checksumCalculator.getValue());
98 		}
99 
100 		// set the timestamp
101 		long localTimeStamp = contents.getLocalTimeStamp();
102 		if(localTimeStamp != IResource.NULL_STAMP)
103 			entry.setTime(localTimeStamp);
104 
105 		outputStream.putNextEntry(entry);
106 		try (InputStream contentStream = contents.getContents(false)) {
107 			int n;
108 			while ((n = contentStream.read(readBuffer)) > 0) {
109 				outputStream.write(readBuffer, 0, n);
110 			}
111 		}
112 		outputStream.closeEntry();
113 	}
114 
115 	@Override
write(IContainer container, String destinationPath)116 	public void write(IContainer container, String destinationPath)
117 			throws IOException {
118 		if (!resolveLinks && container.isLinked(IResource.DEPTH_INFINITE)) {
119 			return;
120 		}
121 		ZipEntry newEntry = new ZipEntry(destinationPath);
122 		outputStream.putNextEntry(newEntry);
123 	}
124 
125 	/**
126 	 *  Write the passed resource to the current archive.
127 	 *
128 	 *  @param resource org.eclipse.core.resources.IFile
129 	 *  @param destinationPath java.lang.String
130 	 *  @exception java.io.IOException
131 	 *  @exception org.eclipse.core.runtime.CoreException
132 	 */
133 	@Override
write(IFile resource, String destinationPath)134 	public void write(IFile resource, String destinationPath)
135 			throws IOException, CoreException {
136 		if (!resolveLinks && resource.isLinked(IResource.DEPTH_INFINITE)) {
137 			return;
138 		}
139 		ZipEntry newEntry = new ZipEntry(destinationPath);
140 		write(newEntry, resource);
141 	}
142 }
143