org.jboss.tools.maven.jbosspackaging.configurators.SarProjectConfigurator.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.tools.maven.jbosspackaging.configurators.SarProjectConfigurator.java

Source

/*******************************************************************************
 * Copyright (c) 2011 Red Hat, Inc.
 * Distributed under license by Red Hat, Inc. All rights reserved.
 * This program is made available under the terms of the
 * Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package org.jboss.tools.maven.jbosspackaging.configurators;

import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.project.MavenProject;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jst.j2ee.classpathdep.IClasspathDependencyConstants;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
import org.eclipse.m2e.core.project.MavenProjectChangedEvent;
import org.eclipse.m2e.core.project.MavenProjectUtils;
import org.eclipse.m2e.core.project.configurator.AbstractProjectConfigurator;
import org.eclipse.m2e.core.project.configurator.ProjectConfigurationRequest;
import org.eclipse.m2e.jdt.internal.MavenClasspathHelpers;
import org.eclipse.m2e.wtp.ArtifactHelper;
import org.eclipse.m2e.wtp.ResourceCleaner;
import org.eclipse.m2e.wtp.WTPProjectsUtil;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.ModuleCoreNature;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
import org.eclipse.wst.common.componentcore.resources.IVirtualReference;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
import org.eclipse.wst.common.project.facet.core.IFacetedProject;
import org.eclipse.wst.common.project.facet.core.IFacetedProject.Action;
import org.eclipse.wst.common.project.facet.core.IProjectFacet;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
import org.jboss.ide.eclipse.as.ui.mbeans.project.IJBossSARFacetDataModelProperties;
import org.jboss.ide.eclipse.as.ui.mbeans.project.JBossSARFacetDataModelProvider;
import org.jboss.tools.maven.core.IJBossMavenConstants;
import org.jboss.tools.maven.core.internal.project.facet.MavenFacetInstallDataModelProvider;

/**
 * 
 * @author Fred Bricon
 * 
 */
public class SarProjectConfigurator extends AbstractProjectConfigurator {

    public static final IProjectFacet JBOSS_SAR_FACET;
    public static final IProjectFacetVersion JBOSS_SAR_FACET_VERSION_1_0;
    public static final ArtifactFilter SCOPE_FILTER_RUNTIME = new ScopeArtifactFilter(Artifact.SCOPE_RUNTIME);
    protected static final IProjectFacet m2Facet;
    protected static final IProjectFacetVersion m2Version;
    private static final IClasspathAttribute NONDEPENDENCY_ATTRIBUTE = JavaCore
            .newClasspathAttribute(IClasspathDependencyConstants.CLASSPATH_COMPONENT_NON_DEPENDENCY, "");
    static {
        JBOSS_SAR_FACET = ProjectFacetsManager.getProjectFacet("jst.jboss.sar");
        JBOSS_SAR_FACET_VERSION_1_0 = JBOSS_SAR_FACET.getVersion("1.0");//$NON-NLS-1$
        m2Facet = ProjectFacetsManager.getProjectFacet("jboss.m2"); //$NON-NLS-1$
        m2Version = m2Facet.getVersion("1.0"); //$NON-NLS-1$
    }

    @Override
    public void configure(ProjectConfigurationRequest request, IProgressMonitor monitor) throws CoreException {

        MavenProject mavenProject = request.getMavenProject();
        IProject project = request.getProject();

        markerManager.deleteMarkers(project, MavenSarConstants.SAR_CONFIGURATION_ERROR_MARKER_ID);

        if (!getExpectedPackage().equals(mavenProject.getPackaging())) {
            return;
        }

        IFacetedProject facetedProject = ProjectFacetsManager.create(project, true, monitor);

        Set<Action> actions = new LinkedHashSet<Action>();

        IMavenProjectFacade facade = request.getMavenProjectFacade();

        ResourceCleaner fileCleaner = new ResourceCleaner(project);
        addFoldersToClean(fileCleaner, facade);

        IPath source = facade.getResourceLocations()[0];

        WTPProjectsUtil.installJavaFacet(actions, project, facetedProject);
        if (!actions.isEmpty()) {
            facetedProject.modify(actions, monitor);
        }
        installSarFacet(facetedProject, source, monitor);

        installM2Facet(facetedProject, monitor);

        ModuleCoreNature.addModuleCoreNatureIfNecessary(project, monitor);

        removeTestFolderLinks(project, mavenProject, monitor, "/");

        WTPProjectsUtil.setNonDependencyAttributeToContainer(project, monitor);

        WTPProjectsUtil.removeWTPClasspathContainer(project);

        fileCleaner.cleanUp();
    }

    //TODO Fix/refactor that method from WTPProjectUtils in m2e-wtp 0.14.x
    public static void removeTestFolderLinks(IProject project, MavenProject mavenProject, IProgressMonitor monitor,
            String folder) throws CoreException {
        IVirtualComponent component = ComponentCore.createComponent(project);
        if (component != null) {
            IVirtualFolder jsrc = component.getRootFolder().getFolder(folder);
            for (IPath location : MavenProjectUtils.getSourceLocations(project,
                    mavenProject.getTestCompileSourceRoots())) {
                if (location == null)
                    continue;
                jsrc.removeLink(location, 0, monitor);
            }
            for (IPath location : MavenProjectUtils.getResourceLocations(project,
                    mavenProject.getTestResources())) {
                if (location == null)
                    continue;
                jsrc.removeLink(location, 0, monitor);
            }
        }
    }

    private void installM2Facet(IFacetedProject fproj, IProgressMonitor monitor) throws CoreException {
        if (!fproj.hasProjectFacet(m2Facet)) {
            IDataModel config = (IDataModel) new MavenFacetInstallDataModelProvider().create();
            config.setBooleanProperty(IJBossMavenConstants.MAVEN_PROJECT_EXISTS, true);
            fproj.installProjectFacet(m2Version, config, monitor);
        }
    }

    private void installSarFacet(IFacetedProject fproj, IPath source, IProgressMonitor monitor)
            throws CoreException {
        if (!fproj.hasProjectFacet(JBOSS_SAR_FACET)) {
            IProjectFacetVersion facetVersion = JBOSS_SAR_FACET_VERSION_1_0;
            IStatus status = facetVersion.getConstraint().check(fproj.getProjectFacets());
            if (status.isOK()) {
                IDataModel config = (IDataModel) new JBossSARFacetDataModelProvider().create();
                config.setProperty(IJBossSARFacetDataModelProperties.SAR_CONTENT_FOLDER, source.toPortableString());
                fproj.installProjectFacet(facetVersion, config, monitor);
            } else {
                addErrorMarker(fproj.getProject(), facetVersion + " can not be installed : " + status.getMessage());
                for (IStatus st : status.getChildren()) {
                    addErrorMarker(fproj.getProject(), st.getMessage());
                }
            }
        }
    }

    private void addErrorMarker(IProject project, String message) {
        markerManager.addMarker(project, MavenSarConstants.SAR_CONFIGURATION_ERROR_MARKER_ID, message, -1,
                IMarker.SEVERITY_ERROR);
    }

    protected String getExpectedPackage() {
        return "jboss-sar";
    }

    public void setModuleDependencies(IProject project, MavenProject mavenProject, IProgressMonitor monitor)
            throws CoreException {

        IVirtualComponent sarComponent = ComponentCore.createComponent(project);
        if (sarComponent == null) {
            return;
        }

        Set<IVirtualReference> newRefs = new LinkedHashSet<IVirtualReference>();

        JBossPackagingPluginConfiguration config = new JBossPackagingPluginConfiguration(mavenProject);

        if (!config.isExcludeAll()) {
            Set<Artifact> artifacts = mavenProject.getArtifacts();

            for (Artifact artifact : artifacts) {
                // Don't deploy pom, non runtime or optional dependencies
                if ("pom".equals(artifact.getType()) || !SCOPE_FILTER_RUNTIME.include(artifact)
                        || artifact.isOptional() || config.isExcluded(artifact)) {
                    continue;
                }

                IMavenProjectFacade workspaceDependency = projectManager.getMavenProject(artifact.getGroupId(),
                        artifact.getArtifactId(), artifact.getVersion());

                IVirtualComponent depComponent;
                if (workspaceDependency != null && !workspaceDependency.getProject().equals(project)
                        && workspaceDependency.getFullPath(artifact.getFile()) != null) {
                    // artifact dependency is a workspace project
                    IProject depProject = workspaceDependency.getProject();
                    configureWtpUtil(workspaceDependency, monitor);
                    depComponent = ComponentCore.createComponent(depProject);
                } else {
                    // artifact dependency should be added as a JEE module,
                    // referenced with M2_REPO variable
                    String artifactPath = ArtifactHelper.getM2REPOVarPath(artifact);
                    depComponent = ComponentCore.createArchiveComponent(sarComponent.getProject(), artifactPath);
                }
                IVirtualReference reference = ComponentCore.createReference(sarComponent, depComponent);
                reference.setArchiveName(config.mapFileName(artifact));
                reference.setRuntimePath(new Path(config.getLibDirectory()));
                newRefs.add(reference);
            }
        }
        IVirtualReference[] newRefsArray = new IVirtualReference[newRefs.size()];
        newRefs.toArray(newRefsArray);

        // Only change the project references if they've changed
        if (WTPProjectsUtil.hasChanged(sarComponent.getReferences(), newRefsArray)) {
            sarComponent.setReferences(newRefsArray);
        }
    }

    protected void updateContainerAttributes(IProject project, IClasspathAttribute attributeToAdd,
            String attributeToDelete, IProgressMonitor monitor) throws JavaModelException {
        IJavaProject javaProject = JavaCore.create(project);
        if (javaProject == null)
            return;
        IClasspathEntry[] cp = javaProject.getRawClasspath();
        for (int i = 0; i < cp.length; i++) {
            if (IClasspathEntry.CPE_CONTAINER == cp[i].getEntryKind()
                    && MavenClasspathHelpers.isMaven2ClasspathContainer(cp[i].getPath())) {
                LinkedHashMap<String, IClasspathAttribute> attrs = new LinkedHashMap<String, IClasspathAttribute>();
                for (IClasspathAttribute attr : cp[i].getExtraAttributes()) {
                    if (!attr.getName().equals(attributeToDelete)) {
                        attrs.put(attr.getName(), attr);
                    }
                }
                attrs.put(attributeToAdd.getName(), attributeToAdd);
                IClasspathAttribute[] newAttrs = attrs.values().toArray(new IClasspathAttribute[attrs.size()]);
                cp[i] = JavaCore.newContainerEntry(cp[i].getPath(), cp[i].getAccessRules(), newAttrs,
                        cp[i].isExported());
                break;
            }
        }
        javaProject.setRawClasspath(cp, monitor);
    }

    @Override
    public void mavenProjectChanged(MavenProjectChangedEvent event, IProgressMonitor monitor) throws CoreException {
        setModuleDependencies(event.getMavenProject().getProject(), event.getMavenProject().getMavenProject(),
                monitor);
    }

    protected void configureWtpUtil(IMavenProjectFacade facade, IProgressMonitor monitor) throws CoreException {
        // Adding utility facet on JEE projects is not allowed
        IProject project = facade.getProject();
        MavenProject mavenProject = facade.getMavenProject();
        if (!WTPProjectsUtil.isJavaProject(facade) || WTPProjectsUtil.isJavaEEProject(project)
                || WTPProjectsUtil.isQualifiedAsWebFragment(facade)) {
            return;
        }

        IPath[] sourceRoots = MavenProjectUtils.getSourceLocations(project, mavenProject.getCompileSourceRoots());
        IPath[] resourceRoots = MavenProjectUtils.getResourceLocations(project, mavenProject.getResources());

        if (!checkJavaConfiguration(project, sourceRoots, resourceRoots)) {
            return;
        }

        IFacetedProject facetedProject = ProjectFacetsManager.create(project, true, monitor);
        Set<Action> actions = new LinkedHashSet<Action>();

        WTPProjectsUtil.installJavaFacet(actions, project, facetedProject);

        if (!facetedProject.hasProjectFacet(WTPProjectsUtil.UTILITY_FACET)) {
            actions.add(new IFacetedProject.Action(IFacetedProject.Action.Type.INSTALL, WTPProjectsUtil.UTILITY_10,
                    null));
        } else if (!facetedProject.hasProjectFacet(WTPProjectsUtil.UTILITY_10)) {
            actions.add(new IFacetedProject.Action(IFacetedProject.Action.Type.VERSION_CHANGE,
                    WTPProjectsUtil.UTILITY_10, null));
        }

        if (!actions.isEmpty()) {
            ResourceCleaner fileCleaner = new ResourceCleaner(project);
            try {
                addFoldersToClean(fileCleaner, facade);
                facetedProject.modify(actions, monitor);
            } finally {
                //Remove any unwanted MANIFEST.MF the Facet installation has created
                fileCleaner.cleanUp();
            }
        }

        WTPProjectsUtil.fixMissingModuleCoreNature(project, monitor);

        //MNGECLIPSE-904 remove tests folder links for utility jars
        removeTestFolderLinks(project, mavenProject, monitor, "/");

        //Remove "library unavailable at runtime" warning.
        WTPProjectsUtil.setNonDependencyAttributeToContainer(project, monitor);

        WTPProjectsUtil.removeWTPClasspathContainer(project);
    }

    /**
     * Checks the maven source folders are correctly added to the project classpath
     */
    private boolean checkJavaConfiguration(IProject project, IPath[] sourceRoots, IPath[] resourceRoots)
            throws JavaModelException {
        IJavaProject javaProject = JavaCore.create(project);
        if (javaProject == null) {
            return false;
        }
        IClasspathEntry[] cpEntries = javaProject.getRawClasspath();
        if (cpEntries == null) {
            return false;
        }
        Set<IPath> currentPaths = new HashSet<IPath>();
        for (IClasspathEntry entry : cpEntries) {
            if (IClasspathEntry.CPE_SOURCE == entry.getEntryKind()) {
                currentPaths.add(entry.getPath().makeRelativeTo(project.getFullPath()));
            }
        }
        for (IPath mavenSource : sourceRoots) {
            if (mavenSource != null && !mavenSource.isEmpty()) {
                IFolder sourceFolder = project.getFolder(mavenSource);
                if (sourceFolder.exists() && !currentPaths.contains(mavenSource)) {
                    return false;
                }
            }
        }
        for (IPath mavenSource : resourceRoots) {
            if (mavenSource != null && !mavenSource.isEmpty()) {
                IFolder resourceFolder = project.getFolder(mavenSource);
                if (resourceFolder.exists() && !currentPaths.contains(mavenSource)) {
                    return false;
                }
            }
        }
        return true;
    }

    protected void addFoldersToClean(ResourceCleaner fileCleaner, IMavenProjectFacade facade) {
        for (IPath p : facade.getCompileSourceLocations()) {
            if (p != null) {
                fileCleaner.addFiles(p.append("META-INF/MANIFEST.MF"));
                fileCleaner.addFolder(p);
            }
        }
        for (IPath p : facade.getResourceLocations()) {
            if (p != null) {
                fileCleaner.addFiles(p.append("META-INF/MANIFEST.MF"));
                fileCleaner.addFolder(p);
            }
        }
        for (IPath p : facade.getTestCompileSourceLocations()) {
            if (p != null)
                fileCleaner.addFolder(p);
        }
        for (IPath p : facade.getTestResourceLocations()) {
            if (p != null)
                fileCleaner.addFolder(p);
        }
    }

}