blob: d7298b8d19994720b42923e3361a0b6e4043e3a5 [file] [log] [blame]
/*******************************************************************************
* 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.bundle;
import java.io.File;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
import org.eclipse.virgo.kernel.artifact.internal.BundleManifestUtils;
import org.eclipse.virgo.repository.ArtifactBridge;
import org.eclipse.virgo.repository.ArtifactDescriptor;
import org.eclipse.virgo.repository.ArtifactGenerationException;
import org.eclipse.virgo.repository.Attribute;
import org.eclipse.virgo.repository.HashGenerator;
import org.eclipse.virgo.repository.builder.ArtifactDescriptorBuilder;
import org.eclipse.virgo.repository.builder.AttributeBuilder;
import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
import org.eclipse.virgo.util.osgi.manifest.BundleSymbolicName;
import org.eclipse.virgo.util.osgi.manifest.ExportedPackage;
import org.eclipse.virgo.util.osgi.manifest.FragmentHost;
import org.eclipse.virgo.util.osgi.manifest.ImportedPackage;
import org.eclipse.virgo.util.osgi.manifest.FragmentHost.Extension;
/**
* Implementation of {@link ArtifactBridge} that creates an {@link ArtifactDescriptor} from an OSGi bundle packaged
* either as a JAR file, or a directory.
* <p />
* <strong>Concurrent Semantics</strong><br />
*
* This class is thread-safe
*
*/
public final class BundleBridge implements ArtifactBridge {
private static final String JAR_SUFFIX = ".jar";
private static final String WAR_SUFFIX = ".war";
public static final String RAW_HEADER_PREFIX = "RAW_HEADER:";
public static final String BRIDGE_TYPE = "bundle";
private final HashGenerator hashGenerator;
public BundleBridge(HashGenerator hashGenerator) {
this.hashGenerator = hashGenerator;
}
/**
* {@inheritDoc}
*/
public ArtifactDescriptor generateArtifactDescriptor(File artifactFile) throws ArtifactGenerationException {
if (artifactFile == null) {
throw new ArtifactGenerationException("The artifact file must not be null.", BRIDGE_TYPE);
}
BundleManifest bundleManifest;
try {
bundleManifest = BundleManifestUtils.readBundleManifest(artifactFile, JAR_SUFFIX, WAR_SUFFIX);
} catch (RuntimeException re) {
throw new RuntimeException(String.format("Error occurred while parsing the manifest of file '%s'.", artifactFile.getPath()), re);
} catch (Exception e) {
throw new ArtifactGenerationException("Error occurred while parsing the manifest.", BRIDGE_TYPE, e);
}
if (bundleManifest == null) {
return null;
}
try {
ArtifactDescriptorBuilder artifactDescriptorBuilder = new ArtifactDescriptorBuilder();
String name = applyBundleSymbolicName(artifactDescriptorBuilder, bundleManifest);
if (name == null) { // no bundle symbolic name ==> not a bundle
return null;
}
artifactDescriptorBuilder.setUri(artifactFile.toURI());
artifactDescriptorBuilder.setName(name);
artifactDescriptorBuilder.setType(BRIDGE_TYPE);
artifactDescriptorBuilder.setVersion(applyBundleVersion(artifactDescriptorBuilder, bundleManifest));
applyImportPackage(artifactDescriptorBuilder, bundleManifest);
applyFragmentHost(artifactDescriptorBuilder, bundleManifest);
applyExportPackage(artifactDescriptorBuilder, bundleManifest);
this.hashGenerator.generateHash(artifactDescriptorBuilder, artifactFile);
Dictionary<String, String> rawManifest = bundleManifest.toDictionary();
Enumeration<String> keys = rawManifest.keys();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
String value = rawManifest.get(key);
artifactDescriptorBuilder.addAttribute(new AttributeBuilder().setName(RAW_HEADER_PREFIX + key).setValue(value).build());
}
return artifactDescriptorBuilder.build();
} catch (Exception e) {
throw new ArtifactGenerationException("Manifest ill-formed.", BRIDGE_TYPE, e);
}
}
/**
* Providing the <code>artifactDescriptor</code> was created by this bridge in the first place then all its
* attributes from the main section of the manifest are placed in to a dictionary and returned. If not then
* <code>null</code> is returned.
*
* @param artifactDescriptor to be converted
* @return the new dictionary or null if the provided <code>artifactDescriptor</code> was not created by this bridge
*/
public static Dictionary<String, String> convertToDictionary(ArtifactDescriptor artifactDescriptor) {
if (!BRIDGE_TYPE.equals(artifactDescriptor.getType())) {
return null;
}
Hashtable<String, String> dictionary = new Hashtable<String, String>();
for (Attribute attribute : artifactDescriptor.getAttributes()) {
if (attribute.getKey().startsWith(RAW_HEADER_PREFIX)) {
dictionary.put(attribute.getKey().substring(RAW_HEADER_PREFIX.length()), attribute.getValue());
}
}
return dictionary;
}
private String applyBundleSymbolicName(ArtifactDescriptorBuilder artifactBuilder, BundleManifest bundleManifest) {
BundleSymbolicName bundleSymbolicName = bundleManifest.getBundleSymbolicName();
String symbolicName = bundleSymbolicName.getSymbolicName();
if (symbolicName != null) { // not a bundle if null
AttributeBuilder attributeBuilder = new AttributeBuilder();
attributeBuilder.setName(Constants.BUNDLE_SYMBOLICNAME);
attributeBuilder.setValue(symbolicName);
attributeBuilder.putProperties(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE, bundleSymbolicName.getFragmentAttachment().name());
attributeBuilder.putProperties(Constants.SINGLETON_DIRECTIVE, Boolean.toString(bundleSymbolicName.isSingleton()));
artifactBuilder.addAttribute(attributeBuilder.build());
}
return symbolicName;
}
private Version applyBundleVersion(ArtifactDescriptorBuilder artifactBuilder, BundleManifest bundleManifest) {
Version version = bundleManifest.getBundleVersion();
artifactBuilder.addAttribute(new AttributeBuilder().setName(Constants.BUNDLE_VERSION).setValue(version.toString()).build());
return version;
}
private void applyImportPackage(ArtifactDescriptorBuilder artifactBuilder, BundleManifest bundleManifest) {
for (ImportedPackage importedPackage : bundleManifest.getImportPackage().getImportedPackages()) {
AttributeBuilder attributeBuilder = new AttributeBuilder();
attributeBuilder.setName(Constants.IMPORT_PACKAGE);
attributeBuilder.setValue(importedPackage.getPackageName());
attributeBuilder.putProperties(Constants.RESOLUTION_DIRECTIVE, importedPackage.getResolution().name());
attributeBuilder.putProperties(Constants.VERSION_ATTRIBUTE, importedPackage.getVersion().toParseString());
artifactBuilder.addAttribute(attributeBuilder.build());
}
}
private void applyFragmentHost(ArtifactDescriptorBuilder artifactBuilder, BundleManifest bundleManifest) {
FragmentHost fragmentHost = bundleManifest.getFragmentHost();
String hostSymbolicName = fragmentHost.getBundleSymbolicName();
if (hostSymbolicName != null) {
AttributeBuilder attributeBuilder = new AttributeBuilder();
attributeBuilder.setName(Constants.FRAGMENT_HOST);
attributeBuilder.setValue(hostSymbolicName);
Extension extension = fragmentHost.getExtension();
if (extension != null) {
attributeBuilder.putProperties(Constants.EXTENSION_DIRECTIVE, extension.name());
}
attributeBuilder.putProperties(Constants.BUNDLE_VERSION_ATTRIBUTE, fragmentHost.getBundleVersion().toParseString());
artifactBuilder.addAttribute(attributeBuilder.build());
}
}
private void applyExportPackage(ArtifactDescriptorBuilder artifactBuilder, BundleManifest bundleManifest) {
for (ExportedPackage exportedPackage : bundleManifest.getExportPackage().getExportedPackages()) {
AttributeBuilder attributeBuilder = new AttributeBuilder();
attributeBuilder.setName(Constants.EXPORT_PACKAGE);
attributeBuilder.setValue(exportedPackage.getPackageName());
attributeBuilder.putProperties(Constants.VERSION_ATTRIBUTE, exportedPackage.getVersion().toString());
List<String> include = exportedPackage.getInclude();
if (include.size() > 0) {
attributeBuilder.putProperties(Constants.INCLUDE_DIRECTIVE, include);
}
List<String> exclude = exportedPackage.getExclude();
if (exclude.size() > 0) {
attributeBuilder.putProperties(Constants.EXCLUDE_DIRECTIVE, exclude);
}
List<String> mandatory = exportedPackage.getMandatory();
if (mandatory.size() > 0) {
attributeBuilder.putProperties(Constants.MANDATORY_DIRECTIVE, mandatory);
}
List<String> uses = exportedPackage.getUses();
if (uses.size() > 0) {
attributeBuilder.putProperties(Constants.USES_DIRECTIVE, uses);
}
artifactBuilder.addAttribute(attributeBuilder.build());
}
}
}