WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
assert warMetaData != null;
List<ResourceRoot> resourceRoots = deploymentUnit.getAttachment(Attachments.RESOURCE_ROOTS);
assert resourceRoots != null;
WebMetaData specMetaData = warMetaData.getWebMetaData();
boolean isComplete = false;
if (specMetaData != null) {
if (specMetaData instanceof Web25MetaData) {
isComplete |= ((Web25MetaData) specMetaData).isMetadataComplete();
} else if (specMetaData instanceof Web30MetaData) {
isComplete |= ((Web30MetaData) specMetaData).isMetadataComplete();
} else {
// Any web.xml 2.4 or earlier deployment is metadata complete
isComplete = true;
}
}
// Find all fragments that have been processed by deployers, and place
// them in a map keyed by location
LinkedList<String> order = new LinkedList<String>();
List<WebOrdering> orderings = new ArrayList<WebOrdering>();
HashSet<String> jarsSet = new HashSet<String>();
Set<VirtualFile> overlays = new HashSet<VirtualFile>();
Map<String, VirtualFile> scis = new HashMap<String, VirtualFile>();
boolean fragmentFound = false;
Map<String, WebFragmentMetaData> webFragments = warMetaData.getWebFragmentsMetaData();
for (ResourceRoot resourceRoot : resourceRoots) {
if (resourceRoot.getRoot().getLowerCaseName().endsWith(".jar")) {
jarsSet.add(resourceRoot.getRootName());
// Find overlays
VirtualFile overlay = resourceRoot.getRoot().getChild("META-INF/resources");
if (overlay.exists()) {
overlays.add(overlay);
}
// Find ServletContainerInitializer services
VirtualFile sci = resourceRoot.getRoot()
.getChild("META-INF/services/javax.servlet.ServletContainerInitializer");
if (sci.exists()) {
scis.put(resourceRoot.getRootName(), sci);
}
}
}
if (!isComplete) {
HashSet<String> jarsWithoutFragmentsSet = new HashSet<String>();
jarsWithoutFragmentsSet.addAll(jarsSet);
for (String jarName : webFragments.keySet()) {
fragmentFound = true;
WebFragmentMetaData fragmentMetaData = webFragments.get(jarName);
webFragments.put(jarName, fragmentMetaData);
WebOrdering webOrdering = new WebOrdering();
webOrdering.setName(fragmentMetaData.getName());
webOrdering.setJar(jarName);
jarsWithoutFragmentsSet.remove(jarName);
if (fragmentMetaData.getOrdering() != null) {
if (fragmentMetaData.getOrdering().getAfter() != null) {
for (OrderingElementMetaData orderingElementMetaData : fragmentMetaData.getOrdering().getAfter()
.getOrdering()) {
if (orderingElementMetaData.isOthers()) {
webOrdering.setAfterOthers(true);
} else {
webOrdering.addAfter(orderingElementMetaData.getName());
}
}
}
if (fragmentMetaData.getOrdering().getBefore() != null) {
for (OrderingElementMetaData orderingElementMetaData : fragmentMetaData.getOrdering().getBefore()
.getOrdering()) {
if (orderingElementMetaData.isOthers()) {
webOrdering.setBeforeOthers(true);
} else {
webOrdering.addBefore(orderingElementMetaData.getName());
}
}
}
}
orderings.add(webOrdering);
}
// If there is no fragment, still consider it for ordering as a
// fragment specifying no name and no order
for (String jarName : jarsWithoutFragmentsSet) {
WebOrdering ordering = new WebOrdering();
ordering.setJar(jarName);
orderings.add(ordering);
}
}
if (!fragmentFound) {
// Drop the order as there is no fragment in the webapp
orderings.clear();
}
// Generate web fragments parsing order
AbsoluteOrderingMetaData absoluteOrderingMetaData = null;
if (!isComplete && specMetaData instanceof Web30MetaData) {
absoluteOrderingMetaData = ((Web30MetaData) specMetaData).getAbsoluteOrdering();
}
if (absoluteOrderingMetaData != null) {
// Absolute ordering from web.xml, any relative fragment ordering is
// ignored
int otherPos = -1;
int i = 0;
for (OrderingElementMetaData orderingElementMetaData : absoluteOrderingMetaData.getOrdering()) {
if (orderingElementMetaData.isOthers()) {
if (otherPos >= 0) {
throw new DeploymentUnitProcessingException("Duplicate others in absolute ordering");
}
otherPos = i;
} else {
boolean found = false;
for (WebOrdering ordering : orderings) {
if (orderingElementMetaData.getName().equals(ordering.getName())) {
order.add(ordering.getJar());
jarsSet.remove(ordering.getJar());
found = true;
break;
}
}
if (!found)
throw new DeploymentUnitProcessingException("Could not resolve name in absolute ordering: "
+ orderingElementMetaData.getName());
}
i++;
}
if (otherPos >= 0) {
order.addAll(otherPos, jarsSet);
jarsSet.clear();
}
} else if (orderings.size() > 0) {
// Resolve relative ordering
try {
resolveOrder(orderings, order);
} catch (IllegalStateException e) {
throw new DeploymentUnitProcessingException("Invalid ordering", e);
}
jarsSet.clear();
} else {
// No order specified
order.addAll(jarsSet);
jarsSet.clear();
warMetaData.setNoOrder(true);
}
Logger log = Logger.getLogger("org.jboss.web");
if (log.isDebugEnabled()) {
StringBuilder builder = new StringBuilder();
builder.append("Resolved order: [ ");
for (String jar : order) {
builder.append(jar).append(' ');
}
builder.append(']');
log.debug(builder.toString());
}
warMetaData.setOrder(order);
warMetaData.setOverlays(overlays);
warMetaData.setScis(scis);
Map<String, WebMetaData> annotationsMetaData = warMetaData.getAnnotationsMetaData();
// The fragments and corresponding annotations will need to be merged in
// order
// For each JAR in the order:
// - Merge the annotation metadata into the fragment meta data
// (unless the fragment exists and is meta data complete)
// - Merge the fragment metadata into merged fragment meta data
WebCommonMetaData mergedFragmentMetaData = new WebCommonMetaData();
if (specMetaData == null) {
// If there is no web.xml, it has to be considered to be the latest version
specMetaData = new Web30MetaData();
specMetaData.setVersion("3.0");
}
// Augment with meta data from annotations in /WEB-INF/classes
WebMetaData classesAnnotatedMetaData = annotationsMetaData.get("classes");
if (classesAnnotatedMetaData != null) {
if (isComplete) {
// Discard @WebFilter, @WebListener and @WebServlet
classesAnnotatedMetaData.setFilters(null);
classesAnnotatedMetaData.setFilterMappings(null);
classesAnnotatedMetaData.setListeners(null);
classesAnnotatedMetaData.setServlets(null);
classesAnnotatedMetaData.setServletMappings(null);
}
WebCommonMetaDataMerger.augment(specMetaData, classesAnnotatedMetaData, null, true);
}
// Augment with meta data from fragments and annotations from the
// corresponding JAR
for (String jar : order) {
WebFragmentMetaData webFragmentMetaData = webFragments.get(jar);
if (webFragmentMetaData == null) {
webFragmentMetaData = new WebFragmentMetaData();
// Add non overriding default distributable flag
webFragmentMetaData.setDistributable(new EmptyMetaData());
}
WebMetaData jarAnnotatedMetaData = annotationsMetaData.get(jar);
if ((isComplete || webFragmentMetaData.isMetadataComplete()) && jarAnnotatedMetaData != null) {
// Discard @WebFilter, @WebListener and @WebServlet
jarAnnotatedMetaData.setFilters(null);
jarAnnotatedMetaData.setFilterMappings(null);
jarAnnotatedMetaData.setListeners(null);
jarAnnotatedMetaData.setServlets(null);
jarAnnotatedMetaData.setServletMappings(null);
}
if (jarAnnotatedMetaData != null) {
// Merge annotations corresponding to the JAR
WebCommonMetaDataMerger.augment(webFragmentMetaData, jarAnnotatedMetaData, null, true);
}
// Merge fragment meta data according to the conflict rules
try {
WebCommonMetaDataMerger.augment(mergedFragmentMetaData, webFragmentMetaData, specMetaData, false);
} catch (Exception e) {
throw new DeploymentUnitProcessingException("Deployment error processing fragment for JAR: " + jar, e);
}
}
// Augment with meta data from annotations from JARs excluded from the
// order
for (String jar : jarsSet) {
WebFragmentMetaData webFragmentMetaData = new WebFragmentMetaData();
// Add non overriding default distributable flag
webFragmentMetaData.setDistributable(new EmptyMetaData());
WebMetaData jarAnnotatedMetaData = annotationsMetaData.get(jar);
if (jarAnnotatedMetaData != null) {
// Discard @WebFilter, @WebListener and @WebServlet
jarAnnotatedMetaData.setFilters(null);
jarAnnotatedMetaData.setFilterMappings(null);
jarAnnotatedMetaData.setListeners(null);
jarAnnotatedMetaData.setServlets(null);
jarAnnotatedMetaData.setServletMappings(null);
}
if (jarAnnotatedMetaData != null) {
// Merge annotations corresponding to the JAR
WebCommonMetaDataMerger.augment(webFragmentMetaData, jarAnnotatedMetaData, null, true);
}