final DeploymentUnit parent = deploymentUnit.getParent();
final DeploymentUnit topLevelDeployment = parent == null ? deploymentUnit : parent;
final VirtualFile topLevelRoot = topLevelDeployment.getAttachment(Attachments.DEPLOYMENT_ROOT).getRoot();
final ExternalModuleService externalModuleService = topLevelDeployment.getAttachment(Attachments.EXTERNAL_MODULE_SERVICE);
final ResourceRoot deploymentRoot = deploymentUnit.getAttachment(Attachments.DEPLOYMENT_ROOT);
//These are resource roots that are already accessible by default
//such as ear/lib jars an web-inf/lib jars
final Set<VirtualFile> existingAccessibleRoots = new HashSet<VirtualFile>();
final Map<VirtualFile, ResourceRoot> subDeployments = new HashMap<VirtualFile, ResourceRoot>();
for (ResourceRoot root : DeploymentUtils.allResourceRoots(topLevelDeployment)) {
if (SubDeploymentMarker.isSubDeployment(root)) {
subDeployments.put(root.getRoot(), root);
} else if (ModuleRootMarker.isModuleRoot(root)) {
//top level module roots are already accessible, as they are either
//ear/lib jars, or jars that are already part of the deployment
existingAccessibleRoots.add(root.getRoot());
}
}
final ArrayDeque<RootEntry> resourceRoots = new ArrayDeque<RootEntry>();
if (deploymentUnit.getParent() != null) {
//top level deployments already had their exiting roots processed above
for (ResourceRoot root : DeploymentUtils.allResourceRoots(deploymentUnit)) {
if (ModuleRootMarker.isModuleRoot(root)) {
//if this is a sub deployment of an ear we need to make sure we don't
//re-add existing module roots as class path entries
//this will mainly be WEB-INF/(lib|classes) entries
existingAccessibleRoots.add(root.getRoot());
}
}
}
for (ResourceRoot root : DeploymentUtils.allResourceRoots(deploymentUnit)) {
//add this to the list of roots to be processed
resourceRoots.add(new RootEntry(deploymentUnit, root));
}
// build a map of the additional module locations
// note that if a resource root has been added to two different additional modules
// and is then referenced via a Class-Path entry the behaviour is undefined
final Map<VirtualFile, AdditionalModuleSpecification> additionalModules = new HashMap<VirtualFile, AdditionalModuleSpecification>();
for (AdditionalModuleSpecification module : topLevelDeployment.getAttachmentList(Attachments.ADDITIONAL_MODULES)) {
for (ResourceRoot additionalModuleResourceRoot : module.getResourceRoots()) {
additionalModules.put(additionalModuleResourceRoot.getRoot(), module);
}
}
//additional resource roots may be added as
while (!resourceRoots.isEmpty()) {
final RootEntry entry = resourceRoots.pop();
final ResourceRoot resourceRoot = entry.resourceRoot;
final Attachable target = entry.target;
//if this is a top level deployment we do not want to process sub deployments
if (SubDeploymentMarker.isSubDeployment(resourceRoot) && resourceRoot != deploymentRoot) {
continue;
}
final String[] items = getClassPathEntries(resourceRoot);
for (final String item : items) {
if(item.isEmpty()) {
continue;
}
//first try and resolve relative to the manifest resource root
final VirtualFile classPathFile = resourceRoot.getRoot().getParent().getChild(item);
//then resolve relative to the deployment root
final VirtualFile topLevelClassPathFile = deploymentRoot.getRoot().getParent().getChild(item);
if (item.startsWith("/")) {
final ModuleIdentifier moduleIdentifier = externalModuleService.addExternalModule(item);
target.addToAttachmentList(Attachments.CLASS_PATH_ENTRIES, moduleIdentifier);
ServerLogger.DEPLOYMENT_LOGGER.debugf("Resource %s added as external jar %s", classPathFile, resourceRoot.getRoot());
} else {
if (classPathFile.exists()) {
handlingExistingClassPathEntry(deploymentUnit, resourceRoots, topLevelDeployment, topLevelRoot, subDeployments, additionalModules, existingAccessibleRoots, resourceRoot, target, classPathFile);