/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package org.arquillian.liferay.deploymentscenario;
import aQute.bnd.osgi.Analyzer;
import aQute.bnd.osgi.Jar;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import org.arquillian.liferay.deploymentscenario.annotations.BndFile;
import org.jboss.arquillian.container.spi.client.deployment.DeploymentDescription;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.container.test.impl.client.deployment.AnnotationDeploymentScenarioGenerator;
import org.jboss.arquillian.container.test.spi.client.deployment.DeploymentScenarioGenerator;
import org.jboss.arquillian.core.api.Injector;
import org.jboss.arquillian.core.api.Instance;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.test.spi.TestClass;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.ByteArrayAsset;
import org.jboss.shrinkwrap.api.exporter.ZipExporter;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.jboss.shrinkwrap.osgi.api.BndProjectBuilder;
/**
* @author Carlos Sierra Andrés
*/
public class BndDeploymentScenarioGenerator
implements DeploymentScenarioGenerator {
public static final String MANIFEST_PATH = "META-INF/MANIFEST.MF";
public BndDeploymentScenarioGenerator() {
String sdkDir = System.getProperty("sdk.dir");
if ((sdkDir != null) && !sdkDir.isEmpty()) {
commonBndFile = new File(sdkDir, "common.bnd");
}
}
@Override
public List<DeploymentDescription> generate(TestClass testClass) {
List<DeploymentDescription> deployments = new ArrayList<>();
DeploymentScenarioGenerator defaultDeploymentScenarioGenerator =
getDefaultDeploymentScenarioGenerator();
if (defaultDeploymentScenarioGenerator != null) {
List<DeploymentDescription> annotationDeployments =
defaultDeploymentScenarioGenerator.generate(testClass);
if ((annotationDeployments != null) &&
!annotationDeployments.isEmpty()) {
return annotationDeployments;
}
}
try (Analyzer analyzer = new Analyzer()) {
bndFile = getBndFile(testClass);
BndProjectBuilder bndProjectBuilder = ShrinkWrap.create(
BndProjectBuilder.class);
bndProjectBuilder.setBndFile(bndFile);
bndProjectBuilder.generateManifest(true);
if (commonBndFile != null) {
bndProjectBuilder.addProjectPropertiesFile(commonBndFile);
}
JavaArchive javaArchive = bndProjectBuilder.as(JavaArchive.class);
javaArchive.addClass(BndFile.class);
Properties analyzerProperties = new Properties();
if (commonBndFile != null) {
analyzerProperties.putAll(
analyzer.loadProperties(commonBndFile));
}
analyzerProperties.putAll(analyzer.loadProperties(bndFile));
analyzer.setProperties(analyzerProperties);
boolean testable = isTestable(testClass);
if (testable) {
addTestClass(testClass, javaArchive);
}
ZipExporter zipExporter = javaArchive.as(ZipExporter.class);
Jar jar = new Jar(
javaArchive.getName(), zipExporter.exportAsInputStream());
analyzer.setJar(jar);
DeploymentDescription deploymentDescription =
new DeploymentDescription(javaArchive.getName(), javaArchive);
deploymentDescription.shouldBeTestable(testable).shouldBeManaged(
true);
deployments.add(deploymentDescription);
Manifest firstPassManifest = new Manifest(
javaArchive.get(MANIFEST_PATH).getAsset().openStream());
firstPassManifest.getMainAttributes().remove(
new Attributes.Name("Import-Package"));
analyzer.mergeManifest(firstPassManifest);
Manifest manifest = analyzer.calcManifest();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
manifest.write(baos);
ByteArrayAsset byteArrayAsset = new ByteArrayAsset(
baos.toByteArray());
replaceManifest(javaArchive, byteArrayAsset);
return deployments;
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
public File getBndFile(TestClass testClass) {
if (testClass.isAnnotationPresent(BndFile.class)) {
BndFile annotation = testClass.getAnnotation(BndFile.class);
return new File(annotation.value());
}
return bndFile;
}
public void setBndFile(File bndFile) {
this.bndFile = bndFile;
}
public void setCommonBndFile(File commonBndFile) {
this.commonBndFile = commonBndFile;
}
protected DeploymentScenarioGenerator
getDefaultDeploymentScenarioGenerator() {
//FIXME: is there a way to request a specific service,
// not an interface?
AnnotationDeploymentScenarioGenerator
annotationDeploymentScenarioGenerator =
new AnnotationDeploymentScenarioGenerator();
annotationDeploymentScenarioGenerator =
injector.get().inject(annotationDeploymentScenarioGenerator);
return annotationDeploymentScenarioGenerator;
}
@Inject
protected Instance<Injector> injector;
private void addTestClass(TestClass testClass, JavaArchive javaArchive) {
javaArchive.addClass(testClass.getJavaClass());
}
private boolean isTestable(TestClass testClass) {
return !testClass.isAnnotationPresent(RunAsClient.class);
}
private void replaceManifest(
Archive<?> archive, ByteArrayAsset byteArrayAsset) {
archive.delete(MANIFEST_PATH);
archive.add(byteArrayAsset, MANIFEST_PATH);
}
private File bndFile = new File("bnd.bnd");
private File commonBndFile;
}