blob: 148828ca871e9cefaeb9632ad22933870f4e69cf [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017 SSI Schaefer IT Solutions GmbH and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SSI Schaefer IT Solutions GmbH
*******************************************************************************/
package org.eclipse.tea.library.build.jar;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import org.eclipse.tea.core.services.TaskingLog;
import org.eclipse.tea.library.build.util.FileUtils;
import com.google.common.base.Splitter;
/**
* ZipExec implementation which calls the JRE ZIP library.
*/
public class InternalZipExec extends BaseZipExec {
private final byte[] BUFFER = new byte[10240];
private final TaskingLog log;
public InternalZipExec(TaskingLog log) {
this.log = log;
}
@Override
protected void doCreateZip() {
try {
FileOutputStream fos = new FileOutputStream(zipFile);
ZipOutputStream zos = new ZipOutputStream(fos);
try {
Map<ZipEntry, File> entries = new TreeMap<>((a, b) -> a.getName().compareTo(b.getName()));
for (ZipExecPart part : parts) {
addZip(part, entries);
}
write(zos, entries);
} finally {
zos.close();
}
} catch (IOException e) {
throw new IllegalStateException("cannot create " + zipFile, e);
}
}
private void addZip(ZipExecPart part, Map<ZipEntry, File> entries) {
for (String relPath : part.relativePaths) {
if (".".equals(relPath)) {
addEntry(part, entries, part.sourceDirectory, null);
} else {
File source = new File(part.sourceDirectory, relPath);
addEntry(part, entries, source, relPath);
}
}
}
private void addEntry(ZipExecPart part, Map<ZipEntry, File> entries, File source, String entryName) {
if (!source.exists()) {
// requested input does not exist. this is worth a warning only.
// command line zip ignores it completely.
log.warn("ZIP input " + source + " does not exist");
return;
}
if (source.isDirectory()) {
if (entryName != null) {
int lastIndex = entryName.length() - 1;
if (entryName.charAt(lastIndex) == '/') {
entryName = entryName.substring(0, lastIndex);
}
}
String[] children = source.list();
Arrays.sort(children);
for (String childName : children) {
if (part.excludeGit) {
if (GITIGNORE.equals(childName)) {
continue;
}
}
File child = new File(source, childName);
if (entryName == null) {
addEntry(part, entries, child, childName);
} else {
addEntry(part, entries, child, entryName + '/' + childName);
}
}
return;
}
// add file
ZipEntry ze = new ZipEntry(entryName);
try {
BasicFileAttributes attr = Files.readAttributes(source.toPath(), BasicFileAttributes.class);
if (!isJar) {
ze.setLastModifiedTime(attr.lastModifiedTime());
ze.setLastAccessTime(attr.lastAccessTime());
ze.setCreationTime(attr.creationTime());
} else {
ze.setLastModifiedTime(FileTime.fromMillis(0));
ze.setLastAccessTime(FileTime.fromMillis(0));
ze.setCreationTime(FileTime.fromMillis(0));
}
} catch (Exception e) {
System.out.println("cannot apply source file timestamps");
}
entries.put(ze, source);
}
private void write(ZipOutputStream zos, Map<ZipEntry, File> entries) {
// sort entries, create entries for directories
entries.keySet().stream().sorted((a, b) -> a.getName().compareTo(b.getName())).forEach((e) -> {
List<String> segments = Splitter.on('/').splitToList(e.getName());
if (segments.size() > 1) {
String rel = null;
for (int i = 0; i < segments.size() - 1; ++i) {
String seg = segments.get(i);
if (rel == null) {
rel = seg + "/";
} else {
rel = rel + seg + "/";
}
ZipEntry de = new ZipEntry(rel);
if (!isJar) {
de.setTime(System.currentTimeMillis());
} else {
de.setLastModifiedTime(FileTime.fromMillis(0));
de.setLastAccessTime(FileTime.fromMillis(0));
de.setCreationTime(FileTime.fromMillis(0));
}
entries.put(de, null);
}
}
});
for (Entry<ZipEntry, File> ze : entries.entrySet()) {
try {
zos.putNextEntry(ze.getKey());
if (!ze.getKey().isDirectory()) {
FileInputStream fis = new FileInputStream(ze.getValue());
try {
int count;
while ((count = fis.read(BUFFER)) >= 0) {
zos.write(BUFFER, 0, count);
}
} finally {
fis.close();
}
}
zos.closeEntry();
} catch (Exception e) {
throw new IllegalStateException("cannot add " + ze.getValue(), e);
}
}
}
/**
* Extracts a ZIP file
*
* @param zipFile
* the ZIP file
* @param destDir
* the destination directory
*/
@Override
public void unzip(File zipFile, File destDir) throws IOException {
try (ZipFile file = new ZipFile(zipFile)) {
Enumeration<? extends ZipEntry> entries = file.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
File realFile = new File(destDir, entry.getName());
if (entry.isDirectory()) {
FileUtils.mkdirs(realFile);
continue;
}
FileUtils.mkdirs(realFile.getParentFile());
try (InputStream is = file.getInputStream(entry);
FileOutputStream os = new FileOutputStream(realFile)) {
int i;
while ((i = is.read(BUFFER)) != -1) {
os.write(BUFFER, 0, i);
}
}
}
}
}
}