Package org.jboss.as.server.deployment.module

Source Code of org.jboss.as.server.deployment.module.ManifestClassPathProcessor

/*
* JBoss, Home of Professional Open Source.
* Copyright 2010, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This 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 software 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.as.server.deployment.module;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import org.jboss.as.server.deployment.Attachable;
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.DeploymentUtils;
import org.jboss.as.server.deployment.SubDeploymentMarker;
import org.jboss.as.server.moduleservice.ExternalModuleService;
import org.jboss.logging.Logger;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.vfs.VirtualFile;

/**
* A processor which adds class path entries for each manifest entry.
* <p/>
* This processor examines all class path entries found.
* <ul>
* <li>
* If the Class-Path entry points to a jar in ear/lib then it is ignored.
* </li>
* <li>
* If the Class-Path entry is external to the deployment then it is handled by the external jar service.</li>
* <li>
* If the entry refers to a sibling deployment then a dependency is added on that deployment. If this deployment is
* not present then this deployment will block until it is.</li>
* <li>
* If the Class-Path entry points to a jar inside the ear that is not a deployment and not a /lib jar then a reference is added
* to this jars {@link AdditionalModuleSpecification}</li>
* </ul>
*
* @author Stuart Douglas
*/
public final class ManifestClassPathProcessor implements DeploymentUnitProcessor {

    private static final Logger log = Logger.getLogger("org.jboss.as.server.deployment");

    private static final String[] EMPTY_STRING_ARRAY = {};

    /**
     * {@inheritDoc}
     */
    public void deploy(final DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
        final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();

        //if this has already been handled by the ear class path processor
        if (deploymentUnit.getAttachment(Attachments.CLASS_PATH_ENTRIES) != null) {
            return;
        }

        final List<ResourceRoot> resourceRoots = DeploymentUtils.allResourceRoots(deploymentUnit);

        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 List<AdditionalModuleSpecification> additionalModuleList = topLevelDeployment.getAttachment(Attachments.ADDITIONAL_MODULES);
        final List<ResourceRoot> topLevelResourceRoots = topLevelDeployment.getAttachment(Attachments.RESOURCE_ROOTS);
        final ResourceRoot deploymentRoot = deploymentUnit.getAttachment(Attachments.DEPLOYMENT_ROOT);
        final List<DeploymentUnit> subDeployments;
        if (deploymentUnit.getParent() == null) {
            subDeployments = deploymentUnit.getAttachmentList(Attachments.SUB_DEPLOYMENTS);
        } else {
            subDeployments = deploymentUnit.getParent().getAttachmentList(Attachments.SUB_DEPLOYMENTS);
        }
        final Map<VirtualFile, ModuleIdentifier> subDeploymentModules = new HashMap<VirtualFile, ModuleIdentifier>();
        for (DeploymentUnit deployment : subDeployments) {
            final ResourceRoot root = deployment.getAttachment(Attachments.DEPLOYMENT_ROOT);
            final ModuleIdentifier identifier = deployment.getAttachment(Attachments.MODULE_IDENTIFIER);
            if (root == null || identifier == null) {
                continue;
            }
            subDeploymentModules.put(root.getRoot(), identifier);
        }

        // build a map of the additional module locations
        final Map<VirtualFile, AdditionalModuleSpecification> additionalModules;
        if (additionalModuleList == null) {
            additionalModules = Collections.emptyMap();
        } else {
            additionalModules = new HashMap<VirtualFile, AdditionalModuleSpecification>();
            for (AdditionalModuleSpecification module : additionalModuleList) {
                for (ResourceRoot additionalModuleResourceRoot : module.getResourceRoots()) {
                    additionalModules.put(additionalModuleResourceRoot.getRoot(), module);
                }
            }
        }
        // build a set of ear/lib jars. references to these classes can be ignored as they are already on the class-path
        final Set<VirtualFile> earLibJars = new HashSet<VirtualFile>();
        if (deploymentUnit.getParent() != null && topLevelResourceRoots != null) {
            for (ResourceRoot resourceRoot : topLevelResourceRoots) {
                if (ModuleRootMarker.isModuleRoot(resourceRoot) && !SubDeploymentMarker.isSubDeployment(resourceRoot)) {
                    earLibJars.add(resourceRoot.getRoot());
                }
            }
        }

        for (ResourceRoot resourceRoot : resourceRoots) {
            if (SubDeploymentMarker.isSubDeployment(resourceRoot) && resourceRoot != deploymentRoot) {
                continue;
            }
            // if this resource root represents an additional module then we need
            // to add the class path entry to the additional module
            final Attachable target;
            if (additionalModules.containsKey(resourceRoot.getRoot())) {
                target = additionalModules.get(resourceRoot.getRoot());
            } else {
                target = deploymentUnit;
            }
            final String[] items = getClassPathEntries(resourceRoot);
            for (String item : items) {
                //first try and resolve relative to the manifest resource root
                boolean found = false;
                final VirtualFile classPathFile = resourceRoot.getRoot().getParent().getChild(item);
                final VirtualFile topLevelClassPathFile = deploymentRoot.getRoot().getParent().getChild(item);
                if (isInside(classPathFile, topLevelRoot)) {
                    if (earLibJars.contains(classPathFile)) {
                        log.debugf("Class-Path entry %s in %s ignored, as target is in or referenced by /lib", classPathFile,
                                resourceRoot.getRoot());
                    } else if (additionalModules.containsKey(classPathFile)) {
                        target.addToAttachmentList(Attachments.CLASS_PATH_ENTRIES, additionalModules.get(classPathFile)
                                .getModuleIdentifier());
                    } else if (subDeploymentModules.containsKey(classPathFile)) {
                        target.addToAttachmentList(Attachments.CLASS_PATH_ENTRIES, subDeploymentModules.get(classPathFile));
                    } else if (additionalModules.containsKey(topLevelClassPathFile)) {
                        //if not found try resolving the class path entry from the deployment root
                        target.addToAttachmentList(Attachments.CLASS_PATH_ENTRIES, additionalModules.get(topLevelClassPathFile)
                                .getModuleIdentifier());
                    } else if (subDeploymentModules.containsKey(topLevelClassPathFile)) {
                        //if not found try resolving the class path entry from the deployment root
                        target.addToAttachmentList(Attachments.CLASS_PATH_ENTRIES, subDeploymentModules.get(topLevelClassPathFile));
                    } else if(classPathFile.exists() && classPathFile.isDirectory()) {

                    } else if(topLevelClassPathFile.exists() && topLevelClassPathFile.isDirectory()) {

                    } else {
                        log.warn("Class Path entry " + item + " in " + resourceRoot.getRoot() + "  does not point to a valid jar for a Class-Path reference.");
                    }
                } else if (item.startsWith("/")) {
                    ModuleIdentifier moduleIdentifier = externalModuleService.addExternalModule(item);
                    target.addToAttachmentList(Attachments.CLASS_PATH_ENTRIES, moduleIdentifier);
                    log.debugf("Resource %s added as external jar %s", classPathFile, resourceRoot.getRoot());
                } else {
                    //ignore
                    log.debugf("Ignoring missing Class-Path entry %s", classPathFile);
                }
            }
        }
    }


    private static boolean isInside(VirtualFile classPathFile, VirtualFile toplevelRoot) {
        VirtualFile[] parentPaths = classPathFile.getParentFiles();
        for (VirtualFile path : parentPaths) {
            if (path == toplevelRoot) {
                // inside the deployment
                return true;
            }
        }
        return false;
    }

    private static String[] getClassPathEntries(final ResourceRoot resourceRoot) {
        final Manifest manifest = resourceRoot.getAttachment(Attachments.MANIFEST);
        if (manifest == null) {
            // no class path to process!
            return EMPTY_STRING_ARRAY;
        }
        final String classPathString = manifest.getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
        if (classPathString == null) {
            // no entry
            return EMPTY_STRING_ARRAY;
        }
        if (classPathString.trim().isEmpty()) {
            return EMPTY_STRING_ARRAY;
        }
        return classPathString.trim().split("\\s+");
    }

    /**
     * {@inheritDoc}
     */
    public void undeploy(final DeploymentUnit context) {
    }
}
TOP

Related Classes of org.jboss.as.server.deployment.module.ManifestClassPathProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.