Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMickael Istria2015-04-13 15:22:44 +0000
committerMickael Istria2016-01-04 10:58:16 +0000
commit6e040948c097075d4d5709be82455330c6de0546 (patch)
treef114ea8f373fa63759e805123792ce5eb616b256 /org.eclipse.m2e.importer
parent09ee83add6c1b56384d50f2faac2c1161fc07ab9 (diff)
downloadm2e-core-6e040948c097075d4d5709be82455330c6de0546.tar.gz
m2e-core-6e040948c097075d4d5709be82455330c6de0546.tar.xz
m2e-core-6e040948c097075d4d5709be82455330c6de0546.zip
[464535] Contribution to smart import mechanism
See https://wiki.eclipse.org/E4/UI/Smart_Import Change-Id: I070e84c33191679d919fa22196546d05c5bfd618 Signed-off-by: Mickael Istria <mistria@redhat.com>
Diffstat (limited to 'org.eclipse.m2e.importer')
-rw-r--r--org.eclipse.m2e.importer/META-INF/MANIFEST.MF18
-rw-r--r--org.eclipse.m2e.importer/build.properties6
-rw-r--r--org.eclipse.m2e.importer/plugin.properties2
-rw-r--r--org.eclipse.m2e.importer/plugin.xml16
-rw-r--r--org.eclipse.m2e.importer/pom.xml17
-rw-r--r--org.eclipse.m2e.importer/src/org/eclipse/m2e/importer/internal/Activator.java64
-rw-r--r--org.eclipse.m2e.importer/src/org/eclipse/m2e/importer/internal/MavenProjectConfigurator.java269
7 files changed, 392 insertions, 0 deletions
diff --git a/org.eclipse.m2e.importer/META-INF/MANIFEST.MF b/org.eclipse.m2e.importer/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..6f58749d
--- /dev/null
+++ b/org.eclipse.m2e.importer/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name
+Bundle-SymbolicName: org.eclipse.m2e.importer;singleton:=true
+Bundle-Version: 1.7.0.qualifier
+Bundle-Vendor: %Bundle-Vendor
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.e4.ui.importer,
+ org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ org.eclipse.ui.ide,
+ org.eclipse.m2e.core;bundle-version="1.6.0",
+ org.eclipse.m2e.core.ui;bundle-version="1.6.0",
+ org.slf4j.api;bundle-version="1.6.2"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-ActivationPolicy: lazy
+Bundle-Activator: org.eclipse.m2e.importer.internal.Activator
diff --git a/org.eclipse.m2e.importer/build.properties b/org.eclipse.m2e.importer/build.properties
new file mode 100644
index 00000000..6e6a38f7
--- /dev/null
+++ b/org.eclipse.m2e.importer/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = target/classes
+bin.includes = META-INF/,\
+ .,\
+ plugin.properties,\
+ plugin.xml \ No newline at end of file
diff --git a/org.eclipse.m2e.importer/plugin.properties b/org.eclipse.m2e.importer/plugin.properties
new file mode 100644
index 00000000..e5b6534d
--- /dev/null
+++ b/org.eclipse.m2e.importer/plugin.properties
@@ -0,0 +1,2 @@
+Bundle-Vendor = Eclipse.org - m2e
+Bundle-Name = m2e extension for import framework \ No newline at end of file
diff --git a/org.eclipse.m2e.importer/plugin.xml b/org.eclipse.m2e.importer/plugin.xml
new file mode 100644
index 00000000..d1d0b96e
--- /dev/null
+++ b/org.eclipse.m2e.importer/plugin.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ point="org.eclipse.e4.ui.importer.projectConfigurators">
+ <projectConfigurator
+ class="org.eclipse.m2e.importer.internal.MavenProjectConfigurator"
+ label="Maven">
+ <activeWhen>
+ <hasFile
+ path="pom.xml">
+ </hasFile>
+ </activeWhen>
+ </projectConfigurator>
+ </extension>
+</plugin>
diff --git a/org.eclipse.m2e.importer/pom.xml b/org.eclipse.m2e.importer/pom.xml
new file mode 100644
index 00000000..15d15df3
--- /dev/null
+++ b/org.eclipse.m2e.importer/pom.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>m2e-core</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.eclipse.m2e.importer</artifactId>
+ <packaging>eclipse-plugin</packaging>
+
+ <name>Maven Integration for Eclipse Importer framework</name>
+
+</project>
diff --git a/org.eclipse.m2e.importer/src/org/eclipse/m2e/importer/internal/Activator.java b/org.eclipse.m2e.importer/src/org/eclipse/m2e/importer/internal/Activator.java
new file mode 100644
index 00000000..b6b87a45
--- /dev/null
+++ b/org.eclipse.m2e.importer/src/org/eclipse/m2e/importer/internal/Activator.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 Red Hat Inc.
+ * 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.importer.internal;
+
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.m2e.importer"; //$NON-NLS-1$
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.
+ * BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.
+ * BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+}
diff --git a/org.eclipse.m2e.importer/src/org/eclipse/m2e/importer/internal/MavenProjectConfigurator.java b/org.eclipse.m2e.importer/src/org/eclipse/m2e/importer/internal/MavenProjectConfigurator.java
new file mode 100644
index 00000000..df54c08a
--- /dev/null
+++ b/org.eclipse.m2e.importer/src/org/eclipse/m2e/importer/internal/MavenProjectConfigurator.java
@@ -0,0 +1,269 @@
+/*******************************************************************************
+ * Copyright (c) 2014-2015 Red Hat Inc.
+ * 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.importer.internal;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+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.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.wizard.IWizard;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.internal.IMavenConstants;
+import org.eclipse.m2e.core.internal.lifecyclemapping.discovery.LifecycleMappingDiscoveryRequest;
+import org.eclipse.m2e.core.internal.project.ProjectConfigurationManager;
+import org.eclipse.m2e.core.project.IProjectConfigurationManager;
+import org.eclipse.m2e.core.project.LocalProjectScanner;
+import org.eclipse.m2e.core.project.MavenProjectInfo;
+import org.eclipse.m2e.core.project.MavenUpdateRequest;
+import org.eclipse.m2e.core.project.ResolverConfiguration;
+import org.eclipse.m2e.core.ui.internal.wizards.LifecycleMappingDiscoveryHelper;
+import org.eclipse.m2e.core.ui.internal.wizards.MappingDiscoveryJob;
+import org.eclipse.ui.internal.wizards.datatransfer.EasymportJob;
+import org.eclipse.ui.wizards.datatransfer.ProjectConfigurator;
+
+public class MavenProjectConfigurator implements ProjectConfigurator {
+
+ private static class CumulativeMappingDiscoveryJob extends MappingDiscoveryJob {
+ private static CumulativeMappingDiscoveryJob INSTANCE;
+ private Set<IProject> toProcess;
+ private boolean started;
+
+ public synchronized static CumulativeMappingDiscoveryJob getInstance() {
+ if (INSTANCE == null) {
+ INSTANCE = new CumulativeMappingDiscoveryJob();
+ }
+ return INSTANCE;
+ }
+
+ private CumulativeMappingDiscoveryJob() {
+ super(null);
+ this.toProcess = Collections.synchronizedSet(new HashSet<IProject>());
+ }
+
+ public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
+ try {
+ // This makes job execution wait until the main Import job is completed
+ // So the mapping discovery happens as a next step, after projects are imported in workspace
+ getJobManager().join(EasymportJob.class, monitor);
+ } catch (InterruptedException ex) {
+ throw new CoreException(new Status(IStatus.WARNING,
+ Activator.getDefault().getBundle().getSymbolicName(), ex.getMessage(), ex));
+ }
+ synchronized (this.toProcess) {
+ this.started = true;
+ }
+ // Detect and resolve Lifecycle Mapping issues
+ try {
+ LifecycleMappingDiscoveryRequest discoveryRequest = LifecycleMappingDiscoveryHelper
+ .createLifecycleMappingDiscoveryRequest(toProcess, monitor);
+ if (discoveryRequest.isMappingComplete()) {
+ return Status.OK_STATUS;
+ }
+ // Some errors were detected
+ discoverProposals(discoveryRequest, monitor);
+ openProposalWizard(toProcess, discoveryRequest);
+ } finally {
+ this.toProcess.clear();
+ this.started = false;
+ }
+ return Status.OK_STATUS;
+ }
+
+ public void addProjects(Collection<IProject> projects) {
+ synchronized (this.toProcess) {
+ if (this.started) {
+ throw new IllegalStateException("Cannot add projects when processing is started");
+ }
+ if (projects != null) {
+ this.toProcess.addAll(projects);
+ }
+ }
+ }
+
+ }
+
+ /**
+ * This singleton job will loop running on the background to update
+ * configuration of Maven projects as they're imported.
+ *
+ * @author mistria
+ *
+ */
+ private static class UpdateMavenConfigurationJob extends Job {
+
+ private static UpdateMavenConfigurationJob INSTANCE;
+ private Set<IProject> toProcess;
+
+ public synchronized static UpdateMavenConfigurationJob getInstance() {
+ if (INSTANCE == null) {
+ INSTANCE = new UpdateMavenConfigurationJob();
+ }
+ return INSTANCE;
+ }
+
+ private UpdateMavenConfigurationJob() {
+ super("Update Maven projects configuration");
+ this.toProcess = Collections.synchronizedSet(new HashSet<IProject>());
+ this.setUser(true);
+ }
+
+ /**
+ * Rather than scheduling this job another time, requestors simply add
+ * to ask for being processed here. The job lifecycle will take care of
+ * processing it as best.
+ *
+ * @param project
+ */
+ public void addProjectToProcess(IProject project) {
+ synchronized (this.toProcess) {
+ toProcess.add(project);
+ }
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ Set<IProject> toProcessNow = new HashSet<IProject>();
+ while (!monitor.isCanceled()) {
+ synchronized (this.toProcess) {
+ if (this.toProcess.isEmpty()) {
+ CumulativeMappingDiscoveryJob.getInstance().schedule();
+ return Status.OK_STATUS;
+ } else {
+ toProcessNow.addAll(this.toProcess);
+ this.toProcess.removeAll(toProcessNow);
+ }
+ }
+ if (!toProcessNow.isEmpty()) {
+ CumulativeMappingDiscoveryJob.getInstance().addProjects(toProcessNow);
+ ProjectConfigurationManager configurationManager = (ProjectConfigurationManager) MavenPlugin
+ .getProjectConfigurationManager();
+ MavenUpdateRequest request = new MavenUpdateRequest(
+ toProcessNow.toArray(new IProject[toProcessNow.size()]), false, false);
+ Map<String, IStatus> updateStatus = configurationManager.updateProjectConfiguration(request, true,
+ false, false, monitor);
+ }
+ }
+ return new Status(IStatus.CANCEL, Activator.getDefault().getBundle().getSymbolicName(),
+ "Cancelled by user");
+ }
+
+ }
+
+ // TODO Uncomment @Override when following API got merged.
+ // this is commented in order to check it in build before API is available
+ // and avoid
+ // build failure because inteface doesn't declare the method (yet).
+ // @Override
+ public Set<File> findConfigurableLocations(File root, IProgressMonitor monitor) {
+ LocalProjectScanner scanner = new LocalProjectScanner(
+ ResourcesPlugin.getWorkspace().getRoot().getLocation().toFile(), root.getAbsolutePath(), false,
+ MavenPlugin.getMavenModelManager());
+ try {
+ scanner.run(monitor);
+ } catch (Exception ex) {
+ Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, ex.getMessage(), ex));
+ return null;
+ }
+ Queue<MavenProjectInfo> projects = new LinkedList<MavenProjectInfo>();
+ projects.addAll(scanner.getProjects());
+ HashSet<File> res = new HashSet<File>();
+ while (!projects.isEmpty()) {
+ MavenProjectInfo projectInfo = projects.poll();
+ res.add(projectInfo.getPomFile().getParentFile());
+ projects.addAll(projectInfo.getProjects());
+ }
+ return res;
+ }
+
+ @Override
+ public boolean canConfigure(IProject project, Set<IPath> ignoredPaths, IProgressMonitor monitor) {
+ return shouldBeAnEclipseProject(project, monitor);
+ }
+
+ @Override
+ public IWizard getConfigurationWizard() {
+ // no need for a wizard, will just set up the m2e nature
+ return null;
+ }
+
+ @Override
+ public void configure(final IProject project, Set<IPath> excludedDirectories, final IProgressMonitor monitor) {
+ // copied from
+ // org.eclipse.m2e.core.ui.internal.actions.EnableNatureAction
+
+ final ResolverConfiguration configuration = new ResolverConfiguration();
+ configuration.setResolveWorkspaceProjects(true);
+ final IProjectConfigurationManager configurationManager = MavenPlugin.getProjectConfigurationManager();
+ try {
+ if (!project.hasNature(IMavenConstants.NATURE_ID)) {
+ IProjectDescription description = project.getDescription();
+ String[] prevNatures = description.getNatureIds();
+ String[] newNatures = new String[prevNatures.length + 1];
+ System.arraycopy(prevNatures, 0, newNatures, 1, prevNatures.length);
+ newNatures[0] = IMavenConstants.NATURE_ID;
+ description.setNatureIds(newNatures);
+ project.setDescription(description, monitor);
+ }
+ UpdateMavenConfigurationJob.getInstance().addProjectToProcess(project);
+ if (UpdateMavenConfigurationJob.getInstance().getState() == Job.NONE) {
+ UpdateMavenConfigurationJob.getInstance().schedule();
+ }
+ } catch (Exception ex) {
+ Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, ex.getMessage(), ex));
+ }
+ }
+
+ @Override
+ public boolean shouldBeAnEclipseProject(IContainer container, IProgressMonitor monitor) {
+ IFile pomFile = container.getFile(new Path(IMavenConstants.POM_FILE_NAME));
+ return pomFile.exists();
+ // debated on m2e-dev:
+ // https://dev.eclipse.org/mhonarc/lists/m2e-dev/msg01852.html
+ // if (!pomFile.exists()) {
+ // return false;
+ // }
+ // try {
+ // Model pomModel =
+ // MavenPlugin.getMavenModelManager().readMavenModel(pomFile);
+ // return !pomModel.getPackaging().equals("pom"); // TODO find symbol
+ // for "pom"
+ // } catch (CoreException ex) {
+ // Activator.log(IStatus.ERROR, "Could not parse pom file " +
+ // pomFile.getLocation(), ex);
+ // return false;
+ // }
+ }
+
+ @Override
+ public Set<IFolder> getDirectoriesToIgnore(IProject project, IProgressMonitor monitor) {
+ Set<IFolder> res = new HashSet<IFolder>();
+ // TODO: get these values from pom/project config
+ res.add(project.getFolder("src"));
+ res.add(project.getFolder("target"));
+ return res;
+ }
+
+}

Back to the top