blob: 32278ffc7f58e8ff262d9515a3cad056ae2a5d8a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008-2010 Sonatype, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Sonatype, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.m2e.core.ui.internal.wizards;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.createElementWithText;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.findChild;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.format;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.getChild;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.performOnDOMDocument;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.textEquals;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
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.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.progress.IProgressConstants;
import org.apache.maven.archetype.catalog.Archetype;
import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.ui.internal.MavenImages;
import org.eclipse.m2e.core.ui.internal.Messages;
import org.eclipse.m2e.core.ui.internal.actions.OpenMavenConsoleAction;
import org.eclipse.m2e.core.ui.internal.editing.PomEdits.Operation;
import org.eclipse.m2e.core.ui.internal.editing.PomEdits.OperationTuple;
/**
* A project wizard for creating a new Maven2 module project.
*/
public class MavenModuleWizard extends AbstractMavenProjectWizard implements INewWizard {
private static final Logger LOG = LoggerFactory.getLogger(MavenModuleWizard.class);
/** the parent page (#1) */
protected MavenModuleWizardParentPage parentPage;
/** The archetype selection page. */
protected MavenProjectWizardArchetypePage archetypePage;
/** The wizard page for gathering Maven2 project information. */
protected MavenProjectWizardArtifactPage artifactPage;
/** The wizard page for gathering archetype project information. */
protected MavenProjectWizardArchetypeParametersPage parametersPage;
private String moduleName;
protected boolean isEditor = false;
/** Default constructor. Sets the title and image of the wizard. */
public MavenModuleWizard() {
setWindowTitle(Messages.wizardModuleTitle);
setDefaultPageImageDescriptor(MavenImages.WIZ_NEW_PROJECT);
setNeedsProgressMonitor(true);
}
public MavenModuleWizard(boolean isEditor) {
this();
this.isEditor = isEditor;
}
/** Creates the pages. */
public void addPages() {
parentPage = new MavenModuleWizardParentPage(importConfiguration, workingSets);
archetypePage = new MavenProjectWizardArchetypePage(importConfiguration);
parametersPage = new MavenProjectWizardArchetypeParametersPage(importConfiguration);
artifactPage = new MavenProjectWizardArtifactPage(importConfiguration);
addPage(parentPage);
addPage(archetypePage);
addPage(parametersPage);
addPage(artifactPage);
}
/** Adds the listeners after the page controls are created. */
public void createPageControls(Composite pageContainer) {
artifactPage.setParentReadonly(true);
artifactPage.setTitle(Messages.wizardModulePageArtifactTitle);
archetypePage.setTitle(Messages.wizardModulePageArchetypeTitle);
parametersPage.setTitle(Messages.wizardModulePageParametersTitle);
super.createPageControls(pageContainer);
parametersPage.setArtifactIdEnabled(false);
parentPage.addArchetypeSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
boolean isArchetype = !parentPage.isSimpleProject();
archetypePage.setUsed(isArchetype);
parametersPage.setUsed(isArchetype);
}
});
parentPage.addModuleNameListener(e -> {
parametersPage.setProjectName(parentPage.getModuleName());
artifactPage.setProjectName(parentPage.getModuleName());
});
parentPage.addParentProjectListener(e -> copyParentValues());
archetypePage.addArchetypeSelectionListener(selectionchangedevent -> {
parametersPage.setArchetype(archetypePage.getArchetype());
getContainer().updateButtons();
});
if(selection != null && selection.size() > 0) {
parentPage.setParent(selection.getFirstElement());
copyParentValues();
}
}
/** Copies the parent project parameters to the artifact page. */
protected void copyParentValues() {
Model model = parentPage.getParentModel();
if(model != null) {
String groupId = model.getGroupId();
String artifactId = model.getArtifactId();
String version = model.getVersion();
if(groupId == null) {
Parent parent = model.getParent();
if(parent != null) {
groupId = parent.getGroupId();
}
}
if(version == null) {
Parent parent = model.getParent();
if(parent != null) {
version = parent.getVersion();
}
}
artifactPage.setParentProject(groupId, artifactId, version);
parametersPage.setParentProject(groupId, artifactId, version);
}
}
/** Performs the "finish" action. */
public boolean performFinish() {
// First of all, we extract all the information from the wizard pages.
// Note that this should not be done inside the operation we will run
// since many of the wizard pages' methods can only be invoked from within
// the SWT event dispatcher thread. However, the operation spawns a new
// separate thread to perform the actual work, i.e. accessing SWT elements
// from within that thread would lead to an exception.
final String moduleName = parentPage.getModuleName();
// Get the location where to create the project. For some reason, when using
// the default workspace location for a project, we have to pass null
// instead of the actual location.
final IPath location = parentPage.getParentContainer().getLocation();
final IFile parentPom = parentPage.getPom();
Job job;
if(parentPage.isSimpleProject()) {
final Model model = artifactPage.getModel();
if(model.getParent() != null) {
Parent par = model.getParent();
String relPath = location.makeRelativeTo(location.append(moduleName)).toOSString();
if(!"..".equals(relPath)) { //$NON-NLS-1$
par.setRelativePath(relPath);
}
//#335331 remove current model's version and groupId if equal to parent, to prevent showing a warning marker
if(par.getGroupId() != null && par.getGroupId().equals(model.getGroupId())) {
model.setGroupId(null);
}
if(par.getVersion() != null && par.getVersion().equals(model.getVersion())) {
model.setVersion(null);
}
}
final String[] folders = artifactPage.getFolders();
job = new AbstractCreateMavenProjectJob(NLS.bind(Messages.wizardProjectJobCreatingProject, moduleName)) {
@Override
protected List<IProject> doCreateMavenProjects(IProgressMonitor monitor) throws CoreException {
setProperty(IProgressConstants.ACTION_PROPERTY, new OpenMavenConsoleAction());
String projectName = importConfiguration.getProjectName(model);
IProject project = importConfiguration.getProject(ResourcesPlugin.getWorkspace().getRoot(), model);
// XXX respect parent's setting for separate projects for modules
// XXX should run update sources on parent instead of creating new module project
MavenPlugin.getProjectConfigurationManager().createSimpleProject(project, location.append(moduleName), model,
folders, importConfiguration, new MavenProjectWorkspaceAssigner(workingSets), monitor);
setModule(projectName);
return Arrays.asList(project);
}
};
} else {
Model model = parametersPage.getModel();
final Archetype archetype = archetypePage.getArchetype();
final String groupId = model.getGroupId();
final String artifactId = model.getArtifactId();
final String version = model.getVersion();
final String javaPackage = parametersPage.getJavaPackage();
final Properties properties = parametersPage.getProperties();
job = new AbstractCreateMavenProjectJob(NLS.bind(Messages.wizardProjectJobCreating, archetype.getArtifactId())) {
@Override
protected List<IProject> doCreateMavenProjects(IProgressMonitor monitor) throws CoreException {
List<IProject> projects = MavenPlugin.getProjectConfigurationManager().createArchetypeProjects(location,
archetype, //
groupId, artifactId, version, javaPackage, //
properties, importConfiguration, new MavenProjectWorkspaceAssigner(workingSets), monitor);
setModule(moduleName);
return projects;
}
};
}
job.addJobChangeListener(new JobChangeAdapter() {
public void done(IJobChangeEvent event) {
final IStatus result = event.getResult();
if(result.isOK()) {
if(!isEditor) {
//add the <module> element to the parent pom
try {
performOnDOMDocument(new OperationTuple(parentPom, (Operation) document -> {
Element root = document.getDocumentElement();
Element modules = getChild(root, "modules"); //$NON-NLS-1$
if(findChild(modules, "module", textEquals(moduleName)) == null) { //$NON-NLS-1$
format(createElementWithText(modules, "module", moduleName)); //$NON-NLS-1$
}
}));
} catch(Exception e) {
LOG.error("Cannot add module to parent POM", e); //$NON-NLS-1$
}
}
} else {
Display.getDefault().asyncExec(() -> MessageDialog.openError(getShell(), //
NLS.bind(Messages.wizardProjectJobFailed, moduleName), //
result.getMessage()));
}
}
});
job.setRule(MavenPlugin.getProjectConfigurationManager().getRule());
job.schedule();
if(isEditor) {
try {
job.join();
} catch(InterruptedException ex) {
// ignore
}
}
return true;
}
void setModule(String moduleName) {
this.moduleName = moduleName;
}
public String getModuleName() {
return this.moduleName;
}
}