/*
* Copyright 2016 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.as.arquillian.jbosgi.container;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import org.jboss.arquillian.container.osgi.AbstractOSGiApplicationArchiveProcessor;
import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor;
import org.jboss.arquillian.test.spi.TestClass;
import org.jboss.osgi.metadata.OSGiManifestBuilder;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ArchivePath;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.Node;
import org.jboss.shrinkwrap.api.asset.Asset;
/**
* An OSGi {@link ApplicationArchiveProcessor} that does not generate the
* manifest on demand. AS7 test archives must be explicit about their manifest
* metadata.
*
* @author Thomas.Diesler@jboss.com
*/
public class JBOSGiApplicationArchiveProcessor implements ApplicationArchiveProcessor {
private static final ArchivePath MANIFEST_PATH = ArchivePaths.create(JarFile.MANIFEST_NAME);
private static final String ESSENTIAL_DEPENDENCIES = "org.jboss.as.osgi,deployment.arquillian-service";
@Override
public void process(Archive<?> appArchive, TestClass testClass) {
if (isValidOSGiBundleArchive(appArchive)) {
ApplicationArchiveProcessor processor = new AbstractOSGiApplicationArchiveProcessor() {
@Override
protected Manifest createBundleManifest(String symbolicName) {
return null;
}
};
processor.process(appArchive, testClass);
} else {
// Add or replace the manifest in the archive
try {
Manifest existingManifest = new Manifest();
Node manifestNode = appArchive.get(MANIFEST_PATH);
if (manifestNode != null) {
existingManifest = new Manifest(manifestNode.getAsset().openStream());
appArchive.delete(MANIFEST_PATH);
}
Attributes attrs = existingManifest.getMainAttributes();
String dependenciesAttr = attrs != null ? attrs.getValue("Dependencies") : null;
if (dependenciesAttr != null) {
dependenciesAttr += "," + ESSENTIAL_DEPENDENCIES;
} else {
dependenciesAttr = ESSENTIAL_DEPENDENCIES;
attrs.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
}
attrs.putValue("Dependencies", dependenciesAttr);
final Manifest newManifest = existingManifest;
appArchive.add(new Asset() {
public InputStream openStream() {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
newManifest.write(bos);
return new ByteArrayInputStream(bos.toByteArray());
} catch (IOException e) {
throw new RuntimeException("Unable to write customized application manifest", e);
}
}
}, JarFile.MANIFEST_NAME);
} catch (IllegalArgumentException | IOException e) {
throw new RuntimeException("Unable to customize existing application manifest", e);
}
}
}
public static boolean isValidOSGiBundleArchive(Archive<?> appArchive) {
// org.jboss.arquillian.container:arquillian-container-osgi must be be
// provided
ClassLoader classLoader = JBOSGiApplicationArchiveProcessor.class.getClassLoader();
try {
classLoader.loadClass("org.jboss.arquillian.container.osgi.AbstractOSGiApplicationArchiveProcessor");
} catch (ClassNotFoundException ex) {
return false;
}
Manifest manifest = ManifestUtils.getManifest(appArchive, true);
return OSGiManifestBuilder.isValidBundleManifest(manifest);
}
}