/*******************************************************************************
* Copyright (c) 2008, 2010 VMware Inc.
* 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:
* VMware Inc. - initial contribution
*******************************************************************************/
package org.eclipse.virgo.kernel.artifact.internal;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.jar.JarFile;
import org.eclipse.virgo.kernel.artifact.fs.ArtifactFS;
import org.eclipse.virgo.kernel.artifact.fs.ArtifactFSEntry;
import org.eclipse.virgo.kernel.artifact.fs.internal.JarFileArtifactFS;
import org.eclipse.virgo.util.io.FileCopyUtils;
import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
import org.eclipse.virgo.util.osgi.manifest.BundleManifestFactory;
/**
* Utility methods for working with {@link BundleManifest BundleManifests}.
*
* <p />
*
* <strong>Concurrent Semantics</strong><br />
*
* Thread-safe.
*
*/
public final class BundleManifestUtils {
/**
* Reads the <code>BundleManifest</code> from the supplied <code>file</code>. The <code>File</code> can either be a
* file, i.e. a jar archive, or a directory. If the file is an archive its manifest will only be read if its name
* ends with one of the supplied <code>archiveSuffixes</code>
*
* @param file The file from which the manifest is to be read.
* @param archiveSuffixes The suffixes with which an archive's file name must end
* @return The <code>BundleManifest</code> from the file or <code>null</code> if one was not found.
* @throws IOException Thrown if a manifest is detected but the reading of it fails.
* @throws SecurityException Thrown if a manifest is detected but the reading of it fails because of signature
* checks (invalid signature file digest...)
*/
public static BundleManifest readBundleManifest(File file, String... archiveSuffixes) throws IOException, SecurityException {
String fileName = file.getName();
Reader reader = null;
if (file.isDirectory()) {
File manifestFile = new File(file, JarFile.MANIFEST_NAME);
if (manifestFile.exists()) {
reader = manifestReaderFromFile(manifestFile);
}
} else {
for (String suffix : archiveSuffixes) {
if (fileName.endsWith(suffix)) {
reader = manifestReaderFromJar(file);
}
}
}
if (reader != null) {
return BundleManifestFactory.createBundleManifest(reader);
} else {
return null;
}
}
private static Reader manifestReaderFromJar(File file) throws IOException, SecurityException {
if (!file.exists()) {
throw new IOException("File '" + file + "' not found");
}
ArtifactFS fs = new JarFileArtifactFS(file);
ArtifactFSEntry fsEntry = fs.getEntry(JarFile.MANIFEST_NAME);
if (fsEntry == null || !fsEntry.exists()) {
return null; // not an error -- no manifest means this isn't a bundle
}
StringWriter writer = new StringWriter();
InputStream inputStream = fsEntry.getInputStream();
FileCopyUtils.copy(new InputStreamReader(inputStream, UTF_8), writer);
inputStream.close();
return new StringReader(writer.toString());
}
private static Reader manifestReaderFromFile(File file) throws IOException {
try {
StringWriter writer = new StringWriter();
FileCopyUtils.copy(new InputStreamReader(new FileInputStream(file), UTF_8), writer);
return new StringReader(writer.toString());
} catch (IOException ioe) {
throw new IOException("Failed to create reader for manifest file.", ioe);
}
}
}