All Downloads are FREE. Search and download functionalities are using the official Maven repository.

aQute.bnd.exporter.subsystem.SubsystemExporter Maven / Gradle / Ivy

There is a newer version: 7.0.0
Show newest version
package aQute.bnd.exporter.subsystem;

import static aQute.bnd.osgi.Constants.REMOVEHEADERS;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import aQute.bnd.annotation.plugin.BndPlugin;
import aQute.bnd.build.Container;
import aQute.bnd.build.Project;
import aQute.bnd.osgi.Constants;
import aQute.bnd.osgi.Domain;
import aQute.bnd.osgi.EmbeddedResource;
import aQute.bnd.osgi.FileResource;
import aQute.bnd.osgi.Instructions;
import aQute.bnd.osgi.Jar;
import aQute.bnd.osgi.JarResource;
import aQute.bnd.osgi.Resource;
import aQute.bnd.osgi.Verifier;
import aQute.bnd.service.export.Exporter;

@BndPlugin(name = "subsystem")
public class SubsystemExporter implements Exporter {

	private static final String	OSGI_INF_SUBSYSTEM_MF		= "OSGI-INF/SUBSYSTEM.MF";
	private static final String	SUBSYSTEM_SYMBOLIC_NAME		= "Subsystem-SymbolicName";
	@SuppressWarnings("unused")
	private static final String	OSGI_SUBSYSTEM_APPLICATION	= "osgi.subsystem.application";
	private static final String	OSGI_SUBSYSTEM_FEATURE		= "osgi.subsystem.feature";
	@SuppressWarnings("unused")
	private static final String	OSGI_SUBSYSTEM_COMPOSITE	= "osgi.subsystem.composite";
	private static final String	SUBSYSTEM_TYPE				= "Subsystem-Type";
	@SuppressWarnings("unused")
	private static final String	SUBSYSTEM_CONTENT			= "Subsystem-Content";

	@Override
	public String[] getTypes() {
		return new String[] {
				// OSGI_SUBSYSTEM_APPLICATION, OSGI_SUBSYSTEM_FEATURE,
				// OSGI_SUBSYSTEM_COMPOSITE
		};
	}

	@Override
	public Map.Entry export(String type, final Project project, Map options)
			throws Exception {
		Jar jar = new Jar(".");

		project.addClose(jar);

		Manifest manifest = new Manifest();
		manifest.getMainAttributes().putValue("Manifest-Version", "1.0");
		manifest.getMainAttributes().putValue("Subsystem-ManifestVersion", "1");

		List files = new ArrayList();

		for (Container c : project.getRunbundles()) {
			switch (c.getType()) {
				case ERROR :
					// skip, already reported
					break;

				case PROJECT :
				case EXTERNAL :
				case REPO :
					files.add(c.getFile());
					break;
				case LIBRARY :
					c.contributeFiles(files, project);
					break;
			}
		}

		for (File file : files) {

			Domain domain = Domain.domain(file);
			String bsn = domain.getBundleSymbolicName().getKey();
			String version = domain.getBundleVersion();

			String path = bsn + "-" + version + ".jar";
			jar.putResource(path, new FileResource(file));
		}

		headers(project, manifest.getMainAttributes());

		set(manifest.getMainAttributes(), SUBSYSTEM_TYPE, OSGI_SUBSYSTEM_FEATURE);

		String ssn = project.getName();

		Collection bsns = project.getBsns();
		if (bsns.size() > 0) {
			ssn = bsns.iterator().next();
		}
		set(manifest.getMainAttributes(), SUBSYSTEM_SYMBOLIC_NAME, ssn);

		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		manifest.write(bout);

		jar.putResource(OSGI_INF_SUBSYSTEM_MF, new EmbeddedResource(bout.toByteArray(), 0));

		final JarResource jarResource = new JarResource(jar);
		final String name = ssn + ".esa";

		return new Map.Entry() {

			@Override
			public String getKey() {
				return name;
			}

			@Override
			public Resource getValue() {
				return jarResource;
			}

			@Override
			public Resource setValue(Resource arg0) {
				throw new UnsupportedOperationException();
			}
		};
	}

	private void headers(final Project project, Attributes application) {
		for (String key : project.getPropertyKeys(true)) {
			if (!Verifier.HEADER_PATTERN.matcher(key).matches())
				continue;

			if (application.getValue(key) != null)
				continue;

			String value = project.getProperty(key);
			if (value == null)
				continue;

			value = value.trim();
			if (value.isEmpty() || Constants.EMPTY_HEADER.equals(value))
				continue;

			char c = value.charAt(0);
			if (Character.isUpperCase(c))
				application.putValue(key, value);
		}
		Instructions instructions = new Instructions(project.mergeProperties(REMOVEHEADERS));
		Collection result = instructions.select(application.keySet(), false);
		application.keySet().removeAll(result);
	}

	private void set(Attributes application, String key, String... values) {
		if (application.getValue(key) != null)
			return;

		for (String value : values) {
			if (value != null) {
				application.putValue(key, value);
				return;
			}
		}

	}

}