blob: e6498c382c83651f022f168ca382182f8ca598b6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2015 Sonatype Inc. 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:
* Sonatype Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.tycho.extras.pack200;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import org.apache.maven.artifact.Artifact;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
@Component(role = Pack200Archiver.class)
public class Pack200Archiver {
@Requirement
private Logger log;
private Pack200Wrapper packWrapper = new Pack200Wrapper();
private ForkedPack200Wrapper forkedPackWrapper = new ForkedPack200Wrapper();
/**
* @param file
* source jar file
* @param packFile
* target pack file
* @return <code>true</code> if the target pack file was created, <code>false</code> if the
* target file was not created
*/
public boolean normalize(List<Artifact> pluginArtifacts, File file, File packFile, boolean fork) throws IOException {
File jarToBePacked = file;
boolean shouldNormalize = false;
boolean jarToBePackedIsTempFile = false;
try (JarFile jarFile = new JarFile(file)) {
EclipseInf eclipseInf = EclipseInf.readEclipseInf(jarFile);
assertSupportedEclipseInf(eclipseInf);
if (eclipseInf == null || (eclipseInf.shouldPack() && !eclipseInf.isPackNormalized())) {
if (isSigned(jarFile)) {
throw new IOException("pack200:normalize cannot be called for signed jar " + file);
}
shouldNormalize = true;
if (eclipseInf != null) {
eclipseInf.setPackNormalized();
jarToBePacked = File.createTempFile(file.getName(), ".prepack");
jarToBePackedIsTempFile = true;
updateEclipseInf(jarFile, eclipseInf, jarToBePacked);
}
}
}
if (shouldNormalize) {
try {
log.info("Pack200 normalizing jar " + file.getAbsolutePath());
getPackWrapper(fork).pack(pluginArtifacts, jarToBePacked, packFile);
} finally {
if (jarToBePackedIsTempFile) {
if (!jarToBePacked.delete()) {
throw new IOException("Could not delete temporary file " + jarToBePacked.getAbsolutePath());
}
}
}
return true;
}
return false;
}
private Pack200Wrapper getPackWrapper(boolean fork) {
return fork ? forkedPackWrapper : packWrapper;
}
protected void assertSupportedEclipseInf(EclipseInf eclipseInf) throws IOException {
if (eclipseInf != null && eclipseInf.shouldPack() && eclipseInf.shouldSign()) {
throw new IOException("Pack200 and jar signing cannot be both enabled in " + EclipseInf.PATH_ECLIPSEINF
+ ". See bug 388629.");
}
}
private void updateEclipseInf(JarFile jarFile, EclipseInf eclipseInf, File tmpFile) throws IOException {
try (JarOutputStream jos = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(tmpFile)))) {
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (!entry.getName().equals(EclipseInf.PATH_ECLIPSEINF)) {
copyJarEntry(jarFile, entry, jos);
}
}
JarEntry entry = new JarEntry(EclipseInf.PATH_ECLIPSEINF);
jos.putNextEntry(entry);
jos.write(eclipseInf.toByteArray());
jos.closeEntry();
}
}
private boolean isSigned(JarFile jarFile) throws IOException {
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
if (name.startsWith("META-INF/") && name.endsWith(".SF")) {
return true;
}
}
return false;
}
private void copyJarEntry(JarFile jarFile, JarEntry entry, JarOutputStream jos) throws IOException {
jos.putNextEntry(entry);
InputStream is = jarFile.getInputStream(entry);
byte[] buf = new byte[4096];
int n;
while ((n = is.read(buf)) != -1) {
jos.write(buf, 0, n);
}
jos.closeEntry();
}
public void unpack(List<Artifact> pluginArtifacts, File packFile, File jarFile, boolean fork) throws IOException {
getPackWrapper(fork).unpack(pluginArtifacts, packFile, jarFile);
}
public boolean pack(List<Artifact> pluginArtifacts, File file, File packFile, boolean fork) throws IOException {
EclipseInf eclipseInf = null;
try (JarFile jarFile = new JarFile(file)) {
eclipseInf = EclipseInf.readEclipseInf(jarFile);
}
assertSupportedEclipseInf(eclipseInf);
if (eclipseInf == null || (eclipseInf.shouldPack() && eclipseInf.isPackNormalized())) {
log.info("Pack200 packing jar " + file.getAbsolutePath());
getPackWrapper(fork).pack(pluginArtifacts, file, packFile);
return true;
}
return false;
}
}