Package org.eclipse.m2e.wtp

Source Code of org.eclipse.m2e.wtp.WebProjectConfiguratorDelegate

/*******************************************************************************
* Copyright (c) 2008, 2013 Sonatype, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are 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
*******************************************************************************/

package org.eclipse.m2e.wtp;

import static org.eclipse.m2e.wtp.WTPProjectsUtil.removeConflictingFacets;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.StringUtils;
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.Path;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jst.j2ee.classpathdep.IClasspathDependencyConstants;
import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities;
import org.eclipse.jst.j2ee.project.facet.IJ2EEModuleFacetInstallDataModelProperties;
import org.eclipse.jst.j2ee.web.project.facet.IWebFacetInstallDataModelProperties;
import org.eclipse.jst.j2ee.web.project.facet.WebFacetInstallDataModelProvider;
import org.eclipse.jst.j2ee.web.project.facet.WebFacetUtils;
import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.embedder.ArtifactKey;
import org.eclipse.m2e.core.internal.IMavenConstants;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
import org.eclipse.m2e.jdt.IClasspathDescriptor;
import org.eclipse.m2e.jdt.IClasspathEntryDescriptor;
import org.eclipse.m2e.wtp.internal.ExtensionReader;
import org.eclipse.m2e.wtp.internal.Messages;
import org.eclipse.m2e.wtp.internal.filtering.WebResourceFilteringConfiguration;
import org.eclipse.m2e.wtp.namemapping.FileNameMapping;
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.IVirtualReference;
import org.eclipse.wst.common.componentcore.resources.IVirtualResource;
import org.eclipse.wst.common.frameworks.datamodel.DataModelFactory;
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.IProjectFacetVersion;
import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;



/**
* Configures web projects based on their maven-war-plugin configuration.
*
* @author Igor Fedorenko
* @author Fred Bricon
*/
@SuppressWarnings("restriction")
class WebProjectConfiguratorDelegate extends AbstractProjectConfiguratorDelegate {

  private static final Logger LOG = LoggerFactory.getLogger(WebProjectConfiguratorDelegate.class);
  /**
   * See http://wiki.eclipse.org/ClasspathEntriesPublishExportSupport
   */
  static final IClasspathAttribute DEPENDENCY_ATTRIBUTE = JavaCore.newClasspathAttribute(
      IClasspathDependencyConstants.CLASSPATH_COMPONENT_DEPENDENCY, "/WEB-INF/lib"); //$NON-NLS-1$

  private static final String CLASSPATH_ARCHIVENAME_ATTRIBUTE;
 
  static {
    String archiveNameAttribute = null;
    try {
      Field classpathArchiveNameField = IClasspathDependencyConstants.class.getField("CLASSPATH_ARCHIVENAME_ATTRIBUTE"); //$NON-NLS-1$
      archiveNameAttribute = (String)classpathArchiveNameField.get(null);
    } catch (Exception e) {
      LOG.warn(Messages.WebProjectConfiguratorDelegate_Renamed_Dependencies_Will_Be_Copied);
    }
    CLASSPATH_ARCHIVENAME_ATTRIBUTE = archiveNameAttribute;
  }
 
  /**
  * Name of maven property that overrides WTP context root.
  */
  private static final String M2ECLIPSE_WTP_CONTEXT_ROOT = "m2eclipse.wtp.contextRoot"; //$NON-NLS-1$
 
  @Override
protected void configure(IProject project, MavenProject mavenProject, IProgressMonitor monitor)
      throws CoreException {
    IFacetedProject facetedProject = ProjectFacetsManager.create(project, true, monitor);
    IMavenProjectFacade facade = MavenPlugin.getMavenProjectRegistry().create(project.getFile(IMavenConstants.POM_FILE_NAME), true, monitor);

    // make sure to update the main deployment folder
    WarPluginConfiguration config = new WarPluginConfiguration(mavenProject, project);
    String warSourceDirectory = config.getWarSourceDirectory();
   
    IFolder contentFolder = project.getFolder(warSourceDirectory);

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

    installJavaFacet(actions, project, facetedProject);
   
    IVirtualComponent component = ComponentCore.createComponent(project, true);
   
    //MNGECLIPSE-2279 get the context root from the final name of the project, or artifactId by default.
    String contextRoot = getContextRoot(mavenProject, config.getWarName());
   
    IProjectFacetVersion webFv = config.getWebFacetVersion(project);
    IDataModel webModelCfg = getWebModelConfig(warSourceDirectory, contextRoot);
    if(!facetedProject.hasProjectFacet(WebFacetUtils.WEB_FACET)) {
      removeConflictingFacets(facetedProject, webFv, actions);
      actions.add(new IFacetedProject.Action(IFacetedProject.Action.Type.INSTALL, webFv, webModelCfg));
    } else {
      IProjectFacetVersion projectFacetVersion = facetedProject.getProjectFacetVersion(WebFacetUtils.WEB_FACET);    
      if(webFv.getVersionString() != null && !webFv.getVersionString().equals(projectFacetVersion.getVersionString())){
          actions.add(new IFacetedProject.Action(IFacetedProject.Action.Type.VERSION_CHANGE, webFv, webModelCfg));
      }
    }

    String customWebXml = config.getCustomWebXml(project);
   
    if(!actions.isEmpty()) {
      ResourceCleaner fileCleaner = new ResourceCleaner(project, contentFolder);
      try {
        addFoldersToClean(fileCleaner, facade);
        fileCleaner.addFiles(contentFolder.getFile("META-INF/MANIFEST.MF").getProjectRelativePath()); //$NON-NLS-1$
        fileCleaner.addFolder(contentFolder.getFolder("WEB-INF/lib")); //$NON-NLS-1$
        if (customWebXml != null) {
          fileCleaner.addFiles(contentFolder.getFile("WEB-INF/web.xml").getProjectRelativePath()); //$NON-NLS-1$
        }
       
        facetedProject.modify(actions, monitor);
      } finally {
        //Remove any unwanted MANIFEST.MF the Facet installation has created
        fileCleaner.cleanUp();
      }
    }
   
    //MECLIPSEWTP-41 Fix the missing moduleCoreNature
    fixMissingModuleCoreNature(project, monitor);
   
    // MNGECLIPSE-632 remove test sources/resources from WEB-INF/classes
    removeTestFolderLinks(project, mavenProject, monitor, "/WEB-INF/classes"); //$NON-NLS-1$

    addContainerAttribute(project, DEPENDENCY_ATTRIBUTE, monitor);

    //MNGECLIPSE-2279 change the context root if needed
    if (!contextRoot.equals(J2EEProjectUtilities.getServerContextRoot(project))) {
      J2EEProjectUtilities.setServerContextRoot(project, contextRoot);
    }
   
    if (customWebXml != null) {
      linkFileFirst(project, customWebXml, "/WEB-INF/web.xml", monitor); //$NON-NLS-1$
    }

   
    component = ComponentCore.createComponent(project, true);
    if(component != null) {     
      IPath warPath = new Path("/").append(contentFolder.getProjectRelativePath()); //$NON-NLS-1$
      List<IPath> sourcePaths = new ArrayList<IPath>();
      sourcePaths.add(warPath);
      if (!WTPProjectsUtil.hasLink(project, ROOT_PATH, warPath, monitor)) {
        component.getRootFolder().createLink(warPath, IVirtualResource.NONE, monitor);
      }
      //MECLIPSEWTP-22 support web filtered resources. Filtered resources directory must be declared BEFORE
      //the regular web source directory. First resources discovered take precedence on deployment
      IPath filteredFolder = new Path("/").append(WebResourceFilteringConfiguration.getTargetFolder(mavenProject, project)); //$NON-NLS-1$
     
      boolean useBuildDir = MavenWtpPlugin.getDefault().getMavenWtpPreferencesManager().getPreferences(project).isWebMavenArchiverUsesBuildDirectory();
      boolean useWebresourcefiltering = config.getWebResources() != null
                                        && config.getWebResources().length > 0
                                        || config.isFilteringDeploymentDescriptorsEnabled();

      if (useBuildDir || useWebresourcefiltering) {
       
        if (!useBuildDir && useWebresourcefiltering) {
          mavenMarkerManager.addMarker(project, MavenWtpConstants.WTP_MARKER_CONFIGURATION_ERROR_ID,
                                      Messages.markers_mavenarchiver_output_settings_ignored_warning, -1, IMarker.SEVERITY_WARNING);
        }
        sourcePaths.add(filteredFolder);
        WTPProjectsUtil.insertLinkBefore(project, filteredFolder, warPath, new Path("/"), monitor); //$NON-NLS-1$
      } else {
        component.getRootFolder().removeLink(filteredFolder,IVirtualResource.NONE, monitor);
      }

      WTPProjectsUtil.deleteLinks(project, ROOT_PATH, sourcePaths, monitor);
     
      WTPProjectsUtil.setDefaultDeploymentDescriptorFolder(component.getRootFolder(), warPath, monitor);

      addComponentExclusionPatterns(component, config);
     
    }
    WTPProjectsUtil.removeWTPClasspathContainer(project);
   
    setModuleDependencies(project, mavenProject, monitor);
  }

  private IDataModel getWebModelConfig(String warSourceDirectory, String contextRoot) {
    IDataModel webModelCfg = DataModelFactory.createDataModel(new WebFacetInstallDataModelProvider());
    webModelCfg.setProperty(IJ2EEModuleFacetInstallDataModelProperties.CONFIG_FOLDER, warSourceDirectory);
    webModelCfg.setProperty(IWebFacetInstallDataModelProperties.CONTEXT_ROOT, contextRoot);
    webModelCfg.setProperty(IJ2EEModuleFacetInstallDataModelProperties.GENERATE_DD, false);
    webModelCfg.setBooleanProperty(IWebFacetInstallDataModelProperties.ADD_TO_EAR, false);
    return webModelCfg;
  }

  @Override
  public void setModuleDependencies(IProject project, MavenProject mavenProject, IProgressMonitor monitor)
      throws CoreException {
    if (!ModuleCoreNature.isFlexibleProject(project)) {
      return;
    }
   
    IVirtualComponent component = ComponentCore.createComponent(project,true);
    //if the attempt to create dependencies happens before the project is actually created, abort.
    //this will be created again when the project exists.
    if(component == null){
      return;
    }
    //MECLIPSEWTP-41 Fix the missing moduleCoreNature
    fixMissingModuleCoreNature(project, monitor);
   
    WarPluginConfiguration config = new WarPluginConfiguration(mavenProject, project);
  
    Map<Artifact, String> deployedArtifacts = getDeployedArtifacts(mavenProject.getArtifacts(), config);
   
    List<AbstractDependencyConfigurator> depConfigurators = ExtensionReader.readDependencyConfiguratorExtensions(projectManager,
        MavenPlugin.getMavenRuntimeManager(), mavenMarkerManager);
   
    Set<IVirtualReference> references = new LinkedHashSet<IVirtualReference>();

    List<IMavenProjectFacade> exportedDependencies = getWorkspaceDependencies(project, mavenProject);
   
    for(IMavenProjectFacade dependency : exportedDependencies) {
      String depPackaging = dependency.getPackaging();
      if ("pom".equals(depPackaging) //MNGECLIPSE-744 pom dependencies shouldn't be deployed //$NON-NLS-1$
          || "war".equals(depPackaging) //Overlays are dealt with the overlay configurator //$NON-NLS-1$
          || "zip".equals(depPackaging)) { //$NON-NLS-1$
        continue;
      }
     
      preConfigureDependencyProject(dependency, monitor);
     
      if (!ModuleCoreNature.isFlexibleProject(dependency.getProject())) {
        //Projects unsupported by WTP (ex. adobe flex projects) should not be added as references
        continue;
      }
      MavenProject depMavenProject =  dependency.getMavenProject(monitor);

      IVirtualComponent depComponent = ComponentCore.createComponent(dependency.getProject());
         
      ArtifactKey artifactKey = ArtifactHelper.toArtifactKey(depMavenProject.getArtifact());
      //Get artifact using the proper classifier
      Artifact artifact = ArtifactHelper.getArtifact(mavenProject.getArtifacts(), artifactKey);
      if (artifact == null) {
        //could not map key to artifact
        artifact = depMavenProject.getArtifact();
      }
      String deployedName = deployedArtifacts.get(artifact);
     
      //an artifact in mavenProject.getArtifacts() doesn't have the "optional" value as depMavenProject.getArtifact(); 
      if (deployedName != null) {
        IVirtualReference reference = ComponentCore.createReference(component, depComponent);
        IPath path = new Path("/WEB-INF/lib"); //$NON-NLS-1$
        reference.setArchiveName(deployedName);
        reference.setRuntimePath(path);
        references.add(reference);
      }
    }

    IVirtualReference[] oldRefs = WTPProjectsUtil.extractHardReferences(component, false);
   
    IVirtualReference[] newRefs = references.toArray(new IVirtualReference[references.size()]);
   
    if (WTPProjectsUtil.hasChanged(oldRefs, newRefs)){
      //Only write in the .component file if necessary
      IVirtualReference[] overlayRefs = WTPProjectsUtil.extractHardReferences(component, true);
      IVirtualReference[] allRefs = new IVirtualReference[overlayRefs.length + newRefs.length];
      System.arraycopy(newRefs, 0, allRefs, 0, newRefs.length);
      System.arraycopy(overlayRefs, 0, allRefs, newRefs.length, overlayRefs.length);
      component.setReferences(allRefs);
    }
   
    //TODO why a 2nd loop???
    for(IMavenProjectFacade dependency : exportedDependencies) {
      MavenProject depMavenProject =  dependency.getMavenProject(monitor);
      Iterator<AbstractDependencyConfigurator> configurators = depConfigurators.iterator();
      while (configurators.hasNext()) {
        try {
          configurators.next().configureDependency(mavenProject, project, depMavenProject, dependency.getProject(), monitor);
        } catch(MarkedException ex) {
          //XXX handle this
        }
      }
    }
  }
 
  /**
   * Get the context root from a maven web project
   * @param mavenProject
   * @param warName
   * @return the final name of the project if it exists, or the project's artifactId.
   */
  protected String getContextRoot(MavenProject mavenProject, String warName) {
    String contextRoot;
  //MECLIPSEWTP-43 : Override with maven property
   String property = mavenProject.getProperties().getProperty(M2ECLIPSE_WTP_CONTEXT_ROOT);
   if (StringUtils.isBlank(property)) {
      String finalName = warName;
      if (StringUtils.isBlank(finalName)
         || finalName.equals(mavenProject.getArtifactId() + "-" + mavenProject.getVersion())) { //$NON-NLS-1$
        contextRoot = mavenProject.getArtifactId();
      else {
        contextRoot = finalName;
      }
    } else {
      contextRoot = property;
    }

    return contextRoot.trim().replace(" ", "_"); //$NON-NLS-1$ //$NON-NLS-2$
  }

  @Override
  public void configureClasspath(IProject project, MavenProject mavenProject, IClasspathDescriptor classpath,
      IProgressMonitor monitor) throws CoreException {
   
    WarPluginConfiguration config = new WarPluginConfiguration(mavenProject, project);
    Set<Artifact> artifacts = mavenProject.getArtifacts();
    Map<Artifact, String> deployedArtifacts = getDeployedArtifacts(artifacts, config);
   
    Iterator<IClasspathEntryDescriptor> iter = classpath.getEntryDescriptors().iterator();
    while (iter.hasNext()) {
      IClasspathEntryDescriptor descriptor = iter.next();
      Artifact artifact = ArtifactHelper.getArtifact(artifacts, descriptor.getArtifactKey());
      if (artifact == null) {
        return;
      }
     
      String deployedName = deployedArtifacts.get(artifact);
   
      if(deployedName == null || isWorkspaceProject(artifact)) {
        descriptor.setClasspathAttribute(NONDEPENDENCY_ATTRIBUTE.getName(), NONDEPENDENCY_ATTRIBUTE.getValue());
        continue;
      }
      descriptor.getClasspathAttributes().put(CLASSPATH_ARCHIVENAME_ATTRIBUTE, deployedName);
    }
  }

  private boolean isWorkspaceProject(Artifact artifact) {
    IMavenProjectFacade facade = projectManager.getMavenProject(artifact.getGroupId(),
                                  artifact.getArtifactId(),
                                  artifact.getVersion());
         
    return facade != null && facade.getFullPath(artifact.getFile()) != null;
  }
  private Map<Artifact, String> getDeployedArtifacts(Collection<Artifact> artifacts, WarPluginConfiguration config ) {
    if (artifacts == null || artifacts.isEmpty()) {
      return Collections.emptyMap();
    }
    int size = artifacts.size();
    Map<Artifact, String> artifactsMap = new LinkedHashMap<Artifact, String>(size);
   
    IPackagingConfiguration opts = new PackagingConfiguration(config.getPackagingIncludes(), config.getPackagingExcludes());
    FileNameMapping fileNameMapping = config.getFileNameMapping();
   
    Set<String> names = new HashSet<String>(size);

    Set<String> duplicates = new HashSet<String>(size);
   
    for (Artifact artifact : artifacts) {
      ArtifactHelper.fixArtifactHandler(artifact.getArtifactHandler());
      String deployedName = fileNameMapping.mapFileName(artifact);
      String scope = artifact.getScope();
      boolean isDeployed =  (Artifact.SCOPE_COMPILE.equals(scope) || Artifact.SCOPE_RUNTIME.equals(scope))
                            && !artifact.isOptional()
                            && opts.isPackaged("WEB-INF/lib/"+deployedName); //$NON-NLS-1$
      if (isDeployed) {
        if (!names.add(deployedName)) {
          duplicates.add(deployedName);
         }
        artifactsMap.put(artifact, deployedName);
      }
    }
   
    //disambiguate duplicates
    for (String name : duplicates) {
      for (Map.Entry<Artifact, String> entry : artifactsMap.entrySet()) {
        if (name.equals(entry.getValue())) {
            String newDeployedName = entry.getKey().getGroupId() + "-" + name; //$NON-NLS-1$
          entry.setValue(newDeployedName);
        }
      }
    }
   
    return artifactsMap;
  }
 
}
TOP

Related Classes of org.eclipse.m2e.wtp.WebProjectConfiguratorDelegate

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.