/*******************************************************************************
* Copyright (c) 2011 Gerd Wuetherich (gerd@gerd-wuetherich.de).
* 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:
* Gerd Wuetherich (gerd@gerd-wuetherich.de) - initial API and implementation
******************************************************************************/
package org.bundlemaker.core.common;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import org.bundlemaker.core.resource.IModuleResource;
import org.eclipse.core.runtime.Assert;
/**
* <p>
* </p>
*
* @author Gerd Wütherich (gerd@gerd-wuetherich.de)
*
* @noextend This class is not intended to be subclassed by clients.
*/
public final class Resource2JarFileExporter {
/**
* <p>
* Creates a jar archive for the given list of {@link IModuleResource IResources}.
* </p>
*
* @param resources
* the list of resources
* @param manifest
* the manifest file
* @param archiveFile
* the archive file to create
*/
public static void createJarArchive(Set<? extends IResource> resources, Manifest manifest,
Set<IResource> additionalContent, OutputStream outputStream) {
Assert.isNotNull(resources);
Assert.isNotNull(manifest);
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
// create the input and output streams
JarOutputStream jarOutputStream = null;
InputStream inputStream = null;
try {
// open the archive file
jarOutputStream = new JarOutputStream(outputStream, manifest);
// add all the resources
for (IResource resourceStandin : resources) {
// add everything but the manifest
if (!skipResource(resourceStandin.getPath())) {
// add archive entry
JarEntry newEntry = new JarEntry(resourceStandin.getPath());
jarOutputStream.putNextEntry(newEntry);
// copy
inputStream = new ByteArrayInputStream(resourceStandin.getContent());
copy(inputStream, jarOutputStream);
inputStream.close();
jarOutputStream.closeEntry();
}
}
if (additionalContent != null) {
// add all additional files
for (IResource contentProvider : additionalContent) {
// add archive entry
JarEntry newEntry = new JarEntry(contentProvider.getPath());
jarOutputStream.putNextEntry(newEntry);
// copy
inputStream = new ByteArrayInputStream(contentProvider.getContent());
copy(inputStream, jarOutputStream);
inputStream.close();
jarOutputStream.closeEntry();
}
}
//
jarOutputStream.flush();
} catch (Exception ex) {
// TODO
ex.printStackTrace();
} finally {
close(jarOutputStream);
close(inputStream);
}
}
/**
* <p>
* </p>
*
* @param resource
* @return
*/
public static boolean skipResource(String path) {
// skip the original manifest
if ("META-INF/MANIFEST.MF".equalsIgnoreCase(path) || "META-INF/".equalsIgnoreCase(path)) {
return true;
}
// skip META-INF/*.RSA, META-INF/*.DSA and META-INF/*.SF files
if (path.matches("[Mm][Ee][Tt][Aa]-[Ii][Nn][Ff]/[^/]*\\.[Rr][Ss][Aa]")
|| path.matches("[Mm][Ee][Tt][Aa]-[Ii][Nn][Ff]/[^/]*\\.[Dd][Ss][Aa]")
|| path.matches("[Mm][Ee][Tt][Aa]-[Ii][Nn][Ff]/[^/]*\\.[Ss][Ff]")) {
return true;
}
// default: don't skip
return false;
}
/**
* <p>
* </p>
*
* @param in
* @param out
* @throws IOException
*/
private static void copy(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[8192];
int bytesRead = -1;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
out.flush();
}
/**
* <p>
* </p>
*
* @param closeable
*/
private static void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
//
}
}
}
private static byte[] serialiseManifest(Manifest manifest) throws IOException {
ByteArrayOutputStream byteout = new ByteArrayOutputStream();
manifest.write(byteout);
byteout.close();
byte[] result = byteout.toByteArray();
return result;
}
}