Skip to content

Commit

Permalink
Merge pull request #25 from jbosgi/JBOSGI-794_9.x
Browse files Browse the repository at this point in the history
JBOSGI-794 (9.x) WAB Fragment resources are not available through host
  • Loading branch information
arcivanov committed May 17, 2016
2 parents f513f39 + 23272f9 commit e2f9ce5
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 30 deletions.
Expand Up @@ -73,8 +73,11 @@ public class WebAppTestCase {
static final String BUNDLE_D_WAB = "bundle-d.wab";
static final String BUNDLE_E_JAR = "bundle-e.jar";
static final String BUNDLE_F_WAB = "bundle-f.wab";
static final String BUNDLE_G_HOST_JAR = "bundle-g.jar";
static final String BUNDLE_H_FRAG_JAR = "bundle-h.jar";

static final Asset STRING_ASSET = new StringAsset("Hello from Resource");
static final Asset STRING_FRAG_ASSET = new StringAsset("Hello from Fragment Resource");

@ArquillianResource
Deployer deployer;
Expand Down Expand Up @@ -197,6 +200,82 @@ public void testSimpleBundleWithJarExtension() throws Exception {
}
}

@Test
// JBOSGI-794
public void testFragmentAndHostBundleWithJarExtension() throws Exception {
// Fragment is started then host is started
deployer.deploy(BUNDLE_H_FRAG_JAR);
try {
deployer.deploy(BUNDLE_G_HOST_JAR);
try {
String result = performCall("/bundle-g/servlet?input=Hello");
Assert.assertEquals("Simple Servlet called with input=Hello", result);
result = performCall("/bundle-g/message.txt");
Assert.assertEquals("Hello from Resource", result);
result = performCall("/bundle-g/message-frag.txt");
Assert.assertEquals("Hello from Fragment Resource", result);
} finally {
deployer.undeploy(BUNDLE_G_HOST_JAR);
}
} finally {
deployer.undeploy(BUNDLE_H_FRAG_JAR);
}
}

@Test
// JBOSGI-794
public void testHostBundleAndFragmentWithJarExtension() throws Exception {
// Bundle is installed but not started, then fragment is started
InputStream input = deployer.getDeployment(BUNDLE_G_HOST_JAR);
Bundle bundle = context.installBundle(BUNDLE_G_HOST_JAR, input);
try {
Assert.assertEquals("INSTALLED", Bundle.INSTALLED, bundle.getState());
deployer.deploy(BUNDLE_H_FRAG_JAR);
bundle.start();
Assert.assertEquals("ACTIVE", Bundle.ACTIVE, bundle.getState());
try {
String result = performCall("/bundle-g/servlet?input=Hello");
Assert.assertEquals("Simple Servlet called with input=Hello", result);
result = performCall("/bundle-g/message.txt");
Assert.assertEquals("Hello from Resource", result);
result = performCall("/bundle-g/message-frag.txt");
Assert.assertEquals("Hello from Fragment Resource", result);
} finally {
deployer.undeploy(BUNDLE_H_FRAG_JAR);
}
} finally {
deployer.undeploy(BUNDLE_G_HOST_JAR);
}
}

@Test
// JBOSGI-794
public void testHostBundleAndFragmentWithJarExtensionSimulateConcurrentStartup() throws Exception {
// Bundle is installed, fragment is installed, then host is started
InputStream input = deployer.getDeployment(BUNDLE_G_HOST_JAR);
Bundle hostBundle = context.installBundle(BUNDLE_G_HOST_JAR, input);
try {
Assert.assertEquals("INSTALLED", Bundle.INSTALLED, hostBundle.getState());
input = deployer.getDeployment(BUNDLE_H_FRAG_JAR);
Bundle fragBundle = context.installBundle(BUNDLE_H_FRAG_JAR, input);
try {
Assert.assertEquals("INSTALLED", Bundle.INSTALLED, fragBundle.getState());
hostBundle.start();
Assert.assertEquals("ACTIVE", Bundle.ACTIVE, hostBundle.getState());
String result = performCall("/bundle-g/servlet?input=Hello");
Assert.assertEquals("Simple Servlet called with input=Hello", result);
result = performCall("/bundle-g/message.txt");
Assert.assertEquals("Hello from Resource", result);
result = performCall("/bundle-g/message-frag.txt");
Assert.assertEquals("Hello from Fragment Resource", result);
} finally {
deployer.undeploy(BUNDLE_H_FRAG_JAR);
}
} finally {
deployer.undeploy(BUNDLE_G_HOST_JAR);
}
}

@Test
public void testDeferredBundleWithWabExtension() throws Exception {
InputStream input = deployer.getDeployment(BUNDLE_C_WAB);
Expand Down Expand Up @@ -393,4 +472,43 @@ public InputStream openStream() {
});
return archive;
}

@Deployment(name = BUNDLE_G_HOST_JAR, managed = false, testable = false)
public static Archive<?> getBundleG() {
final JavaArchive archive = ShrinkWrap.create(JavaArchive.class, BUNDLE_G_HOST_JAR);
archive.addClasses(SimpleServlet.class, Echo.class);
archive.addAsResource(STRING_ASSET, "message.txt");
archive.setManifest(new Asset() {
@Override
public InputStream openStream() {
OSGiManifestBuilder builder = OSGiManifestBuilder.newInstance();
builder.addBundleSymbolicName(archive.getName());
builder.addBundleManifestVersion(2);
builder.addImportPackages(PostConstruct.class, WebServlet.class);
builder.addImportPackages(Servlet.class, HttpServlet.class);
builder.addManifestHeader("Web-ContextPath", "/bundle-g");
builder.addRequiredCapabilities("fragment-h");
return builder.openStream();
}
});
return archive;
}

@Deployment(name = BUNDLE_H_FRAG_JAR, managed = false, testable = false)
public static Archive<?> getBundleH() {
final JavaArchive archive = ShrinkWrap.create(JavaArchive.class, BUNDLE_H_FRAG_JAR);
archive.addAsResource(STRING_FRAG_ASSET, "message-frag.txt");
archive.setManifest(new Asset() {
@Override
public InputStream openStream() {
OSGiManifestBuilder builder = OSGiManifestBuilder.newInstance();
builder.addBundleSymbolicName(archive.getName());
builder.addBundleManifestVersion(2);
builder.addFragmentHost(BUNDLE_G_HOST_JAR);
builder.addProvidedCapabilities("fragment-h");
return builder.openStream();
}
});
return archive;
}
}
Expand Up @@ -153,6 +153,11 @@ public void testWebXMLInFragment() throws Exception {
Bundle bundle = FrameworkUtils.getBundles(context, BUNDLE_C_WAB, null)[0];
Enumeration<URL> entries = bundle.findEntries("WEB-INF", "web.xml", true);
Assert.assertNotNull("WEb-INF/web.xml entries found", entries);
// JBOSGI-794
result = performCall("/bundleC/host-message.txt");
Assert.assertEquals("Hello from Host", result);
result = performCall("/bundleC/fragment-message.txt");
Assert.assertEquals("Hello from Fragment", result);
} finally {
deployer.undeploy(BUNDLE_C_WAB);
deployer.undeploy(FRAGMENT_C);
Expand Down
Expand Up @@ -23,6 +23,12 @@

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
Expand All @@ -31,10 +37,12 @@
import org.jboss.as.ee.structure.SpecDescriptorPropertyReplacement;
import org.jboss.as.osgi.OSGiConstants;
import org.jboss.as.osgi.OSGiLogger;
import org.jboss.as.server.deployment.Attachments;
import org.jboss.as.server.deployment.DeploymentPhaseContext;
import org.jboss.as.server.deployment.DeploymentUnit;
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
import org.jboss.as.server.deployment.module.ResourceRoot;
import org.jboss.as.web.common.WarMetaData;
import org.jboss.metadata.merge.web.jboss.JBossWebMetaDataMerger;
import org.jboss.metadata.parser.servlet.WebMetaDataParser;
Expand All @@ -43,6 +51,7 @@
import org.jboss.metadata.web.spec.WebMetaData;
import org.jboss.osgi.resolver.XBundle;
import org.jboss.osgi.resolver.XBundleRevision;
import org.jboss.vfs.VirtualFile;
import org.osgi.framework.namespace.HostNamespace;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
Expand All @@ -55,58 +64,87 @@
*/
public class WebBundleFragmentProcessor implements DeploymentUnitProcessor {

private final Map<XBundleRevision, VirtualFile> fragmentRoots = new HashMap<>();

@Override
public void deploy(final DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
DeploymentUnit depUnit = phaseContext.getDeploymentUnit();
XBundleRevision hostRev = depUnit.getAttachment(OSGiConstants.BUNDLE_REVISION_KEY);
WarMetaData warMetaData = depUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);

if (hostRev != null && hostRev.isFragment()) {
ResourceRoot resourceRoot = depUnit.getAttachment(Attachments.DEPLOYMENT_ROOT);
if (resourceRoot != null) {
synchronized (fragmentRoots) {
fragmentRoots.put(hostRev, resourceRoot.getRoot());
}
}
}

if (warMetaData == null || hostRev == null)
return;

XBundle fragment = null;
List<XBundle> fragments = new ArrayList<XBundle>();

// Get attached fragments
BundleWiring wiring = hostRev.getWiring();
for (BundleWire wire : wiring.getProvidedWires(HostNamespace.HOST_NAMESPACE)) {
fragment = (XBundle) wire.getRequirer().getBundle();
fragments.add((XBundle) wire.getRequirer().getBundle());
break;
}

// No attached fragments
if (fragment == null)
if (fragments.size() == 0)
return;

// Check if the fragment has a web.xml entry
// Check if the first fragment has a web.xml entry
XBundle fragment = fragments.get(0);
URL entry = fragment.getEntry("WEB-INF/web.xml");
if (entry == null)
return;

// Parse the web.xml
WebMetaData fragmentMetaData = null;
try {
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
MetaDataElementParser.DTDInfo dtdInfo = new MetaDataElementParser.DTDInfo();
inputFactory.setXMLResolver(dtdInfo);
XMLStreamReader xmlReader = inputFactory.createXMLStreamReader(entry.openStream());
fragmentMetaData = WebMetaDataParser.parse(xmlReader, dtdInfo, SpecDescriptorPropertyReplacement.propertyReplacer(depUnit));
} catch (XMLStreamException ex) {
OSGiLogger.LOGGER.debugf(ex, "Cannot parse web.xml in fragment: %s", fragment);
} catch (IOException ex) {
OSGiLogger.LOGGER.debugf(ex, "Cannot parse web.xml in fragment: %s", fragment);
if (entry != null) {
// Parse the web.xml
WebMetaData fragmentMetaData = null;
try {
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
MetaDataElementParser.DTDInfo dtdInfo = new MetaDataElementParser.DTDInfo();
inputFactory.setXMLResolver(dtdInfo);
XMLStreamReader xmlReader = inputFactory.createXMLStreamReader(entry.openStream());
fragmentMetaData = WebMetaDataParser.parse(xmlReader, dtdInfo, SpecDescriptorPropertyReplacement.propertyReplacer(depUnit));
} catch (XMLStreamException ex) {
OSGiLogger.LOGGER.errorf(ex, "Cannot parse web.xml in fragment: %s", fragment);
} catch (IOException ex) {
OSGiLogger.LOGGER.errorf(ex, "Cannot parse web.xml in fragment: %s", fragment);
}
// Merge additional {@link WebMetaData}
if (fragmentMetaData != null) {
warMetaData.setWebMetaData(fragmentMetaData);
JBossWebMetaData mergedMetaData = new JBossWebMetaData();
JBossWebMetaData metaData = warMetaData.getMergedJBossWebMetaData();
JBossWebMetaDataMerger.merge(mergedMetaData, metaData, fragmentMetaData);
warMetaData.setMergedJBossWebMetaData(mergedMetaData);
}
}

// Merge additional {@link WebMetaData}
if (fragmentMetaData != null) {
warMetaData.setWebMetaData(fragmentMetaData);
JBossWebMetaData mergedMetaData = new JBossWebMetaData();
JBossWebMetaData metaData = warMetaData.getMergedJBossWebMetaData();
JBossWebMetaDataMerger.merge(mergedMetaData, metaData, fragmentMetaData);
warMetaData.setMergedJBossWebMetaData(mergedMetaData);
Set<VirtualFile> overlays = new LinkedHashSet<>();
synchronized (fragmentRoots) {
for (XBundle frag : fragments) {
VirtualFile fragRoot = fragmentRoots.get(frag.getBundleRevision());
if (fragRoot != null) {
overlays.add(fragRoot);
}
}
}
if (overlays.size() > 0) {
warMetaData.setOverlays(overlays);
}
}

@Override
public void undeploy(final DeploymentUnit depUnit) {
// do nothing
XBundleRevision hostRev = depUnit.getAttachment(OSGiConstants.BUNDLE_REVISION_KEY);
if (hostRev != null && hostRev.isFragment()) {
synchronized (fragmentRoots) {
fragmentRoots.remove(hostRev);
}
}
}
}
Expand Up @@ -84,9 +84,8 @@ public void deploy(final DeploymentPhaseContext phaseContext) throws DeploymentU

// Check for attached BundleInfo
BundleInfo info = depUnit.getAttachment(OSGiConstants.BUNDLE_INFO_KEY);
OSGiMetaData metadata = null;
if (info != null) {
metadata = info.getOSGiMetadata();
OSGiMetaData metadata = info.getOSGiMetadata();

if (deployment == null) {
deployment = DeploymentFactory.createDeployment(info);
Expand Down Expand Up @@ -158,8 +157,9 @@ public void deploy(final DeploymentPhaseContext phaseContext) throws DeploymentU
}
excludedSubsystems.addAll(Arrays.asList(EXCLUDED_SUBSYSTEMS));

OSGiMetaData metadata = depUnit.getAttachment(OSGiConstants.OSGI_METADATA_KEY);
if (metadata != null && metadata.isFragment()) {
// JBOSGI-751, JBOSGI-761, JBOSGI-793
// JBOSGI-751, JBOSGI-761, JBOSGI-793, JBOSGI-794
excludedSubsystems.add("webservices");
excludedSubsystems.add("ee");
excludedSubsystems.add("ejb3");
Expand Down

0 comments on commit e2f9ce5

Please sign in to comment.