/*******************************************************************************
* 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.par;
import java.io.File;
import java.io.IOException;
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.HashGenerator;
import org.eclipse.virgo.repository.builder.ArtifactDescriptorBuilder;
import org.eclipse.virgo.repository.builder.AttributeBuilder;
import org.eclipse.virgo.util.common.StringUtils;
import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
import org.osgi.framework.Version;
/**
* An <code>ArtifactBridge</code> for PAR files.
*
* <p />
*
* <strong>Concurrent Semantics</strong><br />
*
* Thread-safe.
*
*/
public final class ParBridge implements ArtifactBridge {
private static final String SYMBOLIC_NAME_REGEX = "[-_0-9a-zA-Z]+(\\.[-_0-9a-zA-Z]+)*";
private static final String HEADER_APPLICATION_SYMBOLIC_NAME = "Application-SymbolicName";
private static final String HEADER_APPLICATION_NAME = "Application-Name";
private static final String HEADER_APPLICATION_DESCRIPTION = "Application-Description";
private static final String HEADER_APPLICATION_VERSION = "Application-Version";
public static final String BRIDGE_TYPE = "par";
public static final String PAR_SUFFIX = ".par";
private final HashGenerator hashGenerator;
public ParBridge(HashGenerator hashGenerator) {
this.hashGenerator = hashGenerator;
}
public ArtifactDescriptor generateArtifactDescriptor(File artifactFile) throws ArtifactGenerationException {
BundleManifest manifest;
try {
manifest = BundleManifestUtils.readBundleManifest(artifactFile, PAR_SUFFIX);
} catch (IOException ioe) {
throw new ArtifactGenerationException("Failed to read manifest from " + artifactFile, ioe);
}
if (manifest != null) {
return createDescriptorFromManifest(manifest, artifactFile);
} else {
return createDescriptorFromFile(artifactFile);
}
}
private ArtifactDescriptor createDescriptorFromFile(File artifactFile) throws ArtifactGenerationException {
String fileName = artifactFile.getName();
if (fileName.endsWith(PAR_SUFFIX)) {
String symbolicName = fileName.substring(0, fileName.length() - PAR_SUFFIX.length());
ArtifactDescriptorBuilder builder = new ArtifactDescriptorBuilder();
builder.setType(BRIDGE_TYPE).setName(symbolicName).setVersion(Version.emptyVersion).setUri(artifactFile.toURI());
this.hashGenerator.generateHash(builder, artifactFile);
return builder.build();
}
return null;
}
private ArtifactDescriptor createDescriptorFromManifest(BundleManifest manifest, File artifactFile) throws ArtifactGenerationException {
String symbolicName = getApplicationSymbolicName(manifest);
if (symbolicName == null) {
return null;
}
Version version = getApplicationVersion(manifest);
ArtifactDescriptorBuilder builder = new ArtifactDescriptorBuilder();
builder.setType(BRIDGE_TYPE).setName(symbolicName).setVersion(version).setUri(artifactFile.toURI());
applyAttributeIfPresent(HEADER_APPLICATION_NAME, manifest, builder);
applyAttributeIfPresent(HEADER_APPLICATION_DESCRIPTION, manifest, builder);
this.hashGenerator.generateHash(builder, artifactFile);
return builder.build();
}
private void applyAttributeIfPresent(String headerName, BundleManifest manifest, ArtifactDescriptorBuilder builder) {
String headerValue = manifest.getHeader(headerName);
if (headerValue != null) {
AttributeBuilder attributeBuilder = new AttributeBuilder();
builder.addAttribute(attributeBuilder.setName(headerName).setValue(headerValue).build());
}
}
private Version getApplicationVersion(BundleManifest manifest) {
String versionString = manifest.getHeader(HEADER_APPLICATION_VERSION);
Version version;
if (!StringUtils.hasText(versionString)) {
version = Version.emptyVersion;
} else {
try {
version = new Version(versionString);
} catch (IllegalArgumentException iae) {
throw new IllegalArgumentException("Version '" + versionString + "' is ill-formed", iae);
}
}
return version;
}
private String getApplicationSymbolicName(BundleManifest manifest) throws ArtifactGenerationException {
String symbolicName = manifest.getHeader(HEADER_APPLICATION_SYMBOLIC_NAME);
if (!StringUtils.hasText(symbolicName)) {
return null;
}
if (!symbolicName.matches(SYMBOLIC_NAME_REGEX)) {
throw new ArtifactGenerationException(HEADER_APPLICATION_SYMBOLIC_NAME + " '" + symbolicName + "' contains illegal characters");
}
return symbolicName;
}
}