Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Fedorenko2017-11-19 18:26:34 -0500
committerIgor Fedorenko2018-05-21 09:17:14 -0400
commitb68b8b26d23c41b94abd1b02a1864ab52038f6c1 (patch)
tree0a61500c5afc9f8c56a4e65b308d5f1b81bcb3b0
parent4c27b30f5335de0e98805a42ff83622a854daedd (diff)
downloadm2e-core-b68b8b26d23c41b94abd1b02a1864ab52038f6c1.tar.gz
m2e-core-b68b8b26d23c41b94abd1b02a1864ab52038f6c1.tar.xz
m2e-core-b68b8b26d23c41b94abd1b02a1864ab52038f6c1.zip
Bug 384065: advanced sourcelookup support
Change-Id: Ib145445c60c686bbbc187f252b32591535ac740d Signed-off-by: Igor Fedorenko <igor@ifedorenko.com>
-rw-r--r--org.eclipse.m2e.binaryproject.tests/META-INF/MANIFEST.MF18
-rw-r--r--org.eclipse.m2e.binaryproject.tests/build.properties4
-rw-r--r--org.eclipse.m2e.binaryproject.tests/plugin_customization.ini10
-rw-r--r--org.eclipse.m2e.binaryproject.tests/pom.xml21
-rw-r--r--org.eclipse.m2e.binaryproject.tests/src/org/eclipse/m2e/binaryproject/tests/BinaryProjectTest.java66
-rw-r--r--org.eclipse.m2e.binaryproject.ui/META-INF/MANIFEST.MF15
-rw-r--r--org.eclipse.m2e.binaryproject.ui/build.properties6
-rw-r--r--org.eclipse.m2e.binaryproject.ui/icons/binary_project.gifbin0 -> 241 bytes
-rw-r--r--org.eclipse.m2e.binaryproject.ui/plugin.xml44
-rw-r--r--org.eclipse.m2e.binaryproject.ui/pom.xml21
-rw-r--r--org.eclipse.m2e.binaryproject.ui/src/org/eclipse/m2e/binaryproject/ui/internal/BinaryProjectImportAction.java57
-rw-r--r--org.eclipse.m2e.binaryproject.ui/src/org/eclipse/m2e/binaryproject/ui/internal/BinaryProjectImportWizard.java116
-rw-r--r--org.eclipse.m2e.binaryproject.ui/src/org/eclipse/m2e/binaryproject/ui/internal/BinaryprojectUIActivator.java61
-rw-r--r--org.eclipse.m2e.binaryproject/META-INF/MANIFEST.MF22
-rw-r--r--org.eclipse.m2e.binaryproject/build.properties5
-rw-r--r--org.eclipse.m2e.binaryproject/plugin.xml19
-rw-r--r--org.eclipse.m2e.binaryproject/pom.xml21
-rw-r--r--org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/AbstractBinaryProjectsImportJob.java56
-rw-r--r--org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/BinaryProjectLifecycleMapping.java65
-rw-r--r--org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/BinaryProjectPlugin.java142
-rw-r--r--org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/ClasspathConfigurator.java92
-rw-r--r--org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/sourcelookup/BinaryProjectContainerResolver.java74
-rw-r--r--org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/sourcelookup/BinaryProjectDescriber.java58
-rw-r--r--org.eclipse.m2e.feature/feature.xml28
-rw-r--r--org.eclipse.m2e.importer.tests/pom.xml48
-rw-r--r--org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchDelegate.java4
-rw-r--r--org.eclipse.m2e.sdk.feature/feature.xml28
-rw-r--r--org.eclipse.m2e.sourcelookup.ui/META-INF/MANIFEST.MF25
-rw-r--r--org.eclipse.m2e.sourcelookup.ui/build.properties6
-rw-r--r--org.eclipse.m2e.sourcelookup.ui/icons/binary_project.gifbin0 -> 241 bytes
-rw-r--r--org.eclipse.m2e.sourcelookup.ui/icons/open_pom.gifbin0 -> 249 bytes
-rw-r--r--org.eclipse.m2e.sourcelookup.ui/plugin.xml107
-rw-r--r--org.eclipse.m2e.sourcelookup.ui/pom.xml21
-rw-r--r--org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/ImportBinaryProjectHandler.java84
-rw-r--r--org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/OpenPomCommandHandler.java89
-rw-r--r--org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/OpenSourceLookupInfoDialogCommandHandler.java42
-rw-r--r--org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/SourceLookupInfoDialog.java225
-rw-r--r--org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/SourceLookupPreferencePage.java79
-rw-r--r--org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/SourceLookupUIActivator.java38
-rw-r--r--org.eclipse.m2e.sourcelookup/META-INF/MANIFEST.MF25
-rw-r--r--org.eclipse.m2e.sourcelookup/build.properties5
-rw-r--r--org.eclipse.m2e.sourcelookup/plugin.xml11
-rw-r--r--org.eclipse.m2e.sourcelookup/pom.xml21
-rw-r--r--org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MavenArtifactIdentifier.java160
-rw-r--r--org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MavenSourceContainerResolver.java85
-rw-r--r--org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MavenSourceLookupParticipant.java41
-rw-r--r--org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MetaInfMavenScanner.java90
-rw-r--r--pom.xml54
48 files changed, 2257 insertions, 52 deletions
diff --git a/org.eclipse.m2e.binaryproject.tests/META-INF/MANIFEST.MF b/org.eclipse.m2e.binaryproject.tests/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..e1f79f6a
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject.tests/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name
+Bundle-SymbolicName: org.eclipse.m2e.binaryproject.tests;singleton:=true
+Bundle-Version: 1.9.0.qualifier
+Bundle-Vendor: %Bundle-Vendor
+Require-Bundle: org.eclipse.m2e.core;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.m2e.maven.runtime;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.m2e.binaryproject;bundle-version="[1.9.0,1.10.0)",
+ org.slf4j.api;bundle-version="1.6.1",
+ org.junit;bundle-version="4.0.0",
+ org.eclipse.m2e.tests.common;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.equinox.common;bundle-version="3.6.100",
+ org.eclipse.core.resources;bundle-version="3.8.0",
+ org.eclipse.m2e.jdt;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.jdt.core;bundle-version="3.8.1",
+ org.eclipse.core.runtime;bundle-version="3.8.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
diff --git a/org.eclipse.m2e.binaryproject.tests/build.properties b/org.eclipse.m2e.binaryproject.tests/build.properties
new file mode 100644
index 00000000..ced5f40e
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject.tests/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = target/classes
+bin.includes = META-INF/,\
+ .
diff --git a/org.eclipse.m2e.binaryproject.tests/plugin_customization.ini b/org.eclipse.m2e.binaryproject.tests/plugin_customization.ini
new file mode 100644
index 00000000..cb717545
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject.tests/plugin_customization.ini
@@ -0,0 +1,10 @@
+# Copyright (c) 2010-2011 Sonatype, 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
+
+#
+# Add "-pluginCustomization plugin_customization.ini" to your Eclipse command line to apply these settings
+#
+org.eclipse.m2e.core/eclipse.m2.updateIndexes=false
diff --git a/org.eclipse.m2e.binaryproject.tests/pom.xml b/org.eclipse.m2e.binaryproject.tests/pom.xml
new file mode 100644
index 00000000..9d9e8254
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject.tests/pom.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2012 Igor Fedorenko
+ 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
+-->
+<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.9.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.eclipse.m2e.binaryproject.tests</artifactId>
+ <packaging>eclipse-test-plugin</packaging>
+</project> \ No newline at end of file
diff --git a/org.eclipse.m2e.binaryproject.tests/src/org/eclipse/m2e/binaryproject/tests/BinaryProjectTest.java b/org.eclipse.m2e.binaryproject.tests/src/org/eclipse/m2e/binaryproject/tests/BinaryProjectTest.java
new file mode 100644
index 00000000..001d5098
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject.tests/src/org/eclipse/m2e/binaryproject/tests/BinaryProjectTest.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.binaryproject.tests;
+
+import org.eclipse.core.resources.ICommand;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.m2e.binaryproject.internal.BinaryProjectPlugin;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.internal.IMavenConstants;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.jdt.internal.BuildPathManager;
+import org.eclipse.m2e.tests.common.AbstractMavenProjectTestCase;
+import org.eclipse.m2e.tests.common.ClasspathHelpers;
+
+@SuppressWarnings({"restriction"})
+public class BinaryProjectTest extends AbstractMavenProjectTestCase {
+ IProgressMonitor monitor = new NullProgressMonitor();
+
+ public void testBasic() throws Exception {
+ IProject project =
+ BinaryProjectPlugin.getInstance().create("org.apache.maven", "maven-core", "3.0.4", null, monitor);
+
+ assertTrue(project.hasNature(IMavenConstants.NATURE_ID));
+ assertTrue(project.hasNature(JavaCore.NATURE_ID));
+ assertNotNull(BuildPathManager.getMaven2ClasspathContainer(JavaCore.create(project)));
+ assertFalse(hasBuilder(project, JavaCore.BUILDER_ID));
+
+ IMavenProjectFacade facade = MavenPlugin.getMavenProjectRegistry().create(project, monitor);
+
+ assertNotNull(facade);
+ assertEquals(BinaryProjectPlugin.LIFECYCLE_MAPPING_ID, facade.getLifecycleMappingId());
+
+ IJavaProject javaProject = JavaCore.create(project);
+
+ ClasspathHelpers.assertClasspath(new String[] {"org.eclipse.jdt.launching.JRE_CONTAINER/.*",
+ "org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER", ".*/maven-core-3.0.4.jar"}, javaProject.getRawClasspath());
+
+ IClasspathEntry[] mavenClasspath = BuildPathManager.getMaven2ClasspathContainer(javaProject).getClasspathEntries();
+
+ assertTrue(mavenClasspath.length > 0);
+ }
+
+ private boolean hasBuilder(IProject project, String builderId) throws CoreException {
+ for (ICommand command : project.getDescription().getBuildSpec()) {
+ if (builderId.equals(command.getBuilderName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/org.eclipse.m2e.binaryproject.ui/META-INF/MANIFEST.MF b/org.eclipse.m2e.binaryproject.ui/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..84b3646f
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,15 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name
+Bundle-SymbolicName: org.eclipse.m2e.binaryproject.ui;singleton:=true
+Bundle-Version: 1.9.0.qualifier
+Bundle-Activator: org.eclipse.m2e.binaryproject.ui.internal.BinaryprojectUIActivator
+Bundle-Vendor: %Bundle-Vendor
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.m2e.core.ui;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.m2e.binaryproject;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.m2e.core;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.m2e.maven.runtime;bundle-version="[1.9.0,1.10.0)"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ActivationPolicy: lazy
diff --git a/org.eclipse.m2e.binaryproject.ui/build.properties b/org.eclipse.m2e.binaryproject.ui/build.properties
new file mode 100644
index 00000000..b806395b
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject.ui/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = target/classes/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml,\
+ icons/
diff --git a/org.eclipse.m2e.binaryproject.ui/icons/binary_project.gif b/org.eclipse.m2e.binaryproject.ui/icons/binary_project.gif
new file mode 100644
index 00000000..03c10b0b
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject.ui/icons/binary_project.gif
Binary files differ
diff --git a/org.eclipse.m2e.binaryproject.ui/plugin.xml b/org.eclipse.m2e.binaryproject.ui/plugin.xml
new file mode 100644
index 00000000..4d764856
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject.ui/plugin.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ point="org.eclipse.ui.importWizards">
+ <wizard
+ category="org.eclipse.m2e"
+ class="org.eclipse.m2e.binaryproject.ui.internal.BinaryProjectImportWizard"
+ icon="icons/binary_project.gif"
+ id="org.eclipse.m2e.binaryproject.ui.binaryProjectImportWizard"
+ name="Materialize Maven Binary Project">
+ </wizard>
+ </extension>
+ <extension
+ point="org.eclipse.ui.popupMenus">
+ <objectContribution
+ adaptable="true"
+ id="org.eclipse.m2e.binaryproject.ui.importBinaryProject"
+ objectClass="org.eclipse.jdt.core.IPackageFragmentRoot">
+ <action
+ class="org.eclipse.m2e.binaryproject.ui.internal.BinaryProjectImportAction"
+ enablesFor="+"
+ icon="icons/binary_project.gif"
+ id="org.eclipse.m2e.binaryproject.ui.action.importBinaryProjects"
+ label="Materialize Maven Binary Project"
+ menubarPath="org.eclipse.m2e.classpathMenu/import"
+ style="push">
+ </action>
+ <enablement>
+ <and>
+ <test
+ property="org.eclipse.m2e.hasArtifactKey">
+ </test>
+ <not>
+ <test
+ property="org.eclipse.m2e.hasProjectArtifactKey">
+ </test>
+ </not>
+ </and>
+ </enablement>
+ </objectContribution>
+ </extension>
+
+</plugin>
diff --git a/org.eclipse.m2e.binaryproject.ui/pom.xml b/org.eclipse.m2e.binaryproject.ui/pom.xml
new file mode 100644
index 00000000..0313eab3
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject.ui/pom.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2012 Igor Fedorenko
+ 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
+-->
+<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.9.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.eclipse.m2e.binaryproject.ui</artifactId>
+ <packaging>eclipse-plugin</packaging>
+</project> \ No newline at end of file
diff --git a/org.eclipse.m2e.binaryproject.ui/src/org/eclipse/m2e/binaryproject/ui/internal/BinaryProjectImportAction.java b/org.eclipse.m2e.binaryproject.ui/src/org/eclipse/m2e/binaryproject/ui/internal/BinaryProjectImportAction.java
new file mode 100644
index 00000000..ae2b3675
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject.ui/src/org/eclipse/m2e/binaryproject/ui/internal/BinaryProjectImportAction.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.binaryproject.ui.internal;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchPartSite;
+
+public class BinaryProjectImportAction implements IObjectActionDelegate {
+
+ private IStructuredSelection selection;
+
+ private IWorkbench workbench;
+
+ private IWorkbenchPartSite site;
+
+ @Override
+ public void run(IAction action) {
+ BinaryProjectImportWizard wizard = new BinaryProjectImportWizard();
+ wizard.init(workbench, selection);
+ if (!wizard.getInitialDependencies().isEmpty()) {
+ WizardDialog dialog = new WizardDialog(site.getShell(), wizard);
+ dialog.open();
+ } else {
+ wizard.dispose();
+ }
+ }
+
+ @Override
+ public void selectionChanged(IAction action, ISelection selection) {
+ if (selection instanceof IStructuredSelection) {
+ this.selection = (IStructuredSelection) selection;
+ } else {
+ selection = null;
+ }
+ }
+
+ @Override
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ site = targetPart.getSite();
+ workbench = site.getWorkbenchWindow().getWorkbench();
+ }
+
+}
diff --git a/org.eclipse.m2e.binaryproject.ui/src/org/eclipse/m2e/binaryproject/ui/internal/BinaryProjectImportWizard.java b/org.eclipse.m2e.binaryproject.ui/src/org/eclipse/m2e/binaryproject/ui/internal/BinaryProjectImportWizard.java
new file mode 100644
index 00000000..39a3181c
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject.ui/src/org/eclipse/m2e/binaryproject/ui/internal/BinaryProjectImportWizard.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.binaryproject.ui.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.maven.model.Dependency;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.m2e.binaryproject.internal.AbstractBinaryProjectsImportJob;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.m2e.core.ui.internal.actions.SelectionUtil;
+import org.eclipse.m2e.core.ui.internal.wizards.MavenDependenciesWizardPage;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IImportWizard;
+import org.eclipse.ui.IWorkbench;
+
+@SuppressWarnings("restriction")
+public class BinaryProjectImportWizard extends Wizard implements IImportWizard {
+
+ private MavenDependenciesWizardPage artifactsPage;
+
+ private List<Dependency> initialDependencies;
+
+ public BinaryProjectImportWizard() {}
+
+ @Override
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ final List<Dependency> dependencies = new ArrayList<Dependency>();
+ for (Iterator<?> it = selection.iterator(); it.hasNext();) {
+ Object element = it.next();
+ ArtifactKey artifactKey = SelectionUtil.getType(element, ArtifactKey.class);
+ if (artifactKey != null) {
+ Dependency d = new Dependency();
+ d.setGroupId(artifactKey.getGroupId());
+ d.setArtifactId(artifactKey.getArtifactId());
+ d.setVersion(artifactKey.getVersion());
+ d.setClassifier(artifactKey.getClassifier());
+ dependencies.add(d);
+ }
+ }
+ artifactsPage =
+ new MavenDependenciesWizardPage(new ProjectImportConfiguration(), "Artifacts", "Select artifacts to import") {
+ @Override
+ protected void createAdvancedSettings(Composite composite, GridData gridData) {
+ // TODO profile can theoretically be usedful
+ }
+ };
+ artifactsPage.setDependencies(dependencies.toArray(new Dependency[dependencies.size()]));
+ artifactsPage.addListener(new ISelectionChangedListener() {
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+ getContainer().updateButtons();
+ }
+ });
+ this.initialDependencies = Collections.unmodifiableList(dependencies);
+ }
+
+ @Override
+ public boolean performFinish() {
+ final ArrayList<ArtifactKey> artifacts = new ArrayList<ArtifactKey>();
+
+ for (Dependency dependency : artifactsPage.getDependencies()) {
+ artifacts.add(new ArtifactKey(dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(),
+ dependency.getClassifier()));
+ }
+
+ if (artifacts.isEmpty()) {
+ return false;
+ }
+
+ Job job = new AbstractBinaryProjectsImportJob() {
+
+ @Override
+ protected Collection<ArtifactKey> getArtifactKeys(IProgressMonitor monitor) throws CoreException {
+ return artifacts;
+ }
+ };
+ job.schedule();
+
+ return true;
+ }
+
+ @Override
+ public boolean canFinish() {
+ return artifactsPage.getDependencies().length > 0;
+ }
+
+ @Override
+ public void addPages() {
+ addPage(artifactsPage);
+ }
+
+ public List<Dependency> getInitialDependencies() {
+ return initialDependencies;
+ }
+}
diff --git a/org.eclipse.m2e.binaryproject.ui/src/org/eclipse/m2e/binaryproject/ui/internal/BinaryprojectUIActivator.java b/org.eclipse.m2e.binaryproject.ui/src/org/eclipse/m2e/binaryproject/ui/internal/BinaryprojectUIActivator.java
new file mode 100644
index 00000000..a552c08d
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject.ui/src/org/eclipse/m2e/binaryproject/ui/internal/BinaryprojectUIActivator.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.binaryproject.ui.internal;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class BinaryprojectUIActivator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.m2e.binaryproject.ui"; //$NON-NLS-1$
+
+ // The shared instance
+ private static BinaryprojectUIActivator plugin;
+
+ /**
+ * The constructor
+ */
+ public BinaryprojectUIActivator() {}
+
+ /*
+ * (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 BinaryprojectUIActivator getDefault() {
+ return plugin;
+ }
+
+}
diff --git a/org.eclipse.m2e.binaryproject/META-INF/MANIFEST.MF b/org.eclipse.m2e.binaryproject/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..4a2067de
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject/META-INF/MANIFEST.MF
@@ -0,0 +1,22 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name
+Bundle-SymbolicName: org.eclipse.m2e.binaryproject;singleton:=true
+Bundle-Version: 1.9.0.qualifier
+Bundle-Vendor: %Bundle-Vendor
+Require-Bundle: org.eclipse.m2e.core;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.m2e.maven.runtime;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.m2e.sourcelookup;bundle-version="[1.9.0,1.10.0)",
+ org.slf4j.api;bundle-version="1.6.1",
+ org.eclipse.equinox.common;bundle-version="3.6.0",
+ org.eclipse.m2e.jdt;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.core.resources;bundle-version="3.7.0",
+ org.eclipse.jdt.core;bundle-version="3.7.0",
+ org.eclipse.equinox.registry;bundle-version="3.5.0",
+ org.eclipse.core.runtime;bundle-version="3.7.0",
+ org.eclipse.debug.core;bundle-version="3.9.0",
+ org.eclipse.jdt.launching;bundle-version="3.10.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Export-Package: org.eclipse.m2e.binaryproject.internal;x-friends:="org.eclipse.m2e.sourcelookup,org.eclipse.m2e.sourcelookup.ui"
+Bundle-ActivationPolicy: lazy
+Bundle-Activator: org.eclipse.m2e.binaryproject.internal.BinaryProjectPlugin
diff --git a/org.eclipse.m2e.binaryproject/build.properties b/org.eclipse.m2e.binaryproject/build.properties
new file mode 100644
index 00000000..52a5b4fe
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = target/classes
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml
diff --git a/org.eclipse.m2e.binaryproject/plugin.xml b/org.eclipse.m2e.binaryproject/plugin.xml
new file mode 100644
index 00000000..55064563
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject/plugin.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ point="org.eclipse.m2e.core.lifecycleMappings">
+ <lifecycleMapping
+ class="org.eclipse.m2e.binaryproject.internal.BinaryProjectLifecycleMapping"
+ id="org.eclipse.m2e.binaryproject"
+ name="Maven Binary Project">
+ </lifecycleMapping>
+ </extension>
+ <extension
+ point="org.eclipse.jdt.launching.workspaceProjectDescribers">
+ <describer
+ class="org.eclipse.m2e.binaryproject.internal.sourcelookup.BinaryProjectDescriber">
+ </describer>
+ </extension>
+
+</plugin>
diff --git a/org.eclipse.m2e.binaryproject/pom.xml b/org.eclipse.m2e.binaryproject/pom.xml
new file mode 100644
index 00000000..61859cfd
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject/pom.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2012 Igor Fedorenko
+ 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
+-->
+<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.9.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.eclipse.m2e.binaryproject</artifactId>
+ <packaging>eclipse-plugin</packaging>
+</project> \ No newline at end of file
diff --git a/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/AbstractBinaryProjectsImportJob.java b/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/AbstractBinaryProjectsImportJob.java
new file mode 100644
index 00000000..e80cb3fa
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/AbstractBinaryProjectsImportJob.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.binaryproject.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+
+public abstract class AbstractBinaryProjectsImportJob extends Job {
+
+ public AbstractBinaryProjectsImportJob() {
+ super("Import binary projects");
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ Collection<ArtifactKey> artifacts;
+ try {
+ artifacts = getArtifactKeys(monitor);
+ } catch (CoreException e1) {
+ return e1.getStatus();
+ }
+
+ if (!artifacts.isEmpty()) {
+ List<IStatus> errors = new ArrayList<IStatus>();
+
+ for (ArtifactKey artifact : artifacts) {
+ try {
+ BinaryProjectPlugin.getInstance().create(artifact.getGroupId(), artifact.getArtifactId(),
+ artifact.getVersion(), null, monitor);
+ } catch (CoreException e) {
+ errors.add(e.getStatus());
+ }
+ }
+ }
+ return Status.OK_STATUS;
+ }
+
+ protected abstract Collection<ArtifactKey> getArtifactKeys(IProgressMonitor monitor) throws CoreException;
+
+}
diff --git a/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/BinaryProjectLifecycleMapping.java b/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/BinaryProjectLifecycleMapping.java
new file mode 100644
index 00000000..867806b9
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/BinaryProjectLifecycleMapping.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.binaryproject.internal;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.internal.MavenPluginActivator;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.configurator.AbstractBuildParticipant;
+import org.eclipse.m2e.core.project.configurator.AbstractLifecycleMapping;
+import org.eclipse.m2e.core.project.configurator.AbstractProjectConfigurator;
+import org.eclipse.m2e.core.project.configurator.ILifecycleMappingConfiguration;
+import org.eclipse.m2e.core.project.configurator.MojoExecutionKey;
+import org.eclipse.m2e.core.project.configurator.ProjectConfigurationRequest;
+
+@SuppressWarnings("restriction")
+public class BinaryProjectLifecycleMapping extends AbstractLifecycleMapping {
+ private final ClasspathConfigurator configurator;
+
+ public BinaryProjectLifecycleMapping() {
+ ClasspathConfigurator configurator = new ClasspathConfigurator();
+ configurator.setProjectManager(MavenPlugin.getMavenProjectRegistry());
+ configurator.setMavenConfiguration(MavenPlugin.getMavenConfiguration());
+ configurator.setMarkerManager(MavenPluginActivator.getDefault().getMavenMarkerManager());
+
+ this.configurator = configurator;
+ }
+
+ @Override
+ public Map<MojoExecutionKey, List<AbstractBuildParticipant>> getBuildParticipants(IMavenProjectFacade project,
+ IProgressMonitor monitor) throws CoreException {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public List<AbstractProjectConfigurator> getProjectConfigurators(IMavenProjectFacade project,
+ IProgressMonitor monitor) throws CoreException {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean hasLifecycleMappingChanged(IMavenProjectFacade newFacade,
+ ILifecycleMappingConfiguration oldConfiguration, IProgressMonitor monitor) {
+ return false;
+ }
+
+ public void configure(ProjectConfigurationRequest request, IProgressMonitor monitor) throws CoreException {
+ configurator.configure(request, monitor);
+ }
+
+ public void unconfigure(ProjectConfigurationRequest request, IProgressMonitor monitor) {}
+}
diff --git a/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/BinaryProjectPlugin.java b/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/BinaryProjectPlugin.java
new file mode 100644
index 00000000..652f5c13
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/BinaryProjectPlugin.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.binaryproject.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.codehaus.plexus.util.FileUtils;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ProjectScope;
+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.Platform;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.embedder.IMaven;
+import org.eclipse.m2e.core.project.IProjectConfigurationManager;
+import org.eclipse.m2e.core.project.ResolverConfiguration;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.prefs.BackingStoreException;
+
+public class BinaryProjectPlugin implements BundleActivator {
+
+ public static final String PLUGIN_ID = "org.eclipse.m2e.binaryproject";
+
+ public static final String LIFECYCLE_MAPPING_ID = "org.eclipse.m2e.binaryproject";
+
+ public static final String P_GROUPID = "groupId";
+
+ public static final String P_ARTIFACTID = "artifactId";
+
+ public static final String P_VERSION = "version";
+
+ public static final String P_TYPE = "type";
+
+ public static final String P_CLASSIFIER = "classifier";
+
+ /**
+ * Name of IProject persistent property that identifies absolute filesystem path of the target jar artifact of the
+ * workspace binary project.
+ */
+ public static final QualifiedName QNAME_JAR = new QualifiedName(PLUGIN_ID, "jar");
+
+ private static BinaryProjectPlugin SELF;
+
+ public static BinaryProjectPlugin getInstance() {
+ return SELF;
+ }
+
+ private Bundle bundle;
+
+ public IProject create(String groupId, String artifactId, String version, List<ArtifactRepository> repositories,
+ IProgressMonitor monitor) throws CoreException {
+ IMaven maven = MavenPlugin.getMaven();
+
+ Artifact pomArtifact =
+ maven.resolve(groupId, artifactId, version, "pom" /* type */, null /* classifier */, repositories, monitor);
+
+ ResolverConfiguration resolverConfig = new ResolverConfiguration();
+ resolverConfig.setLifecycleMappingId(LIFECYCLE_MAPPING_ID);
+
+ String projectName = groupId + "_" + artifactId + "_" + version;
+
+ IPath stateLocation = Platform.getStateLocation(bundle);
+
+ IPath projectLocation = stateLocation.append(projectName);
+ projectLocation.toFile().mkdirs();
+
+ File pomFile = new File(projectLocation.toFile(), "pom.xml");
+
+ try {
+ FileUtils.copyFile(pomArtifact.getFile(), pomFile);
+ } catch (IOException e) {
+ throw new CoreException(new Status(IStatus.ERROR, PLUGIN_ID, "Could not create binary project", e));
+ }
+
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ IWorkspaceRoot root = workspace.getRoot();
+
+ IProject project = root.getProject(projectName);
+
+ IProjectDescription description = workspace.newProjectDescription(projectName);
+ description.setLocation(projectLocation);
+ project.create(description, monitor);
+ project.open(monitor);
+
+ IScopeContext projectScope = new ProjectScope(project);
+ IEclipsePreferences projectNode = projectScope.getNode(BinaryProjectPlugin.PLUGIN_ID);
+
+ projectNode.put(P_GROUPID, groupId);
+ projectNode.put(P_ARTIFACTID, artifactId);
+ projectNode.put(P_VERSION, version);
+ // String type = projectNode.get( P_TYPE, "jar" );
+ // String classifier = projectNode.get( P_CLASSIFIER, (String) null );
+
+ try {
+ projectNode.flush();
+ } catch (BackingStoreException e) {
+ throw new CoreException(new Status(IStatus.ERROR, PLUGIN_ID, "Could not create binary project", e));
+ }
+
+ IProjectConfigurationManager configManager = MavenPlugin.getProjectConfigurationManager();
+
+ configManager.enableMavenNature(project, resolverConfig, monitor);
+
+ return project;
+ }
+
+ @Override
+ public void start(BundleContext context) throws Exception {
+ this.bundle = context.getBundle();
+ BinaryProjectPlugin.SELF = this;
+ }
+
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ BinaryProjectPlugin.SELF = null;
+ this.bundle = null;
+ }
+}
diff --git a/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/ClasspathConfigurator.java b/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/ClasspathConfigurator.java
new file mode 100644
index 00000000..c84c9fc1
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/ClasspathConfigurator.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.binaryproject.internal;
+
+import java.util.List;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.embedder.IMaven;
+import org.eclipse.m2e.core.project.configurator.ProjectConfigurationRequest;
+import org.eclipse.m2e.jdt.IClasspathDescriptor;
+import org.eclipse.m2e.jdt.IClasspathEntryDescriptor;
+import org.eclipse.m2e.jdt.internal.AbstractJavaProjectConfigurator;
+import org.eclipse.m2e.jdt.internal.BuildPathManager;
+
+@SuppressWarnings("restriction")
+public class ClasspathConfigurator extends AbstractJavaProjectConfigurator {
+
+ @Override
+ protected void addProjectSourceFolders(IClasspathDescriptor classpath, ProjectConfigurationRequest request,
+ IProgressMonitor monitor) throws CoreException {}
+
+ @Override
+ protected void addJavaNature(IProject project, IProgressMonitor monitor) throws CoreException {
+ addNature(project, JavaCore.NATURE_ID, IResource.KEEP_HISTORY | IResource.AVOID_NATURE_CONFIG, monitor);
+ }
+
+ @Override
+ protected void invokeJavaProjectConfigurators(IClasspathDescriptor classpath, ProjectConfigurationRequest request,
+ IProgressMonitor monitor) throws CoreException {
+ // TODO need repository information
+
+ IProject project = request.getProject();
+
+ IMaven maven = MavenPlugin.getMaven();
+
+ IScopeContext projectScope = new ProjectScope(project);
+ IEclipsePreferences projectNode = projectScope.getNode(BinaryProjectPlugin.PLUGIN_ID);
+
+ String groupId = projectNode.get(BinaryProjectPlugin.P_GROUPID, (String) null);
+ String artifactId = projectNode.get(BinaryProjectPlugin.P_ARTIFACTID, (String) null);
+ String version = projectNode.get(BinaryProjectPlugin.P_VERSION, (String) null);
+ String type = projectNode.get(BinaryProjectPlugin.P_TYPE, "jar");
+ String classifier = projectNode.get(BinaryProjectPlugin.P_CLASSIFIER, (String) null);
+
+ List<ArtifactRepository> repositories = null; // TODO store in project preferences
+
+ Artifact jar = maven.resolve(groupId, artifactId, version, type, classifier, repositories, monitor);
+ String jarLocation = jar.getFile().getAbsolutePath();
+
+ project.setPersistentProperty(BinaryProjectPlugin.QNAME_JAR, jarLocation);
+
+ Artifact sources =
+ maven.resolve(groupId, artifactId, version, type, getSourcesClassifier(classifier), repositories, monitor);
+ IClasspathEntryDescriptor libEntry = classpath.addLibraryEntry(Path.fromOSString(jarLocation));
+ libEntry.setExported(true);
+ libEntry.setSourceAttachment(Path.fromOSString(sources.getFile().getAbsolutePath()), null);
+ libEntry.setArtifactKey(new ArtifactKey(groupId, artifactId, version, classifier));
+ }
+
+ @Override
+ protected IContainer getOutputLocation(ProjectConfigurationRequest request, IProject project) {
+ return project;
+ }
+
+ static String getSourcesClassifier(String baseClassifier) {
+ return BuildPathManager.CLASSIFIER_TESTS.equals(baseClassifier)
+ ? BuildPathManager.CLASSIFIER_TESTSOURCES
+ : BuildPathManager.CLASSIFIER_SOURCES;
+ }
+
+}
diff --git a/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/sourcelookup/BinaryProjectContainerResolver.java b/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/sourcelookup/BinaryProjectContainerResolver.java
new file mode 100644
index 00000000..f374a4fd
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/sourcelookup/BinaryProjectContainerResolver.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.binaryproject.internal.sourcelookup;
+
+import static org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedSourceLookup.getClasspath;
+import static org.eclipse.m2e.binaryproject.internal.sourcelookup.BinaryProjectDescriber.getBinaryLocation;
+
+import java.io.File;
+import java.util.Map;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.sourcelookup.ISourceContainer;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.launching.sourcelookup.advanced.ISourceContainerResolver;
+import org.eclipse.jdt.launching.sourcelookup.containers.PackageFragmentRootSourceContainer;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.IMavenProjectRegistry;
+import org.eclipse.m2e.sourcelookup.internal.launch.MavenSourceContainerResolver;
+
+// useful to lookup shaded binary projects like wagon-http-2.10-shaded.jar
+public class BinaryProjectContainerResolver extends MavenSourceContainerResolver implements ISourceContainerResolver {
+
+ @Override
+ protected ISourceContainer resolveSourceContainer(ArtifactKey artifact, IProgressMonitor monitor) {
+ String groupId = artifact.getGroupId();
+ String artifactId = artifact.getArtifactId();
+ String version = artifact.getVersion();
+
+ IMavenProjectRegistry projectRegistry = MavenPlugin.getMavenProjectRegistry();
+
+ IMavenProjectFacade mavenProject = projectRegistry.getMavenProject(groupId, artifactId, version);
+ if (mavenProject == null) {
+ return null;
+ }
+
+ IProject project = mavenProject.getProject();
+
+ try {
+ final File binaryLocation = getBinaryLocation(project);
+ if (binaryLocation == null) {
+ return null;
+ }
+
+ IJavaProject javaProject = JavaCore.create(project);
+
+ Map<File, IPackageFragmentRoot> classpath = getClasspath(javaProject);
+ IPackageFragmentRoot binary = classpath.remove(binaryLocation);
+
+ if (binary == null) {
+ return null; // this is a bug somewhere in my code
+ }
+
+ return new PackageFragmentRootSourceContainer(binary);
+ } catch (CoreException e) {
+ // ignore, maybe log
+ }
+
+ return null;
+ }
+}
diff --git a/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/sourcelookup/BinaryProjectDescriber.java b/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/sourcelookup/BinaryProjectDescriber.java
new file mode 100644
index 00000000..5619de39
--- /dev/null
+++ b/org.eclipse.m2e.binaryproject/src/org/eclipse/m2e/binaryproject/internal/sourcelookup/BinaryProjectDescriber.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.binaryproject.internal.sourcelookup;
+
+import static org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedSourceLookup.getClasspath;
+
+import java.io.File;
+import java.util.Map;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.launching.sourcelookup.advanced.IWorkspaceProjectDescriber;
+import org.eclipse.jdt.launching.sourcelookup.containers.PackageFragmentRootSourceContainer;
+import org.eclipse.m2e.binaryproject.internal.BinaryProjectPlugin;
+
+public class BinaryProjectDescriber implements IWorkspaceProjectDescriber {
+
+ static File getBinaryLocation(IProject project) throws CoreException {
+ if (!project.isOpen()) {
+ return null;
+ }
+ final String binaryLocation = project.getPersistentProperty(BinaryProjectPlugin.QNAME_JAR);
+ if (binaryLocation == null) {
+ return null;
+ }
+ return new File(binaryLocation);
+ }
+
+ @Override
+ public void describeProject(IJavaProject project, IJavaProjectSourceDescription description) throws CoreException {
+ final File binaryLocation = getBinaryLocation(project.getProject());
+ if (binaryLocation == null) {
+ return;
+ }
+
+ Map<File, IPackageFragmentRoot> classpath = getClasspath(project);
+ IPackageFragmentRoot binary = classpath.remove(binaryLocation);
+
+ if (binary == null) {
+ return; // this is a bug somewhere in my code
+ }
+
+ description.addDependencies(classpath);
+ description.addLocation(binaryLocation);
+ description.addSourceContainerFactory(() -> new PackageFragmentRootSourceContainer(binary));
+ }
+
+}
diff --git a/org.eclipse.m2e.feature/feature.xml b/org.eclipse.m2e.feature/feature.xml
index 393caf7c..dd512e97 100644
--- a/org.eclipse.m2e.feature/feature.xml
+++ b/org.eclipse.m2e.feature/feature.xml
@@ -170,4 +170,32 @@
version="0.0.0"
unpack="false"/>
+ <plugin
+ id="org.eclipse.m2e.sourcelookup"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.m2e.sourcelookup.ui"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.m2e.binaryproject"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.m2e.binaryproject.ui"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
</feature>
diff --git a/org.eclipse.m2e.importer.tests/pom.xml b/org.eclipse.m2e.importer.tests/pom.xml
index fbf7340b..07182c6f 100644
--- a/org.eclipse.m2e.importer.tests/pom.xml
+++ b/org.eclipse.m2e.importer.tests/pom.xml
@@ -24,10 +24,6 @@ Contributors:
<name>Tests for Maven Integration for Eclipse Importer framework</name>
- <properties>
- <tycho.test.jvmArgs>-Xmx800m</tycho.test.jvmArgs>
- <tycho.surefire.timeout>300</tycho.surefire.timeout>
- </properties>
<build>
<pluginManagement>
<plugins>
@@ -38,53 +34,9 @@ Contributors:
<configuration>
<useUIHarness>true</useUIHarness>
<useUIThread>false</useUIThread>
- <!-- kill test JVM if tests take more than 10 minutes (600 seconds) to finish -->
- <forkedProcessTimeoutInSeconds>${tycho.surefire.timeout}</forkedProcessTimeoutInSeconds>
- <argLine>${tycho.test.jvmArgs}</argLine>
- <includes>
- <include>**/*Test.class</include>
- </includes>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
- <profiles>
- <profile>
- <id>osx</id>
- <activation>
- <os>
- <family>mac</family>
- </os>
- </activation>
- <properties>
- <tycho.test.jvmArgs>-Xmx800m -Dosgi.ws=cocoa -XstartOnFirstThread</tycho.test.jvmArgs>
- </properties>
- <build>
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.eclipse.tycho</groupId>
- <artifactId>tycho-surefire-plugin</artifactId>
- <version>${tycho-version}</version>
- <configuration>
- <dependencies combine.children="append">
- <dependency>
- <artifactId>org.eclipse.jdt.launching.macosx</artifactId>
- <version>0.0.0</version>
- <type>eclipse-plugin</type>
- </dependency>
- <dependency>
- <type>eclipse-feature</type>
- <artifactId>org.eclipse.e4.rcp</artifactId>
- <version>0.0.0</version>
- </dependency>
- </dependencies>
- </configuration>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
- </profile>
- </profiles>
</project>
diff --git a/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchDelegate.java b/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchDelegate.java
index 42ae7742..ac6bcaed 100644
--- a/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchDelegate.java
+++ b/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchDelegate.java
@@ -75,6 +75,10 @@ public class MavenLaunchDelegate extends JavaLaunchDelegate implements MavenLaun
private MavenLaunchExtensionsSupport extensionsSupport;
+ public MavenLaunchDelegate() {
+ allowAdvancedSourcelookup();
+ }
+
public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor)
throws CoreException {
this.launch = launch;
diff --git a/org.eclipse.m2e.sdk.feature/feature.xml b/org.eclipse.m2e.sdk.feature/feature.xml
index b8443d9f..9611b6d6 100644
--- a/org.eclipse.m2e.sdk.feature/feature.xml
+++ b/org.eclipse.m2e.sdk.feature/feature.xml
@@ -144,4 +144,32 @@
version="0.0.0"
unpack="false"/>
+ <plugin
+ id="org.eclipse.m2e.sourcelookup.source"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.m2e.sourcelookup.ui.source"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.m2e.binaryproject.source"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.m2e.binaryproject.ui.source"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
</feature>
diff --git a/org.eclipse.m2e.sourcelookup.ui/META-INF/MANIFEST.MF b/org.eclipse.m2e.sourcelookup.ui/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..55329baf
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,25 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name
+Bundle-SymbolicName: org.eclipse.m2e.sourcelookup.ui;singleton:=true
+Bundle-Version: 1.9.0.qualifier
+Bundle-Activator: org.eclipse.m2e.sourcelookup.ui.internal.SourceLookupUIActivator
+Bundle-Vendor: %Bundle-Vendor
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.debug.ui;bundle-version="3.7.0",
+ org.eclipse.jdt.debug.ui;bundle-version="3.6.0",
+ org.eclipse.m2e.core;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.jdt.debug;bundle-version="3.7.0",
+ org.eclipse.m2e.sourcelookup;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.m2e.core.ui;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.m2e.maven.runtime;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.ui.ide;bundle-version="3.7.0",
+ org.eclipse.m2e.binaryproject;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.core.expressions,
+ org.eclipse.jdt.launching;bundle-version="3.10.0",
+ org.eclipse.jdt.core;bundle-version="3.9.0",
+ org.eclipse.core.resources,
+ org.eclipse.debug.core
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ActivationPolicy: lazy
diff --git a/org.eclipse.m2e.sourcelookup.ui/build.properties b/org.eclipse.m2e.sourcelookup.ui/build.properties
new file mode 100644
index 00000000..b806395b
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup.ui/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = target/classes/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml,\
+ icons/
diff --git a/org.eclipse.m2e.sourcelookup.ui/icons/binary_project.gif b/org.eclipse.m2e.sourcelookup.ui/icons/binary_project.gif
new file mode 100644
index 00000000..03c10b0b
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup.ui/icons/binary_project.gif
Binary files differ
diff --git a/org.eclipse.m2e.sourcelookup.ui/icons/open_pom.gif b/org.eclipse.m2e.sourcelookup.ui/icons/open_pom.gif
new file mode 100644
index 00000000..aa4c32cd
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup.ui/icons/open_pom.gif
Binary files differ
diff --git a/org.eclipse.m2e.sourcelookup.ui/plugin.xml b/org.eclipse.m2e.sourcelookup.ui/plugin.xml
new file mode 100644
index 00000000..240d8388
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup.ui/plugin.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ point="org.eclipse.ui.menus">
+ <menuContribution
+ allPopups="false"
+ locationURI="popup:org.eclipse.ui.popup.any?after=additions">
+ <command
+ commandId="org.eclipse.m2e.sourcelookup.ui.openPom"
+ icon="icons/open_pom.gif"
+ style="push">
+ <visibleWhen
+ checkEnabled="true">
+ </visibleWhen>
+ </command>
+ <command
+ commandId="org.eclipse.m2e.sourcelookup.ui.importBinaryProject"
+ icon="icons/binary_project.gif"
+ style="push">
+ <visibleWhen
+ checkEnabled="true">
+ </visibleWhen>
+ </command>
+ <command
+ commandId="org.eclipse.m2e.sourcelookup.ui.openSourceLookupInfoDialog"
+ style="push">
+ <visibleWhen
+ checkEnabled="true">
+ </visibleWhen>
+ </command>
+ </menuContribution>
+ </extension>
+ <extension
+ point="org.eclipse.ui.commands">
+ <command
+ id="org.eclipse.m2e.sourcelookup.ui.openPom"
+ name="Open Pom">
+ </command>
+ <command
+ id="org.eclipse.m2e.sourcelookup.ui.importBinaryProject"
+ name="Import Binary Project">
+ </command>
+ <command
+ id="org.eclipse.m2e.sourcelookup.ui.openSourceLookupInfoDialog"
+ name="Source Lookup Info">
+ </command>
+ </extension>
+ <extension
+ point="org.eclipse.ui.handlers">
+ <handler
+ class="org.eclipse.m2e.sourcelookup.ui.internal.OpenPomCommandHandler"
+ commandId="org.eclipse.m2e.sourcelookup.ui.openPom">
+ <enabledWhen>
+ <reference
+ definitionId="org.eclipse.m2e.sourcelookup.ui.m2estratum">
+ </reference>
+ </enabledWhen>
+ </handler>
+ <handler
+ class="org.eclipse.m2e.sourcelookup.ui.internal.ImportBinaryProjectHandler"
+ commandId="org.eclipse.m2e.sourcelookup.ui.importBinaryProject">
+ <enabledWhen>
+ <reference
+ definitionId="org.eclipse.m2e.sourcelookup.ui.m2estratum">
+ </reference>
+ </enabledWhen>
+ </handler>
+ <handler
+ class="org.eclipse.m2e.sourcelookup.ui.internal.OpenSourceLookupInfoDialogCommandHandler"
+ commandId="org.eclipse.m2e.sourcelookup.ui.openSourceLookupInfoDialog">
+ <enabledWhen>
+ <reference
+ definitionId="org.eclipse.m2e.sourcelookup.ui.m2estratum">
+ </reference>
+ </enabledWhen>
+ </handler>
+ </extension>
+ <extension
+ point="org.eclipse.core.expressions.definitions">
+ <definition
+ id="org.eclipse.m2e.sourcelookup.ui.m2estratum">
+ <with
+ variable="selection">
+ <count
+ value="1">
+ </count>
+ <iterate
+ ifEmpty="false"
+ operator="or">
+ <test
+ property="org.eclipse.jdt.launching.jdtstratum">
+ </test>
+ </iterate>
+ </with>
+ </definition>
+ </extension>
+ <extension
+ point="org.eclipse.ui.preferencePages">
+ <page
+ category="org.eclipse.m2e.core.preferences.Maven2PreferencePage"
+ class="org.eclipse.m2e.sourcelookup.ui.internal.SourceLookupPreferencePage"
+ id="org.eclipse.m2e.sourcelookup.ui.internal.SourceLookupPreferencePage"
+ name="Source Lookup">
+ </page>
+ </extension>
+</plugin>
diff --git a/org.eclipse.m2e.sourcelookup.ui/pom.xml b/org.eclipse.m2e.sourcelookup.ui/pom.xml
new file mode 100644
index 00000000..3a1f18e9
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup.ui/pom.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2011 Igor Fedorenko
+ 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
+-->
+<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.9.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.eclipse.m2e.sourcelookup.ui</artifactId>
+ <packaging>eclipse-plugin</packaging>
+</project> \ No newline at end of file
diff --git a/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/ImportBinaryProjectHandler.java b/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/ImportBinaryProjectHandler.java
new file mode 100644
index 00000000..c51aef22
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/ImportBinaryProjectHandler.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.sourcelookup.ui.internal;
+
+import java.io.File;
+import java.util.Collection;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedSourceLookup;
+import org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedSourceLookupParticipant;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.m2e.binaryproject.internal.AbstractBinaryProjectsImportJob;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.sourcelookup.internal.launch.MavenArtifactIdentifier;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+public class ImportBinaryProjectHandler extends AbstractHandler {
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ISelection selection = HandlerUtil.getCurrentSelectionChecked(event);
+
+ if (selection instanceof IStructuredSelection && !selection.isEmpty()) {
+ try {
+ importBinaryProjects(((IStructuredSelection) selection).getFirstElement());
+ } catch (DebugException e) {
+ throw new ExecutionException("Could not import binary project", e);
+ }
+ }
+
+ return null;
+ }
+
+ public static void importBinaryProjects(final Object debugElement) throws DebugException {
+
+ final File location = AdvancedSourceLookup.getClassesLocation(debugElement);
+
+ if (location == null) {
+ return;
+ }
+
+ Job job = new AbstractBinaryProjectsImportJob() {
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ IStatus status = super.run(monitor);
+
+ if (status.isOK()) {
+ AdvancedSourceLookupParticipant sourceLookup = AdvancedSourceLookupParticipant.getSourceLookup(debugElement);
+
+ try {
+ sourceLookup.getSourceContainer(debugElement, true, monitor);
+ } catch (CoreException e) {
+ status = e.getStatus();
+ }
+ }
+
+ return status;
+ }
+
+ @Override
+ protected Collection<ArtifactKey> getArtifactKeys(IProgressMonitor monitor) throws CoreException {
+ return new MavenArtifactIdentifier().identify(location, monitor);
+ }
+
+ };
+ job.setUser(true);
+ job.schedule();
+ }
+}
diff --git a/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/OpenPomCommandHandler.java b/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/OpenPomCommandHandler.java
new file mode 100644
index 00000000..e7e8d3d5
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/OpenPomCommandHandler.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2012 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.sourcelookup.ui.internal;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import org.codehaus.plexus.util.IOUtil;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedSourceLookup;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.m2e.core.ui.internal.actions.OpenPomAction;
+import org.eclipse.m2e.core.ui.internal.actions.OpenPomAction.MavenStorageEditorInput;
+import org.eclipse.m2e.sourcelookup.internal.launch.MetaInfMavenScanner;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+@SuppressWarnings("restriction")
+public class OpenPomCommandHandler extends AbstractHandler {
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ISelection selection = HandlerUtil.getCurrentSelectionChecked(event);
+
+ if (!(selection instanceof IStructuredSelection) || selection.isEmpty()) {
+ return null;
+ }
+
+ try {
+ final File location =
+ AdvancedSourceLookup.getClassesLocation(((IStructuredSelection) selection).getFirstElement());
+
+ if (location == null) {
+ return null;
+ }
+
+ final String name = location.getName();
+
+ List<IEditorInput> inputs = new MetaInfMavenScanner<IEditorInput>() {
+ @Override
+ protected IEditorInput visitFile(File file) throws IOException {
+ return toEditorInput(name, new FileInputStream(file));
+ }
+
+ @Override
+ protected IEditorInput visitJarEntry(JarFile jar, JarEntry entry) throws IOException {
+ return toEditorInput(name, jar.getInputStream(entry));
+ }
+
+ }.scan(location, "pom.xml");
+
+ if (inputs.isEmpty()) {
+ return null;
+ }
+
+ OpenPomAction.openEditor(inputs.get(0), "pom.xml");
+ } catch (CoreException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ static MavenStorageEditorInput toEditorInput(String name, InputStream is) throws IOException {
+ try {
+ return new MavenStorageEditorInput(name, name, null, IOUtil.toByteArray(is));
+ } finally {
+ IOUtil.close(is);
+ }
+ }
+}
diff --git a/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/OpenSourceLookupInfoDialogCommandHandler.java b/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/OpenSourceLookupInfoDialogCommandHandler.java
new file mode 100644
index 00000000..991ddd7a
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/OpenSourceLookupInfoDialogCommandHandler.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2013 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.sourcelookup.ui.internal;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedSourceLookupParticipant;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+public class OpenSourceLookupInfoDialogCommandHandler extends AbstractHandler {
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ ISelection selection = HandlerUtil.getCurrentSelectionChecked(event);
+
+ if (!(selection instanceof IStructuredSelection) || selection.isEmpty()) {
+ return null;
+ }
+
+ Object debugElement = ((IStructuredSelection) selection).getFirstElement();
+
+ final AdvancedSourceLookupParticipant sourceLookup = AdvancedSourceLookupParticipant.getSourceLookup(debugElement);
+
+ if (debugElement != null && sourceLookup != null) {
+ new SourceLookupInfoDialog(HandlerUtil.getActiveShell(event), debugElement, sourceLookup).open();
+ }
+
+ return null;
+ }
+
+}
diff --git a/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/SourceLookupInfoDialog.java b/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/SourceLookupInfoDialog.java
new file mode 100644
index 00000000..503786ae
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/SourceLookupInfoDialog.java
@@ -0,0 +1,225 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.sourcelookup.ui.internal;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.debug.core.sourcelookup.ISourceContainer;
+import org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedSourceLookup;
+import org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedSourceLookupParticipant;
+import org.eclipse.jdt.launching.sourcelookup.containers.PackageFragmentRootSourceContainer;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.sourcelookup.internal.launch.MavenArtifactIdentifier;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+public class SourceLookupInfoDialog extends Dialog {
+ private final Object debugElement;
+
+ private final AdvancedSourceLookupParticipant sourceLookup;
+
+ private Text textLocation;
+
+ private Text textGAV;
+
+ private Text textJavaProject;
+
+ private Text textSourceContainer;
+
+ // FIXME
+ private IProgressMonitor monitor = new NullProgressMonitor();
+
+ public SourceLookupInfoDialog(Shell parentShell, Object debugElement, AdvancedSourceLookupParticipant sourceLookup) {
+ super(parentShell);
+ setShellStyle(SWT.RESIZE | SWT.TITLE);
+ this.debugElement = debugElement;
+ this.sourceLookup = sourceLookup;
+ }
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ newShell.setText("Source lookup properties");
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite container = (Composite) super.createDialogArea(parent);
+ container.setLayout(new GridLayout(2, false));
+
+ Label lblCodeLocation = new Label(container, SWT.NONE);
+ lblCodeLocation.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ lblCodeLocation.setText("Code location:");
+
+ textLocation = new Text(container, SWT.BORDER | SWT.WRAP | SWT.MULTI);
+ textLocation.setEditable(false);
+ textLocation.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+
+ Label lblGav = new Label(container, SWT.NONE);
+ lblGav.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ lblGav.setText("GAV:");
+
+ textGAV = new Text(container, SWT.BORDER | SWT.WRAP);
+ textGAV.setEditable(false);
+ textGAV.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+
+ Label lblJavaProject = new Label(container, SWT.NONE);
+ lblJavaProject.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ lblJavaProject.setText("Java project:");
+
+ textJavaProject = new Text(container, SWT.BORDER | SWT.WRAP);
+ textJavaProject.setEditable(false);
+ textJavaProject.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+
+ Label lblSourceContainer = new Label(container, SWT.NONE);
+ lblSourceContainer.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ lblSourceContainer.setText("Source container:");
+
+ textSourceContainer = new Text(container, SWT.BORDER | SWT.WRAP);
+ textSourceContainer.setEditable(false);
+ textSourceContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+
+ Composite fillerComposite = new Composite(container, SWT.NONE);
+ fillerComposite.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, true, 2, 1));
+
+ Composite actionsComposite = new Composite(container, SWT.NONE);
+ actionsComposite.setLayout(new RowLayout(SWT.HORIZONTAL));
+ actionsComposite.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1));
+
+ Button btnCopy = new Button(actionsComposite, SWT.NONE);
+ btnCopy.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ copyToClipboard();
+ }
+ });
+ btnCopy.setToolTipText("Copy to clipboard");
+ btnCopy.setText("Copy");
+
+ Button btnRefresh = new Button(actionsComposite, SWT.NONE);
+ btnRefresh.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ try {
+ sourceLookup.getSourceContainer(debugElement, true, monitor);
+ } catch (CoreException e1) {
+ showError(e1);
+ }
+ }
+ });
+ btnRefresh.setToolTipText("Force rediscovery of source lookup information for this code location.");
+ btnRefresh.setText("Refresh");
+
+ updateDisplay(monitor);
+
+ return container;
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+
+ createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ }
+
+ @Override
+ protected Point getInitialSize() {
+ return new Point(450, 300);
+ }
+
+ private void updateDisplay(IProgressMonitor moninor) {
+ try {
+ File location = AdvancedSourceLookup.getClassesLocation(debugElement);
+
+ if (location == null) {
+ return;
+ }
+
+ textLocation.setText(location.getAbsolutePath());
+
+ ISourceContainer container = sourceLookup.getSourceContainer(debugElement, false, moninor /* sync */);
+
+ // TODO consider extracting artifact keys from container
+ final Collection<ArtifactKey> artifacts = new MavenArtifactIdentifier().identify(location, moninor);
+ textGAV.setText(artifacts.toString());
+
+ // TODO extract project(s) from the container
+ textJavaProject.setText("<not-implemented>");
+
+ textSourceContainer.setText(toString(container));
+ } catch (CoreException e) {
+ showError(e);
+ }
+ }
+
+ void showError(CoreException e) {
+ ErrorDialog.openError(getParentShell(), "Source lookup info", "Could not determine code maven coordinates",
+ e.getStatus());
+ }
+
+ private String toString(ISourceContainer container) {
+ if (container == null) {
+ return "";
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(container.getClass().getSimpleName()).append(" ").append(container.getName());
+
+ if (container instanceof PackageFragmentRootSourceContainer) {
+ sb.append(" ").append(
+ ((PackageFragmentRootSourceContainer) container).getPackageFragmentRoot().getJavaProject().getProject());
+ }
+
+ return sb.toString();
+ }
+
+ void copyToClipboard() {
+ List<Transfer> dataTypes = new ArrayList<Transfer>();
+ List<Object> data = new ArrayList<Object>();
+
+ Clipboard clipboard = new Clipboard(getShell().getDisplay());
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("Location: ").append(textLocation.getText()).append("\n");
+ sb.append("GAV: ").append(textGAV.getText()).append("\n");
+ sb.append("Java project: ").append(textJavaProject.getText()).append("\n");
+ sb.append("Source container: ").append(textSourceContainer.getText()).append("\n");
+
+ dataTypes.add(TextTransfer.getInstance());
+ data.add(sb.toString());
+
+ clipboard.setContents(data.toArray(), dataTypes.toArray(new Transfer[dataTypes.size()]));
+
+ clipboard.dispose();
+ }
+}
diff --git a/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/SourceLookupPreferencePage.java b/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/SourceLookupPreferencePage.java
new file mode 100644
index 00000000..69f6fbc7
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/SourceLookupPreferencePage.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.sourcelookup.ui.internal;
+
+import org.eclipse.jdt.internal.launching.sourcelookup.advanced.AdvancedSourceLookupSupport;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+
+public class SourceLookupPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+ private Text vmArguments;
+
+ private Text launchFileVMArguments;
+
+ private Text launchFileAttribute;
+
+ public SourceLookupPreferencePage() {
+ setMessage("Manual configuration of dynamic source lookup");
+ noDefaultAndApplyButton();
+ }
+
+ public void init(IWorkbench workbench) {}
+
+ @Override
+ protected Control createContents(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE) {
+ @Override
+ public Point computeSize(int wHint, int hHint, boolean changed) {
+ return new Point(0, 0);
+ }
+ };
+
+ GridLayout gl_composite = new GridLayout(1, false);
+ gl_composite.marginWidth = 0;
+ gl_composite.marginHeight = 0;
+ composite.setLayout(gl_composite);
+
+ Label lblVMArguments = new Label(composite, SWT.NONE);
+ lblVMArguments.setText("VM arguments:");
+
+ vmArguments = new Text(composite, SWT.BORDER | SWT.READ_ONLY | SWT.WRAP);
+ vmArguments.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
+ vmArguments.setText(AdvancedSourceLookupSupport.getJavaagentString());
+
+ Label lblLaunchVMArguments = new Label(composite, SWT.NONE);
+ lblLaunchVMArguments.setText(".launch file VM arguments:");
+
+ launchFileVMArguments = new Text(composite, SWT.BORDER | SWT.READ_ONLY | SWT.WRAP);
+ launchFileVMArguments.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
+ launchFileVMArguments.setText("-javaagent:${sourcelookup_agent_path}");
+
+ Label lblLaunchFileAttribute = new Label(composite, SWT.NONE);
+ lblLaunchFileAttribute.setText(".launch file attribute:");
+
+ launchFileAttribute = new Text(composite, SWT.BORDER | SWT.READ_ONLY | SWT.WRAP);
+ launchFileAttribute.setText(
+ "<stringAttribute key=\"org.eclipse.debug.core.source_locator_id\" value=\"org.eclipse.m2e.sourcelookupDirector\"/>\n");
+ launchFileAttribute.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+
+ return composite;
+ }
+}
diff --git a/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/SourceLookupUIActivator.java b/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/SourceLookupUIActivator.java
new file mode 100644
index 00000000..ef7a2241
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup.ui/src/org/eclipse/m2e/sourcelookup/ui/internal/SourceLookupUIActivator.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2012 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.sourcelookup.ui.internal;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+public class SourceLookupUIActivator extends AbstractUIPlugin {
+
+ public static final String PLUGIN_ID = "org.eclipse.m2e.sourcelookup.ui"; //$NON-NLS-1$
+
+ private static SourceLookupUIActivator plugin;
+
+ public SourceLookupUIActivator() {}
+
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ public static SourceLookupUIActivator getDefault() {
+ return plugin;
+ }
+
+}
diff --git a/org.eclipse.m2e.sourcelookup/META-INF/MANIFEST.MF b/org.eclipse.m2e.sourcelookup/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..dd4a8fcc
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup/META-INF/MANIFEST.MF
@@ -0,0 +1,25 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name
+Bundle-SymbolicName: org.eclipse.m2e.sourcelookup;singleton:=true
+Bundle-Version: 1.9.0.qualifier
+Bundle-Vendor: %Bundle-Vendor
+Require-Bundle: org.eclipse.m2e.launching;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.m2e.core;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.m2e.maven.runtime;bundle-version="[1.9.0,1.10.0)",
+ org.eclipse.jdt.core;bundle-version="3.7.0",
+ org.eclipse.jdt.debug;bundle-version="3.8.0",
+ org.eclipse.jdt.launching;bundle-version="3.9.0",
+ org.slf4j.api;bundle-version="1.6.1",
+ org.eclipse.debug.core;bundle-version="3.7.0",
+ org.eclipse.core.runtime;bundle-version="3.7.0",
+ org.eclipse.core.expressions;bundle-version="3.4.400",
+ org.eclipse.debug.ui;bundle-version="3.10.0",
+ org.eclipse.core.resources,
+ com.google.guava;bundle-version="15.0.0",
+ com.google.gson;bundle-version="2.2.4",
+ org.eclipse.core.variables;bundle-version="3.2.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ActivationPolicy: lazy
+Eclipse-BundleShape: dir
+Export-Package: org.eclipse.m2e.sourcelookup.internal.launch;x-friends:="org.eclipse.m2e.sourcelookup.ui,org.eclipse.m2e.binaryproject"
diff --git a/org.eclipse.m2e.sourcelookup/build.properties b/org.eclipse.m2e.sourcelookup/build.properties
new file mode 100644
index 00000000..52a5b4fe
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = target/classes
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml
diff --git a/org.eclipse.m2e.sourcelookup/plugin.xml b/org.eclipse.m2e.sourcelookup/plugin.xml
new file mode 100644
index 00000000..13aa85b6
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup/plugin.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ point="org.eclipse.jdt.launching.sourceContainerResolvers">
+ <resolver
+ class="org.eclipse.m2e.sourcelookup.internal.launch.MavenSourceContainerResolver">
+ </resolver>
+ </extension>
+
+</plugin>
diff --git a/org.eclipse.m2e.sourcelookup/pom.xml b/org.eclipse.m2e.sourcelookup/pom.xml
new file mode 100644
index 00000000..806f4b84
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup/pom.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2011 Igor Fedorenko
+ 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
+-->
+<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.9.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.eclipse.m2e.sourcelookup</artifactId>
+ <packaging>eclipse-plugin</packaging>
+</project> \ No newline at end of file
diff --git a/org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MavenArtifactIdentifier.java b/org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MavenArtifactIdentifier.java
new file mode 100644
index 00000000..af625b72
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MavenArtifactIdentifier.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.sourcelookup.internal.launch;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.internal.index.IIndex;
+import org.eclipse.m2e.core.internal.index.IndexedArtifactFile;
+import org.eclipse.m2e.core.internal.index.nexus.CompositeIndex;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.hash.Hashing;
+import com.google.common.io.Files;
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+
+@SuppressWarnings("restriction")
+public class MavenArtifactIdentifier {
+
+ // reads META-INF/maven/**/pom.properties
+ private static final MetaInfMavenScanner<Properties> scanner = new MetaInfMavenScanner<Properties>() {
+ @Override
+ protected Properties visitFile(File file) throws IOException {
+ // TODO validate properties and path match
+ try (InputStream is = new BufferedInputStream(new FileInputStream(file))) {
+ return loadProperties(is);
+ }
+ }
+
+ @Override
+ protected Properties visitJarEntry(JarFile jar, JarEntry entry) throws IOException {
+ // TODO validate properties and path match
+ try (InputStream is = jar.getInputStream(entry)) {
+ return loadProperties(is);
+ }
+ }
+
+ private Properties loadProperties(InputStream is) throws IOException {
+ Properties properties = new Properties();
+ properties.load(is);
+ return properties;
+ }
+ };
+
+ public Collection<ArtifactKey> identify(File classesLocation, IProgressMonitor monitor) {
+ // checksum-based lookup in nexus index
+ // checksum-based lookup in central
+ // GAV extracted from pom.properties
+
+ Collection<ArtifactKey> classesArtifacts = identifyNexusIndexer(classesLocation);
+ if (classesArtifacts == null) {
+ classesArtifacts = identifyCentralSearch(classesLocation);
+ }
+ if (classesArtifacts == null) {
+ classesArtifacts = scanPomProperties(classesLocation);
+ }
+
+ return classesArtifacts;
+ }
+
+ protected Collection<ArtifactKey> identifyNexusIndexer(File file) {
+ if (!file.isFile()) {
+ return null;
+ }
+
+ try {
+ IIndex index = MavenPlugin.getIndexManager().getAllIndexes();
+
+ List<IndexedArtifactFile> identified;
+ if (index instanceof CompositeIndex) {
+ identified = ((CompositeIndex) index).identifyAll(file);
+ } else {
+ IndexedArtifactFile indexed = index.identify(file);
+ if (indexed != null) {
+ identified = Collections.singletonList(indexed);
+ } else {
+ identified = Collections.emptyList();
+ }
+ }
+
+ for (IndexedArtifactFile indexed : identified) {
+ if (indexed.sourcesExists == IIndex.PRESENT) {
+ return Collections.singleton(indexed.getArtifactKey());
+ }
+ }
+ } catch (CoreException e) {
+ // TODO maybe log, but ignore otherwise
+ }
+
+ return null;
+ }
+
+ protected Collection<ArtifactKey> identifyCentralSearch(File file) {
+ if (!file.isFile()) {
+ return null;
+ }
+
+ try {
+ String sha1 = Files.hash(file, Hashing.sha1()).toString(); // TODO use Locations for caching
+ URL url = new URL("https://search.maven.org/solrsearch/select?q=1:" + sha1);
+ try (InputStreamReader reader = new InputStreamReader(url.openStream(), Charsets.UTF_8)) {
+ Set<ArtifactKey> result = new LinkedHashSet<>();
+ JsonObject container = new Gson().fromJson(reader, JsonObject.class);
+ JsonArray docs = container.get("response").getAsJsonObject().get("docs").getAsJsonArray();
+ for (int i = 0; i < docs.size(); i++) {
+ JsonObject doc = docs.get(i).getAsJsonObject();
+ String g = doc.get("g").getAsString();
+ String a = doc.get("a").getAsString();
+ String v = doc.get("v").getAsString();
+ result.add(new ArtifactKey(g, a, v, null));
+ }
+ return !result.isEmpty() ? ImmutableSet.copyOf(result) : null;
+ }
+ } catch (IOException e) {
+ // TODO maybe log, ignore otherwise
+ }
+ return null;
+ }
+
+ public Collection<ArtifactKey> scanPomProperties(File classesLocation) {
+ Set<ArtifactKey> artifacts = new LinkedHashSet<>();
+ for (Properties pomProperties : scanner.scan(classesLocation, "pom.properties")) {
+ String groupId = pomProperties.getProperty("groupId");
+ String artifactId = pomProperties.getProperty("artifactId");
+ String version = pomProperties.getProperty("version");
+ if (groupId != null && artifactId != null && version != null) {
+ artifacts.add(new ArtifactKey(groupId, artifactId, version, /* classifier= */null));
+ }
+ }
+ return ImmutableSet.copyOf(artifacts);
+ }
+}
diff --git a/org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MavenSourceContainerResolver.java b/org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MavenSourceContainerResolver.java
new file mode 100644
index 00000000..6b4a6b26
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MavenSourceContainerResolver.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.sourcelookup.internal.launch;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.sourcelookup.ISourceContainer;
+import org.eclipse.debug.core.sourcelookup.containers.ExternalArchiveSourceContainer;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.launching.sourcelookup.advanced.ISourceContainerResolver;
+import org.eclipse.jdt.launching.sourcelookup.containers.JavaProjectSourceContainer;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.embedder.IMaven;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.IMavenProjectRegistry;
+
+
+public class MavenSourceContainerResolver implements ISourceContainerResolver {
+
+ private static final MavenArtifactIdentifier INDENTIFIER = new MavenArtifactIdentifier();
+
+ @Override
+ public Collection<ISourceContainer> resolveSourceContainers(File classesLocation, IProgressMonitor monitor) {
+ Collection<ArtifactKey> classesArtifacts = INDENTIFIER.identify(classesLocation, monitor);
+
+ if (classesArtifacts == null) {
+ return null;
+ }
+
+ List<ISourceContainer> result = new ArrayList<>();
+ for (ArtifactKey classesArtifact : classesArtifacts) {
+ ISourceContainer container = resolveSourceContainer(classesArtifact, monitor);
+ if (container != null) {
+ result.add(container);
+ }
+ }
+ return result;
+ }
+
+ protected ISourceContainer resolveSourceContainer(ArtifactKey artifact, IProgressMonitor monitor) {
+ String groupId = artifact.getGroupId();
+ String artifactId = artifact.getArtifactId();
+ String version = artifact.getVersion();
+
+ IMaven maven = MavenPlugin.getMaven();
+ IMavenProjectRegistry projectRegistry = MavenPlugin.getMavenProjectRegistry();
+
+ IMavenProjectFacade mavenProject = projectRegistry.getMavenProject(groupId, artifactId, version);
+ if (mavenProject != null) {
+ return new JavaProjectSourceContainer(JavaCore.create(mavenProject.getProject()));
+ }
+
+ try {
+ List<ArtifactRepository> repositories = new ArrayList<ArtifactRepository>();
+ repositories.addAll(maven.getArtifactRepositories());
+ repositories.addAll(maven.getPluginArtifactRepositories());
+
+ if (!maven.isUnavailable(groupId, artifactId, version, "jar", "sources", repositories)) {
+ Artifact resolve = maven.resolve(groupId, artifactId, version, "jar", "sources", null, monitor);
+
+ return new ExternalArchiveSourceContainer(resolve.getFile().getAbsolutePath(), true);
+ }
+ } catch (CoreException e) {
+ // TODO maybe log, ignore otherwise
+ }
+
+ return null;
+ }
+}
diff --git a/org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MavenSourceLookupParticipant.java b/org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MavenSourceLookupParticipant.java
new file mode 100644
index 00000000..16954c74
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MavenSourceLookupParticipant.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2016 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.sourcelookup.internal.launch;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
+import org.eclipse.jdt.launching.sourcelookup.advanced.AdvancedSourceLookupParticipant;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.project.IMavenProjectChangedListener;
+import org.eclipse.m2e.core.project.MavenProjectChangedEvent;
+
+
+public class MavenSourceLookupParticipant extends AdvancedSourceLookupParticipant
+ implements
+ IMavenProjectChangedListener {
+
+ @Override
+ public void init(ISourceLookupDirector director) {
+ super.init(director);
+ MavenPlugin.getMavenProjectRegistry().addMavenProjectChangedListener(this);
+ }
+
+ @Override
+ public void dispose() {
+ MavenPlugin.getMavenProjectRegistry().removeMavenProjectChangedListener(this);
+ super.dispose();
+ }
+
+ @Override
+ public void mavenProjectChanged(MavenProjectChangedEvent[] events, IProgressMonitor monitor) {
+ disposeContainers();
+ }
+}
diff --git a/org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MetaInfMavenScanner.java b/org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MetaInfMavenScanner.java
new file mode 100644
index 00000000..77ddb23b
--- /dev/null
+++ b/org.eclipse.m2e.sourcelookup/src/org/eclipse/m2e/sourcelookup/internal/launch/MetaInfMavenScanner.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2012 Igor Fedorenko
+ * 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
+ *
+ * Contributors:
+ * Igor Fedorenko - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.sourcelookup.internal.launch;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * Helper to find and extract information from META-INF/maven pom.properties files.
+ */
+public abstract class MetaInfMavenScanner<T> {
+
+ private static final String META_INF_MAVEN = "META-INF/maven";
+
+ public List<T> scan(File file, String filename) {
+ List<T> result = new ArrayList<T>();
+ if (file != null) {
+ if (file.isDirectory()) {
+ scanFilesystem(new File(file, META_INF_MAVEN), filename, result);
+ } else if (file.isFile()) {
+ try {
+ try (JarFile jar = new JarFile(file)) {
+ scanJar(jar, filename, result);
+ }
+ } catch (IOException e) {
+ // fall through
+ }
+ }
+ }
+ return result;
+ }
+
+ private void scanJar(JarFile jar, String filename, List<T> result) throws IOException {
+ Enumeration<JarEntry> entries = jar.entries();
+ while (entries.hasMoreElements()) {
+ JarEntry entry = entries.nextElement();
+ if (!entry.isDirectory()) {
+ String name = entry.getName();
+ if (name.startsWith(META_INF_MAVEN) && name.endsWith(filename)) {
+ try {
+ T t = visitJarEntry(jar, entry);
+ if (t != null) {
+ result.add(t);
+ }
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+ }
+ }
+
+ private void scanFilesystem(File dir, String filename, List<T> result) {
+ File[] files = dir.listFiles();
+ if (files == null) {
+ return;
+ }
+ for (File file : files) {
+ if (file.isDirectory()) {
+ scanFilesystem(file, filename, result);
+ } else if (file.isFile() && filename.equals(file.getName())) {
+ try {
+ T t = visitFile(file);
+ if (t != null) {
+ result.add(t);
+ }
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+ }
+
+ protected abstract T visitFile(File file) throws IOException;
+
+ protected abstract T visitJarEntry(JarFile jar, JarEntry entry) throws IOException;
+}
diff --git a/pom.xml b/pom.xml
index 231c7fe0..107fbe74 100644
--- a/pom.xml
+++ b/pom.xml
@@ -43,6 +43,9 @@
<eclipse.stream>photon</eclipse.stream>
<eclipse-repo.url>http://download.eclipse.org/eclipse/updates/4.8-I-builds/</eclipse-repo.url>
<eclipse-simrel.url>http://download.eclipse.org/releases/${eclipse.stream}</eclipse-simrel.url>
+
+ <tycho.test.jvmArgs>-Xmx800m</tycho.test.jvmArgs>
+ <tycho.surefire.timeout>7200</tycho.surefire.timeout>
</properties>
<organization>
@@ -106,21 +109,27 @@
<module>org.eclipse.m2e.profiles.core</module>
<module>org.eclipse.m2e.profiles.ui</module>
<module>org.eclipse.m2e.importer</module>
+ <module>org.eclipse.m2e.binaryproject</module>
+ <module>org.eclipse.m2e.binaryproject.ui</module>
+ <module>org.eclipse.m2e.sourcelookup</module>
+ <module>org.eclipse.m2e.sourcelookup.ui</module>
<!-- common test helpers -->
<module>org.eclipse.m2e.tests.common</module>
- <module>org.eclipse.m2e.importer.tests</module>
<!-- Logging -->
<module>org.eclipse.m2e.logback.appender</module>
<module>org.eclipse.m2e.logback.configuration</module>
- <!-- features -->
+ <!-- features and update site -->
<module>org.eclipse.m2e.feature</module>
<module>org.eclipse.m2e.sdk.feature</module>
<module>org.eclipse.m2e.logback.feature</module>
-
<module>org.eclipse.m2e.site</module>
+
+ <!-- testing -->
+ <module>org.eclipse.m2e.importer.tests</module>
+ <module>org.eclipse.m2e.binaryproject.tests</module>
</modules>
@@ -204,7 +213,7 @@
<include>**/*Test.java</include>
</includes>
<argLine>${tycho.test.jvmArgs}</argLine>
- <forkedProcessTimeoutInSeconds>7200</forkedProcessTimeoutInSeconds>
+ <forkedProcessTimeoutInSeconds>${tycho.surefire.timeout}</forkedProcessTimeoutInSeconds>
</configuration>
</plugin>
<plugin>
@@ -317,6 +326,43 @@
<module>m2e-maven-runtime</module>
</modules>
</profile>
+
+ <profile>
+ <id>osx</id>
+ <activation>
+ <os>
+ <family>mac</family>
+ </os>
+ </activation>
+ <properties>
+ <tycho.test.jvmArgs>-Xmx800m -Dosgi.ws=cocoa -XstartOnFirstThread</tycho.test.jvmArgs>
+ </properties>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.tycho</groupId>
+ <artifactId>tycho-surefire-plugin</artifactId>
+ <version>${tycho-version}</version>
+ <configuration>
+ <dependencies combine.children="append">
+ <dependency>
+ <artifactId>org.eclipse.jdt.launching.macosx</artifactId>
+ <version>0.0.0</version>
+ <type>eclipse-plugin</type>
+ </dependency>
+ <dependency>
+ <type>eclipse-feature</type>
+ <artifactId>org.eclipse.e4.rcp</artifactId>
+ <version>0.0.0</version>
+ </dependency>
+ </dependencies>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
</profiles>
<developers>

Back to the top