/*******************************************************************************
* Copyright (c) 2006-2013, Cloudsmith Inc.
* The code, documentation and other materials contained herein have been
* licensed under the Eclipse Public License - v 1.0 by the copyright holder
* listed above, as the Initial Contributor under such license. The text of
* such license is available at www.eclipse.org.
******************************************************************************/
package org.eclipse.buckminster.pde.tasks;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import org.eclipse.buckminster.pde.IPDEConstants;
import org.eclipse.buckminster.pde.internal.FeatureModelReader;
import org.eclipse.buckminster.runtime.BuckminsterException;
import org.eclipse.buckminster.runtime.IOUtils;
import org.eclipse.buckminster.sax.Utils;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.pde.internal.core.ifeature.IFeature;
import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.xml.sax.SAXException;
/**
* Scans a folder for jar files containing an OSGi manifest or an Eclipse
* feature.xml and generates a JNLP version.xml file based on the information in
* them. The version.xml file is output in the same folder.
*
* @author Thomas Hallgren
*/
@SuppressWarnings("restriction")
public class JNLPSiteGenerator {
private static final String JNLP_SUFFIX = ".jnlp"; //$NON-NLS-1$
private static final String JAR_SUFFIX = ".jar"; //$NON-NLS-1$
private static void emitFolderVersions(File folder, JNLPVersionModel folderVersions) throws CoreException {
if (folderVersions == null)
return;
File versionsFile = new File(folder, "version.xml"); //$NON-NLS-1$
OutputStream output = null;
try {
output = new BufferedOutputStream(new FileOutputStream(versionsFile));
Utils.serialize(folderVersions, output);
} catch (IOException e) {
throw BuckminsterException.wrap(e);
} catch (SAXException e) {
throw BuckminsterException.wrap(e);
} finally {
IOUtils.close(output);
}
}
private final HashMap<String, JNLPModel.Resource> jnlpResources = new HashMap<String, JNLPModel.Resource>();
private final File directory;
public JNLPSiteGenerator(File directory) {
this.directory = directory;
}
public void run() throws CoreException {
try {
JNLPVersionModel folderVersions = null;
File featuresFolder = new File(directory, IPDEConstants.FEATURES_FOLDER);
File[] files = featuresFolder.listFiles();
if (files == null)
return;
for (File file : files) {
IFeature feature;
if (file.isDirectory()) {
File featureFile = new File(file, IPDEConstants.FEATURE_MANIFEST);
if (!featureFile.exists())
continue;
InputStream input = null;
try {
input = new BufferedInputStream(new FileInputStream(featureFile));
IFeatureModel model = FeatureModelReader.readFeatureModel(input);
feature = model.getFeature();
} finally {
IOUtils.close(input);
}
} else {
String leafName = file.getName();
if (!leafName.endsWith(JAR_SUFFIX))
continue;
JarFile jarFile = null;
try {
jarFile = new JarFile(file);
JarEntry entry = jarFile.getJarEntry(IPDEConstants.FEATURE_MANIFEST);
if (entry == null)
continue;
IFeatureModel model = FeatureModelReader.readFeatureModel(jarFile.getInputStream(entry));
feature = model.getFeature();
} finally {
if (jarFile != null)
jarFile.close();
}
}
if (folderVersions == null)
folderVersions = new JNLPVersionModel();
generateFromFeature(folderVersions, featuresFolder, feature);
}
if (folderVersions != null) {
emitFolderVersions(directory, folderVersions);
folderVersions = null;
}
File pluginsFolder = new File(directory, IPDEConstants.PLUGINS_FOLDER);
files = pluginsFolder.listFiles();
if (files == null)
return;
for (File file : files) {
String leafName = file.getName();
if (!leafName.endsWith(JAR_SUFFIX))
continue;
JarFile jarFile = null;
try {
jarFile = new JarFile(file);
Manifest mf = jarFile.getManifest();
String symbolicName = mf.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
if (symbolicName == null)
continue;
if (folderVersions == null)
folderVersions = new JNLPVersionModel();
generateFromBundle(folderVersions, leafName, mf);
} finally {
if (jarFile != null)
jarFile.close();
}
}
emitFolderVersions(pluginsFolder, folderVersions);
} catch (IOException e) {
throw BuckminsterException.wrap(e);
}
}
private void generateFromBundle(JNLPVersionModel folderVersions, String file, Manifest mf) throws CoreException {
Attributes a = mf.getMainAttributes();
String id;
try {
ManifestElement[] elements = ManifestElement.parseHeader(Constants.BUNDLE_SYMBOLICNAME, a.getValue(Constants.BUNDLE_SYMBOLICNAME));
id = elements[0].getValue();
} catch (BundleException be) {
throw BuckminsterException.wrap(be);
}
String version = a.getValue(Constants.BUNDLE_VERSION);
if (version == null)
version = "0.0.0"; //$NON-NLS-1$
/*
* We don't do this now since the requests lack os/arch information for
* some reason.
*
* JNLPVersionModel.Resource resource = folderVersions.addResource(file,
* id + ".jar", version); JNLPModel.Resource jnlpResource =
* jnlpResources.get(id + "_B"); if(jnlpResource != null) { String os =
* jnlpResource.getOs(); if(os != null) resource.addOs(os);
*
* String arch = jnlpResource.getArch(); if(arch != null)
* resource.addArch(arch); }
*/
folderVersions.addResource(file, id + JAR_SUFFIX, version);
}
private void generateFromFeature(JNLPVersionModel folderVersions, File featuresFolder, IFeature feature) throws CoreException {
String id = feature.getId();
String version = feature.getVersion();
String file = id + '_' + version + JNLP_SUFFIX;
JNLPVersionModel.Resource resource = folderVersions.addResource(file, id + JNLP_SUFFIX, version);
String os = feature.getOS();
if (os == null)
os = feature.getWS();
os = JNLPGenerator.convertOS(os);
if (os != null)
resource.addOs(os);
String arch = JNLPGenerator.convertArch(feature.getArch());
if (arch != null)
resource.addArch(arch);
// Generate the JNLPModel for this feature
//
JNLPGenerator jnlpGen = new JNLPGenerator(feature);
JNLPModel jnlp = jnlpGen.generateJNLP();
jnlpResources.putAll(jnlp.getResources());
// Serialize the JNLP xml
//
File jnlpFile = new File(featuresFolder.getParentFile(), file);
OutputStream jnlpOut = null;
try {
jnlpOut = new BufferedOutputStream(new FileOutputStream(jnlpFile));
Utils.serialize(jnlp, jnlpOut);
} catch (IOException e) {
throw BuckminsterException.wrap(e);
} catch (SAXException e) {
throw BuckminsterException.wrap(e);
} finally {
IOUtils.close(jnlpOut);
}
}
}