addOutput(WEB_SCIS_ATTACHMENT_NAME);
}
public void deploy(DeploymentUnit unit) throws DeploymentException
{
WebMetaData specMetaData = unit.getAttachment(WebMetaData.class);
JBossWebMetaData metaData = unit.getAttachment(JBossWebMetaData.class);
if(specMetaData == null && metaData == null)
return;
// Check metadata-complete (see AnnotationMetaDataDeployer)
boolean isComplete = this.isMetaDataCompleteIsDefault();
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>();
VirtualFile webInfLib = null;
boolean fragmentFound = false;
HashMap<String, WebFragmentMetaData> webFragments = new HashMap<String, WebFragmentMetaData>();
if (unit instanceof VFSDeploymentUnit)
{
VFSDeploymentUnit vfsUnit = (VFSDeploymentUnit) unit;
webInfLib = vfsUnit.getFile("WEB-INF/lib");
if (webInfLib != null)
{
List<VirtualFile> jars = webInfLib.getChildren();
for (VirtualFile jar : jars)
{
jarsSet.add(jar.getName());
// Find overlays
VirtualFile overlay = jar.getChild("META-INF/resources");
if (overlay.exists())
{
overlays.add(overlay);
}
// Find ServletContainerInitializer services
VirtualFile sci = jar.getChild("META-INF/services/javax.servlet.ServletContainerInitializer");
if (sci.exists())
{
scis.put(jar.getName(), sci);
}
}
}
if (!isComplete)
{
String base = unit.getName();
int pos = base.indexOf(':');
if (pos > 0)
{
base = base.substring(pos);
}
Iterator<String> attachementNames = unit.getAttachments().keySet().iterator();
HashSet<String> jarsWithoutFragmentsSet = new HashSet<String>();
jarsWithoutFragmentsSet.addAll(jarsSet);
while (attachementNames.hasNext())
{
String location = attachementNames.next();
Object attachement = unit.getAttachment(location);
if (attachement != null && attachement instanceof WebFragmentMetaData)
{
if (!location.startsWith(WebFragmentMetaData.class.getName() + ":"))
{
// If there is only one fragment, it will also get mapped as this attachement
continue;
}
String relativeLocation = "/" + location.substring(WebFragmentMetaData.class.getName().length() + 1);
String jarName = null;
if (relativeLocation.startsWith("/WEB-INF/lib/"))
{
jarName = relativeLocation.substring("/WEB-INF/lib/".length());
pos = jarName.indexOf('/');
if (pos > 0)
jarName = jarName.substring(0, pos);
}
if (jarName == null)
{
continue;
}
fragmentFound = true;
WebFragmentMetaData fragmentMetaData = (WebFragmentMetaData) attachement;
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 DeploymentException("Duplicate others in absolute ordering");
}
otherPos = i;
}
else
{
for (WebOrdering ordering : orderings)
{
if (orderingElementMetaData.getName().equals(ordering.getName())) {
order.add(ordering.getJar());
jarsSet.remove(ordering.getJar());
break;
}
}
}
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)
{
DeploymentException.rethrowAsDeploymentException("Invalid ordering", e);
}
jarsSet.clear();
}
else
{
// No order specified
order.addAll(jarsSet);
jarsSet.clear();
unit.addAttachment(WEB_NOORDER_ATTACHMENT_NAME, Boolean.TRUE);
}
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());
}
unit.addAttachment(WEB_ORDER_ATTACHMENT_NAME, order);
unit.addAttachment(WEB_OVERLAYS_ATTACHMENT_NAME, overlays);
unit.addAttachment(WEB_SCIS_ATTACHMENT_NAME, scis);
// 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");
}
String key = AnnotationMetaDataDeployer.WEB_ANNOTATED_ATTACHMENT_NAME + ":classes";
// Augment with meta data from annotations in /WEB-INF/classes
WebMetaData classesAnnotatedMetaData = unit.getAttachment(key, WebMetaData.class);
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);
}
specMetaData.augment(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());
}
key = AnnotationMetaDataDeployer.WEB_ANNOTATED_ATTACHMENT_NAME + ":" + jar;
WebMetaData jarAnnotatedMetaData = unit.getAttachment(key, WebMetaData.class);
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
webFragmentMetaData.augment(jarAnnotatedMetaData, null, true);
}
// Merge fragment meta data according to the conflict rules
try
{
mergedFragmentMetaData.augment(webFragmentMetaData, specMetaData, false);
}
catch (Exception e)
{
DeploymentException.rethrowAsDeploymentException("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());
key = AnnotationMetaDataDeployer.WEB_ANNOTATED_ATTACHMENT_NAME + ":" + jar;
WebMetaData jarAnnotatedMetaData = unit.getAttachment(key, WebMetaData.class);
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
webFragmentMetaData.augment(jarAnnotatedMetaData, null, true);