blob: 6b9952992b0feba3ae709eebe613188f6139f39b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.sling.ide.eclipse.m2e.internal;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import org.apache.maven.project.MavenProject;
import org.apache.sling.ide.eclipse.core.ConfigurationHelper;
import org.eclipse.aether.util.StringUtils;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jst.common.project.facet.core.JavaFacet;
import org.eclipse.jst.common.project.facet.core.internal.JavaFacetUtil;
import org.eclipse.jst.j2ee.project.facet.IJ2EEFacetConstants;
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.project.configurator.ProjectConfigurationRequest;
import org.eclipse.ui.statushandlers.StatusManager;
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;
/**
* m2e project configurator that creates the Eclipse project files (e.g .project) from a pom.xml for
* the maven packaging type "content-package". The configurator is run automatically
* on "Import..." -> "Existing Maven Project" and Right-Click on Project -> "Maven"
* -> "Update Project...".
*
*
*/
public class ContentPackageProjectConfigurator extends AbstractProjectConfigurator {
// Using these maven properties, the to-be-created eclipse project settings can be configured in pom.xml
private static final String M2E_ACTIVE = "sling.ide.m2e.contentpackage.active";
private static final String M2E_JAVA_FACET_VERSION = "sling.ide.m2e.contentpackage.javaFacetVersion";
private static final String M2E_WEB_FACET_VERSION = "sling.ide.m2e.contentpackage.webFacetVersion";
@Override
public void configure(ProjectConfigurationRequest configRequest, IProgressMonitor progressMonitor) throws CoreException {
IProject project = configRequest.getProject();
// delete all previous markers on this pom.xml set by any project configurator
deleteMarkers(configRequest.getPom());
if (!getPreferences().isContentPackageProjectConfiguratorEnabled()) {
trace("M2E project configurator for packing type 'content-package' was disabled through preference.");
return;
}
MavenProject mavenProject = configRequest.getMavenProject();
boolean active = !"false".equalsIgnoreCase(mavenProject.getProperties().getProperty(M2E_ACTIVE));
if(!active) {
trace("M2E project configurator for packing type 'content-package' was disabled with Maven property {0}", M2E_ACTIVE);
return;
}
trace("Configuring {0} with packaging 'content-package'...", mavenProject);
// core configuration for sling ide plugin
try {
Optional<java.nio.file.Path> contentSyncPath = MavenProjectUtils.guessJcrRootFolder(mavenProject);
if (contentSyncPath.isPresent()) {
// add marker
addMarker(configRequest.getPom(), "Could not detect jcr_root path for this content package!", IMarker.SEVERITY_ERROR);
}
String jcrRootPath = contentSyncPath.toString();
ConfigurationHelper.convertToContentPackageProject(project, progressMonitor, Path.fromOSString(jcrRootPath));
if (getPreferences().isWtpFacetsEnabledInContentPackageProjectConfigurator()) {
new WtpProjectConfigurer(configRequest, project, jcrRootPath).configure(progressMonitor);
trace("WTP facets for {0} added", mavenProject);
} else {
trace("WTP facets for packing type 'content-package' are disabled through preferences.");
}
} catch (IOException e) {
Activator.getDefault().getPluginLogger().warn("Could not determine jcr_root for project: " + mavenProject.getBasedir() + ": "+e, e);
}
trace("Done converting .");
}
/**
* Adds the given natures to the project
* @param project
* @param natureIdsToAdd
* @param progressMonitor
* @throws CoreException
* @see <a href="http://help.eclipse.org/neon/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Fguide%2FresAdv_natures.htm">Eclipse Help: Project Natures</a>
*/
private void addNatures(IProject project, String[] natureIdsToAdd, IProgressMonitor progressMonitor, IResource pomResource)
throws CoreException {
trace("Adding natures {0} to project {1} ", Arrays.toString(natureIdsToAdd), project);
IProjectDescription description = project.getDescription();
String[] oldNatureIds = description.getNatureIds();
Set<String> newNatureIdSet = new TreeSet<String>();
newNatureIdSet.addAll(Arrays.asList(oldNatureIds));
// check if there is a nature change really requested
if (newNatureIdSet.addAll(Arrays.asList(natureIdsToAdd))) {
String[] newNatureIds = newNatureIdSet.toArray(new String[newNatureIdSet.size()]);
IStatus status = project.getWorkspace().validateNatureSet(newNatureIds);
// check the status and decide what to do
if (status.getCode() == IStatus.OK) {
trace("Modifiying natures of project {1} to {0}", Arrays.toString(newNatureIds), project);
description.setNatureIds(newNatureIds);
project.setDescription(description, IResource.KEEP_HISTORY, progressMonitor);
} else {
StatusManager.getManager().handle(status, StatusManager.LOG|StatusManager.SHOW);
// add marker
addMarker(pomResource, "Could not add all necessary WTP natures: " + status.getMessage(), IMarker.SEVERITY_ERROR);
}
} else {
trace("Not modifiying natures of project {1} as required natures {0} are already set ", Arrays.toString(natureIdsToAdd), project);
}
}
// Implemented in line with the current m2e-wtp plugin, except that java/web facet version can be configured
private class WtpProjectConfigurer {
private final ProjectConfigurationRequest configRequest;
private final IProject project;
private final String jcrRootPath;
WtpProjectConfigurer(ProjectConfigurationRequest configRequest,
IProject project, String jcrRootPath) {
this.configRequest = configRequest;
this.project = project;
this.jcrRootPath = jcrRootPath;
}
void configure(IProgressMonitor progressMonitor) throws CoreException {
trace("Configuring content-package with WTP facets/natures");
addNatures(project, getDefaultWtpNatures(), progressMonitor, configRequest.getPom());
addWtpFacets(progressMonitor);
}
void addWtpFacets( IProgressMonitor progressMonitor) throws CoreException {
MavenProject mavenProject = configRequest.getMavenProject();
String javaFacetVersion;
if ( !StringUtils.isEmpty(mavenProject.getProperties().getProperty(M2E_JAVA_FACET_VERSION))) {
javaFacetVersion = mavenProject.getProperties().getProperty(M2E_JAVA_FACET_VERSION);
trace("Configured Java facet version {0} from pom property {1}", javaFacetVersion, M2E_JAVA_FACET_VERSION);
} else {
javaFacetVersion = JavaFacetUtil.getCompilerLevel(project);
trace("Configured Java facet version {0} using JavaFacetUtil", javaFacetVersion);
}
String webFacetVersion;
if ( !StringUtils.isEmpty(mavenProject.getProperties().getProperty(M2E_WEB_FACET_VERSION))) {
webFacetVersion = mavenProject.getProperties().getProperty(M2E_WEB_FACET_VERSION);
trace("Configured Web facet version {0} from pom property {1}", webFacetVersion, M2E_WEB_FACET_VERSION);
} else {
webFacetVersion = MavenProjectUtils.guessServletApiVersion(mavenProject);
trace("Configured Web facet version {0} from project dependencies", webFacetVersion);
}
// web facets
IFacetedProject facetedProject = ProjectFacetsManager.create(project, true, progressMonitor);
Set<Action> actions = new LinkedHashSet<Action>();
installJavaFacet(actions, project, facetedProject, javaFacetVersion);
IProjectFacetVersion webFv = ProjectFacetsManager.getProjectFacet(IJ2EEFacetConstants.DYNAMIC_WEB).getVersion(webFacetVersion);
IDataModel webModelCfg = getWebModelConfig(jcrRootPath);
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));
}
}
if (!actions.isEmpty()) {
try {
facetedProject.modify(actions, progressMonitor);
} catch (Exception e) {
Activator.getDefault().getPluginLogger().warn("Could not add facets to project: "+e, e);
}
}
}
private IDataModel getWebModelConfig(String warSourceDirectory) {
IDataModel webModelCfg = DataModelFactory.createDataModel(new WebFacetInstallDataModelProvider());
webModelCfg.setProperty(IJ2EEModuleFacetInstallDataModelProperties.CONFIG_FOLDER, warSourceDirectory);
webModelCfg.setProperty(IWebFacetInstallDataModelProperties.CONTEXT_ROOT, "/");
webModelCfg.setProperty(IJ2EEModuleFacetInstallDataModelProperties.GENERATE_DD, false);
return webModelCfg;
}
private void installJavaFacet(Set<Action> actions, IProject project, IFacetedProject facetedProject, String javaFacetVersion) {
IProjectFacetVersion javaFv = JavaFacet.FACET.getVersion(javaFacetVersion);
if (!facetedProject.hasProjectFacet(JavaFacet.FACET)) {
actions.add(new IFacetedProject.Action(IFacetedProject.Action.Type.INSTALL, javaFv, null));
} else if (!facetedProject.hasProjectFacet(javaFv)) {
actions.add(new IFacetedProject.Action(IFacetedProject.Action.Type.VERSION_CHANGE, javaFv, null));
}
}
/**
* Adds uninstall actions of facets from the faceted project that conflict with the given facetVersion.
*/
private void removeConflictingFacets(IFacetedProject project, IProjectFacetVersion facetVersion, Set<Action> actions) {
if (project == null) {
throw new IllegalArgumentException("project can not be null");
}
if (facetVersion == null) {
throw new IllegalArgumentException("Facet version can not be null");
}
if (actions == null) {
throw new IllegalArgumentException("actions can not be null");
}
for (IProjectFacetVersion existingFacetVersion : project.getProjectFacets()) {
if (facetVersion.conflictsWith(existingFacetVersion)) {
actions.add(new IFacetedProject.Action(IFacetedProject.Action.Type.UNINSTALL, existingFacetVersion, null));
}
}
}
private String[] getDefaultWtpNatures() {
return new String[] {
"org.eclipse.wst.jsdt.core.jsNature",
"org.eclipse.wst.common.project.facet.core.nature",
"org.eclipse.wst.common.modulecore.ModuleCoreNature",
"org.eclipse.jem.workbench.JavaEMFNature"
};
}
}
}