blob: 3242b1c9a4efe623d05a461f074f39753892dde5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM - Initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.internal.p2.jarprocessor;
import java.io.*;
import java.util.*;
import java.util.zip.*;
import org.eclipse.internal.provisional.equinox.p2.jarprocessor.JarProcessor;
import org.eclipse.internal.provisional.equinox.p2.jarprocessor.JarProcessorExecutor;
public class ZipProcessor {
private JarProcessorExecutor executor = null;
private JarProcessorExecutor.Options options = null;
private String workingDirectory = null;
private Properties properties = null;
private Set<String> packExclusions = null;
private Set<String> signExclusions = null;
public void setExecutor(JarProcessorExecutor executor) {
this.executor = executor;
}
public void setOptions(JarProcessorExecutor.Options options) {
this.options = options;
}
public void setWorkingDirectory(String dir) {
workingDirectory = dir;
}
public String getWorkingDirectory() {
if (workingDirectory == null)
workingDirectory = "."; //$NON-NLS-1$
return workingDirectory;
}
@SuppressWarnings("removal")
private boolean repacking() {
return options.repack || (options.pack && options.signCommand != null);
}
@SuppressWarnings("removal")
public void processZip(File zipFile) throws ZipException, IOException {
if (options.verbose)
System.out.println("Processing " + zipFile.getPath()); //$NON-NLS-1$
try (ZipFile zip = new ZipFile(zipFile)) {
initialize(zip);
String extension = options.unpack ? "pack.gz" : ".jar"; //$NON-NLS-1$ //$NON-NLS-2$
File tempDir = new File(getWorkingDirectory(), "temp_" + zipFile.getName()); //$NON-NLS-1$
JarProcessor processor = new JarProcessor();
processor.setVerbose(options.verbose);
processor.setProcessAll(options.processAll);
processor.setWorkingDirectory(tempDir.getCanonicalPath());
if (options.unpack) {
executor.addPackUnpackStep(processor, properties, options);
}
File outputFile = new File(getWorkingDirectory(), zipFile.getName() + ".temp"); //$NON-NLS-1$
File parent = outputFile.getParentFile();
if (!parent.exists())
parent.mkdirs();
try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(outputFile))) {
Enumeration<? extends ZipEntry> entries = zip.entries();
if (entries.hasMoreElements()) {
for (ZipEntry entry = entries.nextElement(); entry != null; entry = entries.hasMoreElements()
? (ZipEntry) entries.nextElement()
: null) {
String name = entry.getName();
InputStream entryStream = zip.getInputStream(entry);
boolean pack = options.pack && !packExclusions.contains(name);
boolean sign = options.signCommand != null && !signExclusions.contains(name);
boolean repack = repacking() && !packExclusions.contains(name);
File extractedFile = null;
if (entry.getName().endsWith(extension) && (pack || sign || repack || options.unpack)) {
extractedFile = createSubPathFile(tempDir, name);
parent = extractedFile.getParentFile();
if (!parent.exists())
parent.mkdirs();
if (options.verbose)
System.out.println("Extracting " + entry.getName()); //$NON-NLS-1$
FileOutputStream extracted = new FileOutputStream(extractedFile);
Utils.transferStreams(entryStream, extracted, true); // this will close the stream
entryStream = null;
boolean skip = Utils.shouldSkipJar(extractedFile, options.processAll, options.verbose);
if (skip) {
// skipping this file
entryStream = new FileInputStream(extractedFile);
if (options.verbose)
System.out.println(entry.getName() + " is not marked, skipping."); //$NON-NLS-1$
} else {
if (options.unpack) {
File result = processor.processJar(extractedFile);
name = name.substring(0, name.length() - extractedFile.getName().length())
+ result.getName();
extractedFile = result;
} else {
if (repack || sign) {
processor.clearProcessSteps();
if (repack)
executor.addPackUnpackStep(processor, properties, options);
if (sign)
executor.addSignStep(processor, properties, options);
extractedFile = processor.processJar(extractedFile);
}
if (pack) {
processor.clearProcessSteps();
executor.addPackStep(processor, properties, options);
File modifiedFile = processor.processJar(extractedFile);
if (modifiedFile.exists()) {
try {
String newName = name.substring(0,
name.length() - extractedFile.getName().length())
+ modifiedFile.getName();
if (options.verbose) {
System.out.println(
"Adding " + newName + " to " + outputFile.getPath()); //$NON-NLS-1$ //$NON-NLS-2$
System.out.println();
}
ZipEntry zipEntry = new ZipEntry(newName);
entryStream = new FileInputStream(modifiedFile);
zipOut.putNextEntry(zipEntry);
Utils.transferStreams(entryStream, zipOut, false); // we want to keep
// zipOut open
entryStream.close();
Utils.clear(modifiedFile);
} catch (IOException e) {
Utils.close(entryStream);
if (options.verbose) {
e.printStackTrace();
System.out.println(
"Warning: Problem reading " + modifiedFile.getPath() + "."); //$NON-NLS-1$//$NON-NLS-2$
}
}
entryStream = null;
} else if (options.verbose) {
System.out.println("Warning: " + modifiedFile.getPath() + " not found."); //$NON-NLS-1$//$NON-NLS-2$
}
}
}
if (extractedFile.exists()) {
try {
entryStream = new FileInputStream(extractedFile);
} catch (IOException e) {
if (options.verbose) {
e.printStackTrace();
System.out.println(
"Warning: Problem reading " + extractedFile.getPath() + "."); //$NON-NLS-1$//$NON-NLS-2$
}
}
}
if (options.verbose && entryStream != null) {
System.out.println("Adding " + name + " to " + outputFile.getPath()); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
if (entryStream != null) {
ZipEntry newEntry = new ZipEntry(name);
try {
zipOut.putNextEntry(newEntry);
Utils.transferStreams(entryStream, zipOut, false);
zipOut.closeEntry();
} catch (ZipException e) {
if (options.verbose) {
System.out.println("Warning: " + name + " already exists in " + outputFile.getName() //$NON-NLS-1$//$NON-NLS-2$
+ ". Skipping."); //$NON-NLS-1$
}
}
entryStream.close();
}
if (extractedFile != null)
Utils.clear(extractedFile);
if (options.verbose) {
System.out.println();
System.out.println("Processing " + zipFile.getPath()); //$NON-NLS-1$
}
}
}
}
File finalFile = new File(getWorkingDirectory(), zipFile.getName());
if (finalFile.exists())
finalFile.delete();
outputFile.renameTo(finalFile);
Utils.clear(tempDir);
}
}
public static File createSubPathFile(File root, String subPath) throws IOException {
File result = new File(root, subPath);
String resultCanonical = result.getCanonicalPath();
String rootCanonical = root.getCanonicalPath();
if (!resultCanonical.startsWith(rootCanonical + File.separator) && !resultCanonical.equals(rootCanonical)) {
throw new IOException("Invalid path: " + subPath); //$NON-NLS-1$
}
return result;
}
@SuppressWarnings("removal")
private void initialize(ZipFile zip) {
ZipEntry entry = zip.getEntry("pack.properties"); //$NON-NLS-1$
properties = new Properties();
if (entry != null) {
InputStream stream = null;
try {
stream = zip.getInputStream(entry);
properties.load(stream);
} catch (IOException e) {
if (options.verbose)
e.printStackTrace();
} finally {
Utils.close(stream);
}
}
packExclusions = Utils.getPackExclusions(properties);
signExclusions = Utils.getSignExclusions(properties);
if (executor == null)
executor = new JarProcessorExecutor();
}
}