Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPascal Rapicault2010-12-08 11:46:25 -0500
committerPascal Rapicault2010-12-08 11:46:25 -0500
commite9f99daf187dd67ffbce5570a5590db73b656d65 (patch)
treee10a29ec6b9ab8c15919187c190f750810b0d222
parent7c94c0ac086502cf6c254b087865017e6fc0db47 (diff)
downloadm2e-core-e9f99daf187dd67ffbce5570a5590db73b656d65.tar.gz
m2e-core-e9f99daf187dd67ffbce5570a5590db73b656d65.tar.xz
m2e-core-e9f99daf187dd67ffbce5570a5590db73b656d65.zip
Move test infrastructure bundles
-rw-r--r--org.eclipse.m2e.integration.tests.common/.classpath7
-rw-r--r--org.eclipse.m2e.integration.tests.common/.gitignore2
-rw-r--r--org.eclipse.m2e.integration.tests.common/.project34
-rw-r--r--org.eclipse.m2e.integration.tests.common/META-INF/MANIFEST.MF35
-rw-r--r--org.eclipse.m2e.integration.tests.common/OSGI-INF/l10n/bundle.properties3
-rw-r--r--org.eclipse.m2e.integration.tests.common/about.html28
-rw-r--r--org.eclipse.m2e.integration.tests.common/build.properties18
-rw-r--r--org.eclipse.m2e.integration.tests.common/pom.xml28
-rw-r--r--org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/ContextMenuHelper.java150
-rw-r--r--org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/HyperlinkBot.java52
-rw-r--r--org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SWTBotMenuEx.java47
-rw-r--r--org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SectionBot.java84
-rw-r--r--org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SonatypeSWTBot.java131
-rw-r--r--org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SonatypeSWTBotTree.java108
-rw-r--r--org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SwtbotUtil.java78
-rw-r--r--org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/UIIntegrationTestCase.java1480
-rw-r--r--org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/UIThreadTask.java55
-rw-r--r--org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/matchers/ContainsMnemonic.java57
-rw-r--r--org.eclipse.m2e.parent/pom.xml4
-rw-r--r--org.eclipse.m2e.tests.common/.gitignore3
-rw-r--r--org.eclipse.m2e.tests.common/.project34
-rw-r--r--org.eclipse.m2e.tests.common/.settings/org.eclipse.jdt.core.prefs359
-rw-r--r--org.eclipse.m2e.tests.common/.settings/org.eclipse.jdt.ui.prefs14
-rw-r--r--org.eclipse.m2e.tests.common/.settings/org.maven.ide.eclipse.prefs9
-rw-r--r--org.eclipse.m2e.tests.common/META-INF/MANIFEST.MF25
-rw-r--r--org.eclipse.m2e.tests.common/OSGI-INF/l10n/bundle.properties3
-rw-r--r--org.eclipse.m2e.tests.common/about.html28
-rw-r--r--org.eclipse.m2e.tests.common/build.properties18
-rw-r--r--org.eclipse.m2e.tests.common/jars/jetty-6.1.22.jarbin0 -> 536866 bytes
-rw-r--r--org.eclipse.m2e.tests.common/jars/jetty-util-6.1.22.jarbin0 -> 176973 bytes
-rw-r--r--org.eclipse.m2e.tests.common/jars/servlet-api-2.5-20081211.jarbin0 -> 134133 bytes
-rw-r--r--org.eclipse.m2e.tests.common/pom.xml36
-rw-r--r--org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/AbstractLifecycleMappingTest.java49
-rw-r--r--org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/AbstractMavenProjectTestCase.java442
-rw-r--r--org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/FileHelpers.java115
-rw-r--r--org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/FilexWagon.java81
-rw-r--r--org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/HttpServer.java747
-rw-r--r--org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/JobHelpers.java211
-rw-r--r--org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/MavenHelpers.java37
-rw-r--r--org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/WorkspaceHelpers.java203
40 files changed, 4813 insertions, 2 deletions
diff --git a/org.eclipse.m2e.integration.tests.common/.classpath b/org.eclipse.m2e.integration.tests.common/.classpath
new file mode 100644
index 00000000..798048dd
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src/"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.m2e.integration.tests.common/.gitignore b/org.eclipse.m2e.integration.tests.common/.gitignore
new file mode 100644
index 00000000..d90e434e
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/.gitignore
@@ -0,0 +1,2 @@
+/.settings
+/target
diff --git a/org.eclipse.m2e.integration.tests.common/.project b/org.eclipse.m2e.integration.tests.common/.project
new file mode 100644
index 00000000..ab32da86
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.m2e.integration.tests.common</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.maven.ide.eclipse.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.maven.ide.eclipse.maven2Nature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.m2e.integration.tests.common/META-INF/MANIFEST.MF b/org.eclipse.m2e.integration.tests.common/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..b997f8e5
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/META-INF/MANIFEST.MF
@@ -0,0 +1,35 @@
+Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6
+Bundle-Name: %Bundle-Name
+Manifest-Version: 1.0
+Bundle-Vendor: %Bundle-Vendor
+Bundle-ClassPath: .
+Bundle-SymbolicName: org.eclipse.m2e.integration.tests.common;singleton:=true
+Bundle-ManifestVersion: 2
+Eclipse-LazyStart: true
+MavenArtifact-GroupId: org.eclipse.m2e
+Bundle-Version: 0.13.0.qualifier
+MavenArtifact-ArtifactId: org.eclipse.m2e.integration.test.common
+Export-Package: org.eclipse.m2e.integration.tests.common,
+ org.eclipse.m2e.integration.tests.common.matchers
+Require-Bundle: org.junit4;bundle-version="4.4.0",
+ org.hamcrest,
+ org.hamcrest.library,
+ org.eclipse.swtbot.eclipse.finder,
+ org.eclipse.swtbot.swt.finder,
+ org.eclipse.swtbot.junit4_x,
+ org.apache.log4j,
+ org.eclipse.ui,
+ org.eclipse.ui.ide,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ org.eclipse.swt,
+ org.eclipse.ui.forms,
+ org.eclipse.search,
+ org.eclipse.ui.editors,
+ org.eclipse.m2e.editor,
+ org.eclipse.m2e.editor.xml,
+ org.eclipse.m2e.model.edit,
+ org.eclipse.m2e.core,
+ org.eclipse.m2e.maven.runtime,
+ org.eclipse.m2e.tests.common
+
diff --git a/org.eclipse.m2e.integration.tests.common/OSGI-INF/l10n/bundle.properties b/org.eclipse.m2e.integration.tests.common/OSGI-INF/l10n/bundle.properties
new file mode 100644
index 00000000..ce31d365
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/OSGI-INF/l10n/bundle.properties
@@ -0,0 +1,3 @@
+#Properties file for org.eclipse.m2e.integration.tests.common
+Bundle-Vendor = Eclipse m2e
+Bundle-Name = Maven Integration Tests Plug-in \ No newline at end of file
diff --git a/org.eclipse.m2e.integration.tests.common/about.html b/org.eclipse.m2e.integration.tests.common/about.html
new file mode 100644
index 00000000..70e4b67c
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>October 29, 2010</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
diff --git a/org.eclipse.m2e.integration.tests.common/build.properties b/org.eclipse.m2e.integration.tests.common/build.properties
new file mode 100644
index 00000000..31788075
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/build.properties
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2008-2010 Sonatype, Inc.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Sonatype, Inc. - initial API and implementation
+#
+
+source.. = src/
+output.. = target/classes/
+bin.includes = META-INF/,\
+ .,\
+ about.html,\
+ OSGI-INF/l10n/bundle.properties
+
diff --git a/org.eclipse.m2e.integration.tests.common/pom.xml b/org.eclipse.m2e.integration.tests.common/pom.xml
new file mode 100644
index 00000000..e9379013
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/pom.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2009 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
+-->
+<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>org.eclipse.m2e.parent</artifactId>
+ <version>0.13.0-SNAPSHOT</version>
+ <relativePath>../org.eclipse.m2e.parent</relativePath>
+ </parent>
+
+ <artifactId>org.eclipse.m2e.integration.tests.common</artifactId>
+ <packaging>eclipse-plugin</packaging>
+
+ <name>Maven Integration for Eclipse System Tests Common</name>
+
+ <build>
+ <sourceDirectory>src</sourceDirectory>
+ </build>
+
+</project>
diff --git a/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/ContextMenuHelper.java b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/ContextMenuHelper.java
new file mode 100644
index 00000000..3dd36b21
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/ContextMenuHelper.java
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.integration.tests.common;
+
+import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withMnemonic;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.instanceOf;
+
+import java.util.Arrays;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
+import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
+import org.eclipse.swtbot.swt.finder.results.VoidResult;
+import org.eclipse.swtbot.swt.finder.results.WidgetResult;
+import org.eclipse.swtbot.swt.finder.widgets.AbstractSWTBot;
+import org.hamcrest.Matcher;
+
+public class ContextMenuHelper {
+
+ public static void clickContextMenu(
+ final AbstractSWTBot<? extends Control> bot,
+ final Matcher<? extends org.eclipse.swt.widgets.Widget>...matchers) {
+ // show
+ final MenuItem menuItem = UIThreadRunnable
+ .syncExec(new WidgetResult<MenuItem>() {
+ @SuppressWarnings("unchecked")
+ public MenuItem run() {
+ MenuItem menuItem = null;
+ Control control = bot.widget;
+ Menu menu = control.getMenu();
+ for (Matcher<? extends org.eclipse.swt.widgets.Widget> m : matchers) {
+ Matcher<?> matcher = allOf(
+ instanceOf(MenuItem.class), m);
+ menuItem = show(menu, matcher);
+ if (menuItem != null) {
+ menu = menuItem.getMenu();
+ } else {
+ hide(menu);
+
+ throw new WidgetNotFoundException(
+ "ContextMenuHelper was looking for: '"
+ + m + "' but only found: '"
+ + availableItems(menu) + "'");
+
+ }
+ }
+
+ return menuItem;
+ }
+
+ });
+ if (menuItem == null) {
+ throw new WidgetNotFoundException("Could not find menu: "
+ + Arrays.asList(matchers));
+ }
+
+ // click
+ click(menuItem);
+
+ // hide
+ UIThreadRunnable.syncExec(new VoidResult() {
+ public void run() {
+ hide(menuItem.getParent());
+ }
+ });
+
+ }
+
+ /**
+ * Clicks the context menu matching the text.
+ *
+ * @param text
+ * the text on the context menu.
+ * @throws WidgetNotFoundException
+ * if the widget is not found.
+ */
+ public static void clickContextMenu(
+ final AbstractSWTBot<? extends Control> bot, final String... texts) {
+ Matcher<? extends Widget>[] matchers = new Matcher[texts.length];
+ for (int i = 0; i < texts.length; i++) {
+ matchers[i] = withMnemonic(texts[i]);
+ }
+ clickContextMenu(bot, matchers);
+ }
+
+ static MenuItem show(final Menu menu, final Matcher<?> matcher) {
+ if (menu != null) {
+ menu.notifyListeners(SWT.Show, new Event());
+ MenuItem[] items = menu.getItems();
+ for (final MenuItem menuItem : items) {
+ if (matcher.matches(menuItem)) {
+ return menuItem;
+ }
+ }
+ menu.notifyListeners(SWT.Hide, new Event());
+ }
+ return null;
+ }
+
+ static String availableItems(Menu menu) {
+ StringBuilder sb = new StringBuilder();
+
+ if (menu != null) {
+ MenuItem[] items = menu.getItems();
+ for (final MenuItem menuItem : items) {
+ sb.append(menuItem.getText().replace("&", ""));
+
+ sb.append(", ");
+ }
+ }
+ return sb.toString();
+
+ }
+
+ private static void click(final MenuItem menuItem) {
+ final Event event = new Event();
+ event.time = (int) System.currentTimeMillis();
+ event.widget = menuItem;
+ event.display = menuItem.getDisplay();
+ event.type = SWT.Selection;
+
+ UIThreadRunnable.asyncExec(menuItem.getDisplay(), new VoidResult() {
+ public void run() {
+ menuItem.notifyListeners(SWT.Selection, event);
+ }
+ });
+ }
+
+ static void hide(final Menu menu) {
+ menu.notifyListeners(SWT.Hide, new Event());
+ if (menu.getParentMenu() != null) {
+ hide(menu.getParentMenu());
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/HyperlinkBot.java b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/HyperlinkBot.java
new file mode 100644
index 00000000..4e5e95d7
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/HyperlinkBot.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.integration.tests.common;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swtbot.swt.finder.ReferenceBy;
+import org.eclipse.swtbot.swt.finder.SWTBotWidget;
+import org.eclipse.swtbot.swt.finder.Style;
+import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
+import org.eclipse.swtbot.swt.finder.utils.MessageFormat;
+import org.eclipse.swtbot.swt.finder.utils.SWTUtils;
+import org.eclipse.swtbot.swt.finder.widgets.AbstractSWTBotControl;
+import org.eclipse.ui.forms.widgets.Hyperlink;
+import org.hamcrest.SelfDescribing;
+
+@SWTBotWidget( clasz = Hyperlink.class, style = @Style( name = "SWT.NONE", value = SWT.NONE ), preferredName = "hyperlink", referenceBy = { ReferenceBy.LABEL, ReferenceBy.MNEMONIC } )//$NON-NLS-1$
+public class HyperlinkBot
+ extends AbstractSWTBotControl<Hyperlink>
+{
+
+ public HyperlinkBot( Hyperlink h )
+ throws WidgetNotFoundException
+ {
+ this( h, null );
+ }
+
+ public HyperlinkBot( Hyperlink h, SelfDescribing selfDescribing )
+ {
+ super( h, selfDescribing );
+ }
+
+ public HyperlinkBot click()
+ {
+ log.debug( MessageFormat.format( "Clicking on {0}", SWTUtils.getText( widget ) ) ); //$NON-NLS-1$
+ waitForEnabled();
+ Event e = createEvent();
+ e.character = SWT.CR;
+ notify( SWT.KeyDown, e );
+ log.debug( MessageFormat.format( "Clicked on {0}", SWTUtils.getText( widget ) ) ); //$NON-NLS-1$
+ return this;
+ }
+}
diff --git a/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SWTBotMenuEx.java b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SWTBotMenuEx.java
new file mode 100644
index 00000000..469f1eea
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SWTBotMenuEx.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.integration.tests.common;
+
+import java.util.List;
+
+import org.eclipse.m2e.integration.tests.common.matchers.ContainsMnemonic;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
+import org.eclipse.swtbot.swt.finder.finders.MenuFinder;
+import org.eclipse.swtbot.swt.finder.results.WidgetResult;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
+import org.hamcrest.Matcher;
+
+
+public class SWTBotMenuEx extends SWTBotMenu {
+
+ public SWTBotMenuEx(SWTBotMenu bot) {
+ super(bot.widget);
+ }
+
+ public SWTBotMenu menuContains(final String menuName) throws WidgetNotFoundException {
+ final Matcher<MenuItem> matcher = ContainsMnemonic.containsMnemonic(menuName);
+ MenuItem menuItem = syncExec(new WidgetResult<MenuItem>() {
+ public MenuItem run() {
+ Menu bar = widget.getMenu();
+ List<MenuItem> menus = new MenuFinder().findMenus(bar, matcher, true);
+ if(!menus.isEmpty()) {
+ return menus.get(0);
+ }
+ return null;
+ }
+ });
+ return new SWTBotMenu(menuItem, matcher);
+ }
+
+}
diff --git a/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SectionBot.java b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SectionBot.java
new file mode 100644
index 00000000..c0fafa97
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SectionBot.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.integration.tests.common;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swtbot.swt.finder.ReferenceBy;
+import org.eclipse.swtbot.swt.finder.SWTBotWidget;
+import org.eclipse.swtbot.swt.finder.Style;
+import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
+import org.eclipse.swtbot.swt.finder.results.BoolResult;
+import org.eclipse.swtbot.swt.finder.results.VoidResult;
+import org.eclipse.swtbot.swt.finder.utils.MessageFormat;
+import org.eclipse.swtbot.swt.finder.widgets.AbstractSWTBotControl;
+import org.eclipse.ui.forms.widgets.Section;
+import org.hamcrest.SelfDescribing;
+
+@SWTBotWidget(clasz = Section.class, style = @Style(name = "SWT.NONE", value = SWT.NONE), preferredName = "section", referenceBy = { ReferenceBy.LABEL, ReferenceBy.MNEMONIC })//$NON-NLS-1$
+public class SectionBot extends AbstractSWTBotControl<Section> {
+
+ public SectionBot(Section s) throws WidgetNotFoundException {
+ this(s, null);
+ }
+
+ public SectionBot(Section s, SelfDescribing selfDescribing) {
+ super(s, selfDescribing);
+ }
+
+ public boolean isExpanded() {
+ return syncExec(new BoolResult() {
+ public Boolean run() {
+ return widget.isExpanded();
+ }
+ });
+ }
+
+ public void setExpanded(final boolean expand) {
+ waitForEnabled();
+ asyncExec(new VoidResult() {
+ public void run() {
+ log
+ .debug(MessageFormat
+ .format(
+ "Expanding section {0}. Setting state to {1}", widget, (expand ? "expanded" //$NON-NLS-1$ //$NON-NLS-2$
+ : "collapsed"))); //$NON-NLS-1$
+ widget.setExpanded(expand);
+ }
+ });
+ }
+
+ public void expand() {
+ waitForEnabled();
+ asyncExec(new VoidResult() {
+ public void run() {
+ if (!widget.isExpanded()) {
+ log.debug(MessageFormat.format("Expanding section {0}.",
+ widget));
+ widget.setExpanded(true);
+ }
+ }
+ });
+ }
+
+ public void collapse() {
+ waitForEnabled();
+ asyncExec(new VoidResult() {
+ public void run() {
+ if (widget.isExpanded()) {
+ log.debug(MessageFormat.format("Collapsing section {0}.",
+ widget));
+ widget.setExpanded(false);
+ }
+ }
+ });
+ }
+}
diff --git a/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SonatypeSWTBot.java b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SonatypeSWTBot.java
new file mode 100644
index 00000000..7c08eea6
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SonatypeSWTBot.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.integration.tests.common;
+
+import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.allOf;
+import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.widgetOfType;
+import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withId;
+import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withLabel;
+import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withStyle;
+import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withText;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CCombo;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotCCombo;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotCheckBox;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotText;
+import org.eclipse.ui.forms.widgets.Hyperlink;
+import org.eclipse.ui.forms.widgets.Section;
+import org.hamcrest.Matcher;
+
+public class SonatypeSWTBot
+ extends SWTWorkbenchBot
+{
+
+ public SWTBotText textWithName( String value )
+ {
+ return textWithName( value, 0 );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ public SWTBotText textWithName( String value, int index )
+ {
+ Matcher matcher = allOf( widgetOfType( Text.class ), withId( "name", value ) );
+ return new SWTBotText( (Text) widget( matcher, index ), matcher );
+ }
+
+ public SWTBotCheckBox checkBoxWithName( String name )
+ {
+ return checkBoxWithName( name, 0 );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ public SWTBotCCombo ccomboBoxWithName( String value, int index )
+ {
+ Matcher matcher = allOf( widgetOfType( CCombo.class ), withId( "name", value ) );
+ return new SWTBotCCombo( (CCombo) widget( matcher, index ), matcher );
+ }
+
+ public SWTBotCCombo ccomboBoxWithName( String value )
+ {
+ return ccomboBoxWithName( value, 0 );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ public SWTBotCheckBox checkBoxWithName( String name, int index )
+ {
+ Matcher matcher =
+ allOf( widgetOfType( Button.class ), withId( "name", name ), withStyle( SWT.CHECK, "SWT.CHECK" ) );
+ return new SWTBotCheckBox( (Button) widget( matcher, index ), matcher );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ public HyperlinkBot hyperlink( String text )
+ {
+ return new HyperlinkBot( (Hyperlink) widget( allOf( widgetOfType( Hyperlink.class ), withText( text ) ) ) );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ public HyperlinkBot hyperlinkWithLabel( String label )
+ {
+ return new HyperlinkBot( (Hyperlink) widget( allOf( widgetOfType( Hyperlink.class ), withLabel( label ) ) ) );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ public SectionBot section( String title )
+ {
+ return new SectionBot( (Section) widget( allOf( widgetOfType( Section.class ), withText( title ) ) ) );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ public SectionBot sectionWithName( String value )
+ {
+ return new SectionBot( (Section) widget( allOf( widgetOfType( Section.class ), withId( "name", value ) ) ) );
+ }
+
+ public boolean waitForShellToClose( String title )
+ {
+ SWTBotShell shell = activeShell();
+ if ( title != null && title.equals( shell.getText() ) )
+ {
+ return waitForShellToClose( shell );
+ }
+ return false;
+ }
+
+ public boolean waitForShellToClose( SWTBotShell shell )
+ {
+ if ( shell != null )
+ {
+ for ( int i = 0; i < 50; i++ )
+ {
+ if ( !shell.isOpen() )
+ {
+ return true;
+ }
+ sleep( 200 );
+ }
+ shell.close();
+ }
+ return false;
+ }
+
+ @Override
+ public SonatypeSWTBotTree tree()
+ {
+ return new SonatypeSWTBotTree( super.tree() );
+ }
+}
diff --git a/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SonatypeSWTBotTree.java b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SonatypeSWTBotTree.java
new file mode 100644
index 00000000..8a24d8d5
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SonatypeSWTBotTree.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.integration.tests.common;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swtbot.swt.finder.SWTBot;
+import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
+import org.eclipse.swtbot.swt.finder.results.ArrayResult;
+import org.eclipse.swtbot.swt.finder.results.WidgetResult;
+import org.eclipse.swtbot.swt.finder.waits.DefaultCondition;
+import org.eclipse.swtbot.swt.finder.widgets.AbstractSWTBot;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
+import org.eclipse.swtbot.swt.finder.widgets.TimeoutException;
+import org.hamcrest.Matcher;
+import org.hamcrest.SelfDescribing;
+
+public class SonatypeSWTBotTree extends SWTBotTree {
+
+ public SonatypeSWTBotTree(Tree tree, SelfDescribing description)
+ throws WidgetNotFoundException {
+ super(tree, description);
+ }
+
+ public SonatypeSWTBotTree(Tree tree) throws WidgetNotFoundException {
+ super(tree);
+ }
+
+ public SonatypeSWTBotTree(SWTBotTree tree) {
+ this(tree.widget, getDescription(tree));
+ }
+
+ private static SelfDescribing getDescription(SWTBotTree tree) {
+ try {
+ Field f = AbstractSWTBot.class.getDeclaredField("description");
+ return (SelfDescribing) f.get(tree);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public SWTBotTreeItem getTreeItem(final Matcher<Widget>... matchers) {
+ try {
+ new SWTBot().waitUntil(new DefaultCondition() {
+ public String getFailureMessage() {
+ return "Could not find node with text " + Arrays.toString(matchers) + "\nAvailable items: " + Arrays.toString(getItemsText()); //$NON-NLS-1$
+ }
+
+ public boolean test() throws Exception {
+ return getItem(matchers) != null;
+ }
+ });
+ } catch (TimeoutException e) {
+ throw new WidgetNotFoundException(
+ "Timed out waiting for tree item " + Arrays.toString(matchers), e); //$NON-NLS-1$
+ }
+ return new SWTBotTreeItem(getItem(matchers));
+ }
+
+ protected String[] getItemsText() {
+ return syncExec(new ArrayResult<String>() {
+ public String[] run() {
+ TreeItem[] treeItems = widget.getItems();
+ String[] names = new String[treeItems.length];
+
+ for (int i = 0; i < treeItems.length; i++) {
+ TreeItem treeItem = treeItems[i];
+ names[i] = treeItem.getText();
+ }
+
+ return names;
+ }
+ });
+ }
+
+ protected TreeItem getItem(final Matcher<Widget>... matchers) {
+ return syncExec(new WidgetResult<TreeItem>() {
+ public TreeItem run() {
+ TreeItem[] treeItems = widget.getItems();
+ item: for (TreeItem treeItem : treeItems) {
+ for (Matcher<Widget> matcher : matchers) {
+ if (!matcher.matches(treeItem)) {
+ continue item;
+ }
+ }
+
+ return treeItem;
+ }
+
+ return null;
+ }
+ });
+ }
+}
diff --git a/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SwtbotUtil.java b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SwtbotUtil.java
new file mode 100644
index 00000000..1deaec1e
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/SwtbotUtil.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.integration.tests.common;
+
+import org.eclipse.jface.bindings.keys.KeyStroke;
+import org.eclipse.swt.SWT;
+import org.eclipse.swtbot.swt.finder.keyboard.Keystrokes;
+import org.eclipse.swtbot.swt.finder.waits.DefaultCondition;
+import org.eclipse.swtbot.swt.finder.waits.ICondition;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable;
+
+public class SwtbotUtil {
+
+ private static final boolean OS_MAC = "carbon".equals( SWT.getPlatform() ) || "cocoa".equals( SWT.getPlatform() );
+
+ public static boolean waitForClose(SWTBotShell shell) {
+ for (int i = 0; i < 50; i++) {
+ if (!shell.isOpen()) {
+ return true;
+ }
+ sleep(200);
+ }
+ shell.close();
+ return false;
+ }
+
+ private static void sleep(int i) {
+ try {
+ Thread.sleep(i);
+ } catch (InterruptedException ex) {
+ // ;)
+ }
+ }
+
+ public static ICondition waitForLoad(final SWTBotTable table) {
+ return new DefaultCondition() {
+ public boolean test() throws Exception {
+ return table.rowCount() != 0;
+ }
+
+ public String getFailureMessage() {
+ return "Table still empty";
+ }
+ };
+
+ }
+
+ public static KeyStroke[] getUndoShortcut() {
+ return Keystrokes.toKeys(OS_MAC ? SWT.COMMAND : SWT.CONTROL, 'z');
+ }
+
+ public static KeyStroke[] getRedoShortcut() {
+ return Keystrokes.toKeys(OS_MAC ? SWT.COMMAND : SWT.CONTROL, 'y');
+ }
+
+ public static KeyStroke[] getPasteShortcut() {
+ return Keystrokes.toKeys(OS_MAC ? SWT.COMMAND : SWT.CONTROL, 'v');
+ }
+
+ public static KeyStroke[] getMaximizeEditorShortcut() {
+ return Keystrokes.toKeys(OS_MAC ? SWT.COMMAND : SWT.CONTROL, 'm');
+ }
+
+ public static KeyStroke[] getCloseShortcut() {
+ return Keystrokes.toKeys(OS_MAC ? SWT.COMMAND : SWT.CONTROL, 'w');
+ }
+
+}
diff --git a/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/UIIntegrationTestCase.java b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/UIIntegrationTestCase.java
new file mode 100644
index 00000000..c9d5e4a3
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/UIIntegrationTestCase.java
@@ -0,0 +1,1480 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.integration.tests.common;
+
+import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withMnemonic;
+import static org.hamcrest.Matchers.startsWith;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.Socket;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.codehaus.plexus.util.IOUtil;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.embedder.IMavenConfiguration;
+import org.eclipse.m2e.core.embedder.MavenRuntime;
+import org.eclipse.m2e.core.embedder.MavenRuntimeManager;
+import org.eclipse.m2e.core.internal.index.NexusIndexManager;
+import org.eclipse.m2e.core.internal.repository.RepositoryRegistry;
+import org.eclipse.m2e.core.repository.IRepository;
+import org.eclipse.m2e.core.repository.IRepositoryRegistry;
+import org.eclipse.m2e.editor.pom.MavenPomEditor;
+import org.eclipse.m2e.integration.tests.common.matchers.ContainsMnemonic;
+import org.eclipse.m2e.model.edit.pom.Model;
+import org.eclipse.m2e.tests.common.JobHelpers;
+import org.eclipse.m2e.tests.common.WorkspaceHelpers;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEditor;
+import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
+import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
+import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
+import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner;
+import org.eclipse.swtbot.swt.finder.results.Result;
+import org.eclipse.swtbot.swt.finder.results.VoidResult;
+import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
+import org.eclipse.swtbot.swt.finder.utils.SWTUtils;
+import org.eclipse.swtbot.swt.finder.waits.DefaultCondition;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IPerspectiveDescriptor;
+import org.eclipse.ui.IPerspectiveRegistry;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPreferenceConstants;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.internal.IPreferenceConstants;
+import org.eclipse.ui.internal.WorkbenchPlugin;
+import org.eclipse.ui.internal.util.PrefUtil;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.progress.UIJob;
+import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
+import org.hamcrest.text.StringStartsWith;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+
+/**
+ * @author rseddon
+ * @author Marvin Froeder
+ *
+ */
+@SuppressWarnings("restriction")
+@RunWith(SWTBotJunit4ClassRunner.class)
+public abstract class UIIntegrationTestCase {
+
+ private static final String DEFAULT_PROJECT_GROUP = "org.sonatype.test";
+
+ public static final String PACKAGE_EXPLORER_VIEW_ID = "org.eclipse.jdt.ui.PackageExplorer";
+
+ protected static SonatypeSWTBot bot;
+
+ protected static final IProgressMonitor monitor = new NullProgressMonitor();
+
+ private static JobHelpers.IJobMatcher EDITOR_JOB_MATCHER = new JobHelpers.IJobMatcher() {
+ public boolean matches(Job job) {
+ // wait for the job from MavenPomEditor.doSave()
+ return (job instanceof UIJob) && "Saving".equals(job.getName());
+ }
+ };
+
+ @BeforeClass
+ public final static void beforeClass() throws Exception {
+ bot = new SonatypeSWTBot();
+
+ SWTBotPreferences.KEYBOARD_LAYOUT = "EN_US";
+ SWTBotPreferences.TIMEOUT = 10 * 1000;
+
+ // close the Welcome view if it's open
+ try {
+ SWTBotView view = bot.activeView();
+ if(view != null && "org.eclipse.ui.internal.introview".equals(view.getViewReference().getId())) {
+ view.close();
+ }
+ } catch(WidgetNotFoundException e) {
+ // no active view
+ }
+
+ SWTBotShell[] shells = bot.shells();
+ for (SWTBotShell shell : shells) {
+ final Shell widget = shell.widget;
+ Object parent = UIThreadRunnable.syncExec(shell.display,
+ new Result<Object>() {
+ public Object run() {
+ return widget.isDisposed() ? null : widget.getParent();
+ }
+ });
+
+ if (parent == null) {
+ continue;
+ }
+
+ shell.close();
+ }
+
+ List<? extends SWTBotEditor> editors = bot.editors();
+ for (SWTBotEditor e : editors) {
+ e.close();
+ }
+
+ // Clean out projects left over from previous test runs.
+ clearProjects();
+
+ // Turn off eclipse features which make tests unreliable.
+ WorkbenchPlugin.getDefault().getPreferenceStore().setValue(
+ IPreferenceConstants.RUN_IN_BACKGROUND, true);
+
+ PrefUtil.getAPIPreferenceStore().setValue(
+ IWorkbenchPreferenceConstants.ENABLE_ANIMATIONS, false);
+
+ // fullScreen();
+ MavenPlugin.getDefault(); // force m2e to load so its indexing jobs will
+ // be scheduled.
+
+ openPerspective("org.eclipse.jdt.ui.JavaPerspective");
+
+ closeView("org.eclipse.ui.views.ContentOutline");
+ closeView("org.eclipse.mylyn.tasks.ui.views.tasks");
+ }
+
+ @Before
+ public final void waitMenu() {
+ // The following seems to be needed to run SWTBot tests in Xvfb (the 'fake' X-server).
+ // see http://dev.eclipse.org/mhonarc/newsLists/news.eclipse.swtbot/msg01134.html
+ UIThreadRunnable.syncExec(new VoidResult() {
+ public void run() {
+ PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell()
+ .forceActive();
+ }
+ });
+
+ bot.waitUntil(new DefaultCondition() {
+
+ public boolean test() throws Exception {
+ return bot.menu("File").isEnabled();
+ }
+
+ public String getFailureMessage() {
+ return "Menu bar not available";
+ }
+ });
+ }
+
+ @AfterClass
+ public final static void sleep() throws Exception {
+ removeServer();
+ clearProjects();
+ takeScreenShot("cleared projects");
+ }
+
+ @After
+ public final void finalShot() throws IOException {
+ takeScreenShot(getClass().getSimpleName());
+ }
+
+ public static File takeScreenShot(String classifier) throws IOException {
+ File parent = new File("target/screenshots");
+ parent.mkdirs();
+ File output = getCanonicalFile(File.createTempFile("swtbot-", "-"
+ + classifier + ".png", parent));
+ output.getParentFile().mkdirs();
+ SWTUtils.captureScreenshot(output.getAbsolutePath());
+ return output;
+ }
+
+ protected static File getCanonicalFile(File file) {
+ try {
+ return file.getCanonicalFile();
+ } catch (IOException e) {
+ return file.getAbsoluteFile();
+ }
+ }
+
+ public static File takeScreenShot() throws IOException {
+ return takeScreenShot("screen");
+ }
+
+ public static Exception takeScreenShot(Throwable e) throws Exception {
+ File shot = takeScreenShot("exception");
+ throw new Exception(e.getMessage() + " - " + shot, e);
+ }
+
+ protected void importZippedProject(File f) throws Exception {
+ try {
+ bot.menu("File").menu("Import...").click();
+ SWTBotShell shell = bot.shell("Import");
+ try {
+ shell.activate();
+
+ bot.tree().expandNode("General").select(
+ "Existing Projects into Workspace");
+ bot.button("Next >").click();
+ // bot.button("Select root directory:").click();
+ bot.radio("Select archive file:").click();
+ bot.text(1).setText(f.getCanonicalPath());
+
+ bot.button("Refresh").click();
+ bot.button("Finish").click();
+ } catch (Throwable e) {
+ takeScreenShot(e);
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+
+ waitForAllBuildsToComplete();
+ } finally {
+ f.delete();
+ }
+ }
+
+ protected static void waitForAllBuildsToComplete() {
+ waitForAllEditorsToSave();
+ JobHelpers.waitForJobsToComplete();
+ }
+
+ protected static void waitForAllLaunchesToComplete(int maxWaitMillis) {
+ waitForAllEditorsToSave();
+ JobHelpers.waitForLaunchesToComplete(maxWaitMillis);
+ }
+
+ protected static void waitForAllEditorsToSave() {
+ JobHelpers.waitForJobs(EDITOR_JOB_MATCHER, 30 * 1000);
+ }
+
+ protected void createNewFolder(String projectName, String folderName) {
+ // Add a new src folder with simple source file
+ SWTBotTree tree = selectProject(projectName, true);
+
+ ContextMenuHelper.clickContextMenu(tree, "New", "Folder");
+
+ SWTBotShell shell = bot.shell("New Folder");
+ try {
+ shell.activate();
+
+ bot.textWithLabel("Folder name:").setText(folderName);
+ bot.button("Finish").click();
+
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+ }
+
+ protected File importMavenProjects(String pluginId, String projectPath)
+ throws Exception {
+ File tempDir = unzipProject(pluginId, projectPath);
+ waitForAllBuildsToComplete();
+ // try {
+ // getUI().click(new ButtonLocator("Cancel"));
+ // // if there is a dialog up here, take a screenshot but get rid of it
+ // // - so we can keep going
+ // ScreenCapture.createScreenCapture();
+ // } catch (Exception e) {
+ // // make sure that there are no dialogs up here
+ // }fi
+ try {
+ bot.menu("File").menu("Import...").click();
+
+ SWTBotShell shell = bot.shell("Import");
+ try {
+ shell.activate();
+
+ bot.tree().expandNode("Maven")
+ .select("Existing Maven Projects");
+ bot.button("Next >").click();
+ bot.comboBoxWithLabel("Root Directory:").setText(
+ tempDir.getCanonicalPath());
+
+ bot.button("Refresh").click();
+ bot.button("Finish").click();
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+
+ waitForAllBuildsToComplete();
+
+ } catch (Exception ex) {
+ deleteDirectory(tempDir);
+ throw ex;
+ }
+
+ return tempDir;
+ }
+
+ protected void openResource(String resourceName) {
+ bot.menu("Navigate").menu("Open Resource...").click();
+ SWTBotShell shell = bot.shell("Open Resource");
+ try {
+ shell.activate();
+
+ bot.text().setText(resourceName);
+ bot.button("Open").click();
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+ }
+
+ protected void openType(String typeName) {
+ bot.menu("Navigate").menu("Open Type...").click();
+ SWTBotShell shell = bot.shell("Open Type");
+ try {
+ shell.activate();
+
+ bot.text().setText(typeName);
+ bot.button("OK").click();
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+ }
+
+ protected void checkoutProjectsFromSVN(String url) throws Exception {
+ bot.menu("File").menu("Import...").click();
+
+ SWTBotShell shell = bot.shell("Import");
+ try {
+ shell.activate();
+
+ bot.tree().expandNode("Maven").select(
+ "Check out Maven Projects from SCM");
+ bot.button("Next >").click();
+ // for some reason, in eclipse 3.5.1 and WT, the direct combo
+ // selection
+ // is
+ // not triggering the UI events, so the finish button never gets
+ // enabled
+ // getUI().click(new ComboItemLocator("svn", new
+ // NamedWidgetLocator("mavenCheckoutLocation.typeCombo")));
+ // getUI().setFocus(
+ // new NamedWidgetLocator("mavenCheckoutLocation.typeCombo"));
+ // for (int i = 0; i < 9; i++) {
+ // getUI().keyClick(WT.ARROW_DOWN);
+ // }
+ try {
+ bot.comboBoxWithLabel("SCM URL:").setSelection("svn");
+ } catch (RuntimeException ex) {
+ throw new RuntimeException("Available options: "
+ + Arrays.asList(bot.comboBoxWithLabel("SCM URL:")
+ .items()), ex);
+ }
+ bot.comboBox(1).setText(url);
+
+ bot.button("Finish").click();
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+
+ waitForAllBuildsToComplete();
+ }
+
+ public void importZippedProject(String pluginID, String pluginPath)
+ throws Exception {
+ File f = copyPluginResourceToTempFile(pluginID, pluginPath);
+ try {
+ importZippedProject(f);
+ } finally {
+ f.delete();
+ }
+ }
+
+ protected IViewPart showView(final String id) throws Exception {
+ IViewPart part = (IViewPart) UIThreadTask
+ .executeOnEventQueue(new UIThreadTask() {
+ public Object runEx() throws Exception {
+ IViewPart part = getActivePage().showView(id);
+
+ return part;
+ }
+ });
+
+ waitForAllBuildsToComplete();
+ Assert.assertFalse(part == null);
+
+ SWTBotView view = bot.viewById(id);
+ view.show();
+
+ return part;
+ }
+
+ protected static SWTBotView openView(final String id) {
+ SWTBotView view;
+ try {
+ view = bot.viewById(id);
+ } catch (WidgetNotFoundException e) {
+ IViewPart part;
+ try {
+ part = (IViewPart) UIThreadTask
+ .executeOnEventQueue(new UIThreadTask() {
+ public Object runEx() throws Exception {
+ IViewPart part = getActivePage().showView(id);
+
+ return part;
+ }
+ });
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ Assert.assertFalse(part == null);
+
+ view = bot.viewById(id);
+ }
+ view.show();
+
+ return view;
+ }
+
+ protected void updateProjectConfiguration(String projectName)
+ throws Exception {
+ SWTBotTree tree = selectProject(projectName, true);
+
+ ContextMenuHelper.clickContextMenu(tree, "Maven",
+ "Update Project Configuration");
+
+ waitForAllBuildsToComplete();
+ }
+
+ protected void openIssueTracking(String projectName) throws Exception {
+ SWTBotTree tree = selectProject("test-project", true);
+
+ ContextMenuHelper.clickContextMenu(tree, "Maven", "Open Issue Tracker");
+
+ waitForAllBuildsToComplete();
+ }
+
+ protected SWTBotTree selectProject(String projectName) {
+ return selectProject(projectName, true);
+ }
+
+ protected SWTBotTree selectProject(String projectName, boolean searchForIt) {
+ SWTBotTree tree = bot.viewById(PACKAGE_EXPLORER_VIEW_ID).bot().tree();
+ SWTBotTreeItem treeItem = null;
+ try {
+ treeItem = tree.getTreeItem(projectName);
+ } catch (WidgetNotFoundException ex) {
+ if (searchForIt) {
+ SWTBotTreeItem[] allItems = tree.getAllItems();
+ for (SWTBotTreeItem item : allItems) {
+ // workaround required due to SVN/CVS that does add extra
+ // informations to project name
+ if (item.getText().contains(projectName)) {
+ treeItem = item;
+ break;
+ }
+ }
+ }
+
+ if (treeItem == null) {
+ throw ex;
+ }
+ }
+ treeItem.select();
+ return tree;
+ }
+
+ protected List<SWTBotTreeItem> findItems(SWTBotTreeItem tree,
+ Matcher<String> matcher) {
+ List<SWTBotTreeItem> items = new ArrayList<SWTBotTreeItem>();
+ SWTBotTreeItem[] allItems = tree.getItems();
+ for (SWTBotTreeItem item : allItems) {
+ if (matcher.matches(item.getText())) {
+ items.add(item);
+ }
+ }
+
+ return items;
+ }
+
+ protected SWTBotTreeItem findItem(SWTBotTreeItem tree,
+ Matcher<String> matcher) {
+ List<SWTBotTreeItem> items = findItems(tree, matcher);
+ Assert.assertEquals(1, items.size());
+ return items.get(0);
+ }
+
+ protected SWTBotTreeItem selectNode(SWTBotTree tree, Matcher<String> matcher) {
+ SWTBotTreeItem treeItem = null;
+ SWTBotTreeItem[] allItems = tree.getAllItems();
+ for (SWTBotTreeItem item : allItems) {
+ if (matcher.matches(item.getText())) {
+ treeItem = item;
+ break;
+ }
+ }
+
+ if (treeItem != null) {
+ treeItem.select();
+ }
+ return treeItem;
+ }
+
+ protected void installTomcat6() throws Exception {
+
+ String tomcatInstallLocation = System
+ .getProperty(TOMCAT_INSTALL_LOCATION_PROPERTY);
+ if (tomcatInstallLocation == null) {
+ tomcatInstallLocation = DEFAULT_TOMCAT_INSTALL_LOCATION;
+ }
+
+ Assert.assertTrue("Can't locate tomcat installation: "
+ + tomcatInstallLocation, new File(tomcatInstallLocation)
+ .exists());
+ // Install the Tomcat server
+
+ Thread.sleep(5000);
+
+ showView(SERVERS_VIEW_ID);
+ SWTBotView serversView = bot.viewById(SERVERS_VIEW_ID);
+
+ SWTBotTree tree = serversView.bot().tree();
+ Assert.assertEquals("Server view already contains a server "
+ + tree.getAllItems(), 0, tree.getAllItems().length);
+
+ ContextMenuHelper.clickContextMenu(tree, "New", "Server");
+
+ SWTBotShell shell = bot.shell("New Server");
+ try {
+ shell.activate();
+
+ bot.tree().expandNode("Apache").select("Tomcat v6.0 Server");
+ bot.button("Next >").click();
+
+ SWTBotButton b = bot.button("Finish");
+ if (!b.isEnabled()) {
+ // First time...
+ bot.textWithLabel("Tomcat installation &directory:").setText(
+ tomcatInstallLocation);
+ }
+ b.click();
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+
+ waitForAllBuildsToComplete();
+ }
+
+ protected void deployProjectsIntoTomcat() throws Exception {
+ // Deploy the test project into tomcat
+ SWTBotView serversView = bot.viewById(SERVERS_VIEW_ID);
+ serversView.show();
+ serversView.setFocus();
+
+ SWTBotTree tree = serversView.bot().tree().select(0);
+ if (isEclipseVersion(3, 5)) {
+ ContextMenuHelper.clickContextMenu(tree, "Add and Remove...");
+ } else {
+ ContextMenuHelper.clickContextMenu(tree,
+ "Add and Remove Projects...");
+ }
+ String title = isEclipseVersion(3, 5) ? "Add and Remove..."
+ : "Add and Remove Projects";
+
+ SWTBotShell shell = bot.shell(title);
+ try {
+ shell.activate();
+ bot.button("Add All >>").click();
+ bot.button("Finish").click();
+ } catch (Throwable ex) {
+ takeScreenShot(ex);
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+
+ ContextMenuHelper.clickContextMenu(tree, "Start");
+
+ waitForAllBuildsToComplete();
+ if (!waitForServer(8080, 10000)) {
+ ContextMenuHelper.clickContextMenu(tree, Matchers.anyOf(
+ withMnemonic("Start"), withMnemonic("Restart")));
+ waitForAllBuildsToComplete();
+ waitForServer(8080, 10000);
+ }
+ }
+
+ protected static void shutdownServer() {
+ try {
+ // shutdown the server
+ SWTBotView serversView = bot.viewById(SERVERS_VIEW_ID);
+ serversView.show();
+ SWTBotTree tree = serversView.bot().tree().select(0);
+
+ ContextMenuHelper.clickContextMenu(tree, "Stop");
+
+ waitForAllBuildsToComplete();
+
+ SWTBotShell shell = bot.shell("Terminate Server");
+ try {
+ shell.activate();
+ bot.button("OK").click();
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+ } catch (WidgetNotFoundException ex) {
+ // this only happen when server takes too long to stop
+ }
+ }
+
+ public static void removeServer() {
+ // shutdown the server
+ try {
+ SWTBotView serversView = bot.viewById(SERVERS_VIEW_ID);
+ SWTBotTree tree = serversView.bot().tree();
+
+ for (int i = 0; i < tree.getAllItems().length; i++) {
+ SWTBotTree server = tree.select(0);
+
+ // stop it first
+ try {
+ ContextMenuHelper.clickContextMenu(server, "Stop");
+ } catch (Exception e) {
+ // was not started
+ }
+ waitForAllBuildsToComplete();
+
+ ContextMenuHelper.clickContextMenu(server, "Delete");
+
+ SWTBotShell shell = bot.shell("Delete Server");
+ try {
+ shell.activate();
+
+ bot.button("OK").click();
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+ }
+
+ waitForAllBuildsToComplete();
+ } catch (WidgetNotFoundException e) {
+ // not an issue, mean this is not a server test
+ return;
+ } catch (SWTException e) {
+ if (e.getCause() instanceof WidgetNotFoundException) {
+ return; // not a problem
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ protected void restartServer(boolean republish) throws Exception {
+ // shutdown the server
+ SWTBotView serversView = bot.viewById(SERVERS_VIEW_ID);
+ serversView.show();
+
+ SWTBotTree tree;
+ try {
+ tree = serversView.bot().tree().select(0);
+ } catch (WidgetNotFoundException ex) {
+ takeScreenShot(ex);
+ throw ex;
+ }
+
+ shutdownServer();
+
+ if (republish) {
+ ContextMenuHelper.clickContextMenu(tree, "Publish");
+ waitForAllBuildsToComplete();
+ }
+
+ ContextMenuHelper.clickContextMenu(tree, "Start");
+ waitForAllBuildsToComplete();
+ }
+
+ protected void findText(String src) {
+ findTextWithWrap(src, false);
+ }
+
+ public static final String FIND_REPLACE = "Find/Replace";
+
+ protected void findTextWithWrap(String src, boolean wrap) {
+ bot.menu("Edit").menu("Find/Replace...").click();
+
+ SWTBotShell shell = bot.shell(FIND_REPLACE);
+ try {
+ shell.activate();
+
+ bot.comboBoxWithLabel("Find:").setText(src);
+ if (wrap) {
+ bot.checkBox("Wrap search").select();
+ } else {
+ bot.checkBox("Wrap search").deselect();
+ }
+
+ bot.button("Find").click();
+ bot.button("Close").click();
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+ }
+
+ protected void replaceText(String src, String target) {
+ replaceTextWithWrap(src, target, false);
+ }
+
+ protected void replaceTextWithWrap(String src, String target, boolean wrap) {
+ bot.menu("Edit").menu("Find/Replace...").click();
+
+ SWTBotShell shell = bot.shell(FIND_REPLACE);
+ try {
+ shell.activate();
+
+ bot.comboBoxWithLabel("Find:").setText(src);
+ bot.comboBoxWithLabel("Replace with:").setText(target);
+
+ if (wrap) {
+ bot.checkBox("Wrap search").select();
+ } else {
+ bot.checkBox("Wrap search").deselect();
+ }
+
+ bot.button("Replace All").click();
+
+ bot.button("Close").click();
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+
+ }
+
+ public static boolean isEclipseVersion(int major, int minor) {
+ Bundle bundle = ResourcesPlugin.getPlugin().getBundle();
+ String version = (String) bundle.getHeaders().get(
+ org.osgi.framework.Constants.BUNDLE_VERSION);
+ Version v = org.osgi.framework.Version.parseVersion(version);
+ return v.getMajor() == major && v.getMinor() == minor;
+ }
+
+ protected static IWorkbenchPage getActivePage() {
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ return workbench.getWorkbenchWindows()[0].getActivePage();
+ }
+
+ protected File copyPluginResourceToTempFile(String plugin, String file)
+ throws MalformedURLException, IOException {
+ URL url = FileLocator.find(Platform.getBundle(plugin), new Path("/"
+ + file), null);
+ return copyPluginResourceToTempFile(plugin, url);
+ }
+
+ protected File copyPluginResourceToTempFile(String plugin, URL url)
+ throws MalformedURLException, IOException {
+ File f = File.createTempFile("temp", "."
+ + new Path(url.getFile()).getFileExtension());
+ InputStream is = new BufferedInputStream(url.openStream());
+ FileOutputStream os = new FileOutputStream(f);
+ try {
+ IOUtil.copy(is, os);
+ } finally {
+ is.close();
+ os.close();
+ }
+
+ return f;
+ }
+
+ /**
+ * Import a project and assert it has no markers of SEVERITY_ERROR
+ */
+ protected File doImport(String pluginId, String projectPath)
+ throws Exception {
+ return doImport(pluginId, projectPath, true);
+ }
+
+ protected File doImport(String pluginId, String projectPath,
+ boolean assertNoErrors) throws Exception {
+ File tempDir = importMavenProjects(pluginId, projectPath);
+ if (assertNoErrors) {
+ assertProjectsHaveNoErrors();
+ }
+ return tempDir;
+ }
+
+ protected void assertProjectsHaveNoErrors() throws Exception {
+ StringBuffer messages = new StringBuffer();
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
+ .getProjects();
+ int count = 0;
+ for (IProject project : projects) {
+ if ("Servers".equals(project.getName())) {
+ continue;
+ }
+ if (count >= 10) {
+ break;
+ }
+ IMarker[] markers = project.findMarkers(IMarker.PROBLEM, true,
+ IResource.DEPTH_INFINITE);
+ for (int i = 0; i < markers.length; i++) {
+ if (markers[i].getAttribute(IMarker.SEVERITY, 0) == IMarker.SEVERITY_ERROR) {
+ count++;
+ messages.append('\t');
+ if (messages.length() > 0) {
+ messages.append(System.getProperty("line.separator"));
+ }
+ messages.append(project.getName()
+ + ":"
+ + markers[i].getAttribute(IMarker.LOCATION,
+ "unknown location")
+ + " "
+ + markers[i].getAttribute(IMarker.MESSAGE,
+ "unknown message"));
+ }
+ }
+ }
+ if (count > 0) {
+ Assert.fail("One or more compile errors found:"
+ + System.getProperty("line.separator") + messages);
+ }
+ }
+
+ private static void unzipFile(String pluginId, String pluginPath, File dest)
+ throws IOException {
+ URL url = FileLocator.find(Platform.getBundle(pluginId), new Path("/"
+ + pluginPath), null);
+ InputStream is = new BufferedInputStream(url.openStream());
+ ZipInputStream zis = new ZipInputStream(is);
+ try {
+ ZipEntry entry = zis.getNextEntry();
+ while (entry != null) {
+ File f = new File(dest, entry.getName());
+ if (entry.isDirectory()) {
+ f.mkdirs();
+ } else {
+ if (!f.getParentFile().exists()) {
+ f.getParentFile().mkdirs();
+ }
+ OutputStream os = new BufferedOutputStream(
+ new FileOutputStream(f));
+ try {
+ IOUtil.copy(zis, os);
+ } finally {
+ os.close();
+ }
+ }
+ zis.closeEntry();
+ entry = zis.getNextEntry();
+ }
+ } finally {
+ zis.close();
+ }
+ }
+
+ public static File unzipProject(String pluginId, String pluginPath)
+ throws Exception {
+ File tempDir = createTempDir("sonatype");
+ unzipFile(pluginId, pluginPath, tempDir);
+ return tempDir;
+ }
+
+ protected static File createTempDir(String prefix) throws IOException {
+ File temp = null;
+ temp = File.createTempFile(prefix, "");
+ if (!temp.delete()) {
+ throw new IOException("Unable to delete temp file:"
+ + temp.getName());
+ }
+ if (!temp.mkdir()) {
+ throw new IOException("Unable to create temp dir:" + temp.getName());
+ }
+ return temp;
+ }
+
+ private void deleteDirectory(File dir) {
+ File[] fileArray = dir.listFiles();
+ if (fileArray != null) {
+ for (int i = 0; i < fileArray.length; i++) {
+ if (fileArray[i].isDirectory())
+ deleteDirectory(fileArray[i]);
+ else
+ fileArray[i].delete();
+ }
+ }
+ dir.delete();
+ }
+
+ // Location of tomcat 6 installation which can be used by Eclipse WTP tests
+ private static final String DEFAULT_TOMCAT_INSTALL_LOCATION = "target/tomcat/apache-tomcat-6.0.24";
+
+ // Set this system property to override DEFAULT_TOMCAT_INSTALL_LOCATION
+ private static final String TOMCAT_INSTALL_LOCATION_PROPERTY = "tomcat.install.location";
+
+ public static final String SERVERS_VIEW_ID = "org.eclipse.wst.server.ui.ServersView";
+
+ public static final String TOMCAT_SERVER_NAME = "Tomcat.*";
+
+ public static void clearProjects() throws Exception {
+ WorkspaceHelpers.cleanWorkspace();
+ }
+
+ protected MavenPomEditor openPomFile(String name) throws Exception {
+
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IFile file = root.getFile(new Path(name));
+
+ final IEditorInput editorInput = new FileEditorInput(file);
+ MavenPomEditor editor = (MavenPomEditor) UIThreadTask
+ .executeOnEventQueue(new UIThreadTask() {
+
+ public Object runEx() throws Exception {
+ IEditorPart part = getActivePage().openEditor(
+ editorInput,
+ "org.eclipse.m2e.editor.MavenPomEditor",
+ true);
+ if (part instanceof MavenPomEditor) {
+ return part;
+ }
+ return null;
+ }
+ });
+
+ waitForAllBuildsToComplete();
+
+ return editor;
+ }
+
+ protected Model getModel(final MavenPomEditor editor) throws Exception {
+ Model model = (Model) UIThreadTask
+ .executeOnEventQueue(new UIThreadTask() {
+
+ public Object runEx() throws Exception {
+ return editor.readProjectDocument();
+ }
+ });
+ return model;
+ }
+
+ /**
+ * Create an archetype project and assert that it has proper natures &
+ * builders, and no error markers
+ */
+ protected IProject createArchetypeProject(final String archetypeName,
+ String projectName) throws Exception {
+ try {
+ IProject project = ResourcesPlugin.getWorkspace().getRoot()
+ .getProject(projectName);
+ Assert.assertFalse(project.exists());
+
+ bot.menu("File").menu("New").menu("Project...").click();
+
+ SWTBotShell shell = bot.shell("New Project");
+ try {
+ shell.activate();
+
+ bot.tree().expandNode("Maven").select("Maven Project");
+ // click the first next button
+ bot.button("Next >").click();
+ bot.checkBox(
+ "Create a simple project (skip archetype selection)")
+ .deselect();
+
+ // then the first page with only 'default' values
+ bot.button("Next >").click();
+ bot.comboBoxWithId("name", "catalogsCombo").setSelection(0);
+
+ bot.waitUntil(SwtbotUtil.waitForLoad(bot.table()));
+
+ // now select the quickstart row
+ bot.table().select(bot.table().indexOf(archetypeName, 1));
+
+ // and then click next
+ bot.button("Next >").click();
+
+ // then fill in the last page details
+ bot.comboBoxWithLabel("Group Id:").setText(
+ DEFAULT_PROJECT_GROUP);
+ bot.comboBoxWithLabel("Artifact Id:").setText(projectName);
+
+ bot.button("Finish").click();
+ } catch (Throwable ex) {
+ throw new Exception("Failed to create project for archetype:"
+ + archetypeName + " - " + takeScreenShot(), ex);
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+
+ waitForAllBuildsToComplete();
+
+ project = ResourcesPlugin.getWorkspace().getRoot().getProject(
+ projectName);
+ Assert.assertTrue(project.exists());
+ assertProjectsHaveNoErrors();
+ Assert.assertTrue("archtype project \"" + archetypeName
+ + "\" created without Maven nature", project
+ .hasNature(IMavenConstants.NATURE_ID));
+
+ selectProject(projectName, true);
+
+ return project;
+ } catch (Throwable ex) {
+ throw new Exception("Failed to create project for archetype:"
+ + archetypeName + " - " + takeScreenShot(), ex);
+ }
+ }
+
+ /**
+ * Create an archetype project and assert that it has proper natures &
+ * builders, and no error markers
+ */
+ protected IProject createSimpleMavenProject(String projectName)
+ throws Exception {
+ try {
+ IProject project = ResourcesPlugin.getWorkspace().getRoot()
+ .getProject(projectName);
+ Assert.assertFalse(project.exists());
+
+ bot.menu("File").menu("New").menu("Project...").click();
+
+ SWTBotShell shell = bot.shell("New Project");
+ try {
+ shell.activate();
+
+ bot.tree().expandNode("Maven").select("Maven Project");
+
+ bot.button("Next >").click();
+
+ bot.checkBox(
+ "Create a simple project (skip archetype selection)")
+ .click();
+
+ bot.button("Next >").click();
+
+ // then fill in the last page details
+ bot.comboBoxWithLabel("Group Id:").setText(
+ DEFAULT_PROJECT_GROUP);
+ bot.comboBoxWithLabel("Artifact Id:").setText(projectName);
+
+ bot.button("Finish").click();
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+
+ waitForAllBuildsToComplete();
+
+ project = ResourcesPlugin.getWorkspace().getRoot().getProject(
+ projectName);
+ Assert.assertTrue(project.exists());
+ assertProjectsHaveNoErrors();
+ Assert.assertTrue(projectName + " created without Maven nature",
+ project.hasNature(IMavenConstants.NATURE_ID));
+
+ selectProject(projectName, true);
+
+ return project;
+ } catch (Throwable ex) {
+ throw new Exception("Failed to create project for archetype:"
+ + projectName + " - " + takeScreenShot(), ex);
+ }
+ }
+
+ protected IEditorPart openFile(IProject project, String relPath)
+ throws Exception {
+
+ final IFile f = project.getFile(relPath);
+
+ IEditorPart editor = (IEditorPart) UIThreadTask
+ .executeOnEventQueue(new UIThreadTask() {
+
+ public Object runEx() throws Exception {
+ return IDE.openEditor(getActivePage(), f, true);
+ }
+ });
+
+ return editor;
+ }
+
+ private static boolean xmlPrefsSet = false;
+
+ protected void setXmlPrefs() throws Exception {
+ if (!xmlPrefsSet && isEclipseVersion(3, 5)) {
+ // Disable new xml completion behavior to preserver compatibility
+ // with previous versions.
+ bot.menu("Window").menu("Preferences").click();
+
+ SWTBotShell shell = bot.shell("Preferences");
+ try {
+ shell.activate();
+
+ bot.tree().expandNode("XML").expandNode("XML Files")
+ .expandNode("Editor").select("Typing");
+
+ bot.checkBox("Insert a matching end tag").select();
+
+ bot.button("OK").click();
+
+ xmlPrefsSet = true;
+
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+ }
+ }
+
+ protected IProject createQuickstartProject(String projectName)
+ throws Exception {
+ return createArchetypeProject("maven-archetype-quickstart", projectName);
+ }
+
+ protected void save() {
+ bot.menu("File").menu("Save").click();
+ }
+
+ protected static void assertWizardError(final String message)
+ throws Exception {
+ assertWizardMessage(message, WizardPage.ERROR);
+ }
+
+ protected static void assertWizardMessage(final String message)
+ throws Exception {
+ assertWizardMessage(message, WizardPage.INFORMATION);
+ }
+
+ protected static void assertWizardMessage(final String message,
+ final int severity) throws Exception {
+ bot.sleep(1000);
+ final AssertionError[] error = new AssertionError[] { null };
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ try {
+ Object data = bot.activeShell().widget.getData();
+ assertTrue("Current dialog is expected to be a wizard",
+ data instanceof WizardDialog);
+
+ boolean error = severity == WizardPage.ERROR;
+
+ IWizardPage page = ((WizardDialog) data).getCurrentPage();
+ String wizardMessage = error ? page.getErrorMessage()
+ : page.getMessage();
+ String prefix = error ? "Wizard error " : "Wizard message ";
+
+ if (message == null) {
+ assertNull(prefix + "should be null", wizardMessage);
+ } else {
+ assertNotNull(prefix + "should not be null",
+ wizardMessage);
+ assertEquals(prefix + "is not as expected", message,
+ wizardMessage.trim());
+ }
+ } catch (AssertionError e) {
+ error[0] = e;
+ }
+ }
+ });
+ if (error[0] != null) {
+ takeScreenShot(error[0]);
+ }
+ }
+
+ protected void addDependency(IProject project, String groupId,
+ String artifactId, String version) {
+ addDependency(project.getName(), groupId, artifactId, version);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void addDependency(String projectName, String groupId,
+ String artifactId, String version) {
+ ContextMenuHelper.clickContextMenu(selectProject(projectName), "Maven",
+ "Add Dependency");
+
+ SWTBotShell shell = bot.shell("Add Dependency");
+ try {
+ shell.activate();
+
+ bot.text().setText(artifactId);
+ SWTBotTreeItem node = bot.tree().getTreeItem(
+ ContainsMnemonic.containsMnemonic(groupId),
+ ContainsMnemonic.containsMnemonic(artifactId));
+ node.expand();
+ String[] selection = findNodeName(node, startsWith(version));
+ assertEquals("The matcher is expected to find one node", 1,
+ selection.length);
+ node.getNode(selection[0]).doubleClick();
+
+ // bot.button("OK").click();
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+ }
+
+ protected String[] findNodeName(SWTBotTreeItem node, Matcher<String> matcher) {
+ List<String> nodes = new ArrayList<String>();
+ List<String> items = node.getNodes();
+ for (String text : items) {
+ if (matcher.matches(text)) {
+ nodes.add(text);
+ }
+ }
+ return nodes.toArray(new String[0]);
+ }
+
+ protected void cleanProjects() {
+ bot.menu("Project").menu("Clean...").click();
+
+ SWTBotShell shell = bot.shell("Clean");
+ try {
+ shell.activate();
+ bot.radio("Clean all projects").click();
+ bot.button("ok").click();
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+
+ waitForAllBuildsToComplete();
+ }
+
+ protected static void closeView(final String id) throws Exception {
+ IViewPart view = (IViewPart) UIThreadTask
+ .executeOnEventQueue(new UIThreadTask() {
+
+ public Object runEx() throws Exception {
+ IViewPart view = getActivePage().findView(id);
+
+ return view;
+ }
+ });
+
+ if (view != null) {
+ bot.viewById(id).close();
+ }
+ }
+
+ protected static void openPerspective(final String id) throws Exception {
+ // select Java perspective
+ bot.perspectiveById(id).activate();
+
+ UIThreadTask.executeOnEventQueue(new UIThreadTask() {
+
+ public Object runEx() throws Exception {
+ IPerspectiveRegistry perspectiveRegistry = PlatformUI
+ .getWorkbench().getPerspectiveRegistry();
+ IPerspectiveDescriptor perspective = perspectiveRegistry
+ .findPerspectiveWithId(id);
+ getActivePage().setPerspective(perspective);
+
+ return null;
+ }
+ });
+ }
+
+ protected void switchToExternalMaven() throws Exception {
+ MavenRuntime newRuntime = MavenRuntimeManager
+ .createExternalRuntime("C:\\apache-maven-2.1.0");
+ List<MavenRuntime> currRuntimes = MavenPlugin.getDefault()
+ .getMavenRuntimeManager().getMavenRuntimes();
+ ArrayList<MavenRuntime> list = new ArrayList<MavenRuntime>(currRuntimes);
+ list.add(newRuntime);
+ MavenPlugin.getDefault().getMavenRuntimeManager().setRuntimes(list);
+ MavenPlugin.getDefault().getMavenRuntimeManager().setDefaultRuntime(
+ newRuntime);
+ }
+
+ protected void updateLocalIndex() throws Exception {
+ SWTBotView view = openView("org.eclipse.m2e.core.views.MavenRepositoryView");
+ SWTBotTree tree = view.bot().tree();
+ findItem(tree.expandNode("Local Repositories"),
+ StringStartsWith.startsWith("Local Repository")).select();
+ ContextMenuHelper.clickContextMenu(tree, "Rebuild Index");
+
+ SWTBotShell shell = bot.shell("Rebuild Index");
+ try {
+ shell.activate();
+ bot.button("OK").click();
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+
+ waitForAllBuildsToComplete();
+
+ showView("org.eclipse.m2e.core.views.MavenRepositoryView");
+ }
+
+ protected void excludeArtifact(String projectName, String jarName)
+ throws Exception {
+ SWTBotTree tree = selectProject(projectName);
+ findItem(tree.expandNode(projectName).expandNode("Maven Dependencies"),
+ StringStartsWith.startsWith(jarName)).select();
+ ContextMenuHelper.clickContextMenu(tree, "Maven",
+ "Exclude Maven artifact...");
+ SWTBotShell shell = bot.shell("Exclude Maven Artifact");
+ try {
+ shell.activate();
+ bot.button("OK").click();
+ } finally {
+ SwtbotUtil.waitForClose(shell);
+ }
+
+ waitForAllBuildsToComplete();
+ }
+
+ protected static boolean waitForServer(int port, int timeout) {
+ Socket socket = new Socket();
+ try {
+ socket.bind(null);
+ } catch (IOException e) {
+ return false;
+ }
+ try {
+ for (int i = 0; i <= timeout / 100; i++) {
+ try {
+ socket.connect(new InetSocketAddress(InetAddress
+ .getByName(null), port), 100);
+ return true;
+ } catch (IOException e) {
+ // ignored, retry
+ }
+ }
+ return false;
+ } finally {
+ try {
+ socket.close();
+ } catch (IOException e) {
+ // ignored
+ }
+ }
+ }
+
+ protected String retrieveWebPage(String urlString) throws IOException,
+ InterruptedException {
+ int i = 0;
+ do {
+ URL url = new URL(urlString);
+ URLConnection conn;
+ try {
+ conn = url.openConnection();
+ } catch (IOException e) {
+ continue;
+ }
+ conn.setDoInput(true);
+ try {
+ conn.connect();
+ } catch (IOException e) {
+ Thread.sleep(1000);
+ continue;
+ }
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ IOUtil.copy(conn.getInputStream(), out);
+
+ try {
+ conn.getInputStream().close();
+ } catch (IOException e) {
+ // not relevant
+ }
+
+ return new String(out.toByteArray(), "UTF-8");
+ } while (i < 10);
+
+ return null;
+ }
+
+ protected void copy(final String str) throws Exception {
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ Clipboard clipboard = new Clipboard(Display.getDefault());
+ TextTransfer transfer = TextTransfer.getInstance();
+ clipboard.setContents(new String[] { str },
+ new Transfer[] { transfer });
+ clipboard.dispose();
+ }
+ });
+ }
+
+ protected static String setUserSettings(String settingsFile) {
+ if (settingsFile != null) {
+ settingsFile = new File(settingsFile).getAbsolutePath();
+ }
+ IMavenConfiguration mavenConfiguration = MavenPlugin.getDefault().getMavenConfiguration();
+ String oldUserSettingsFile = mavenConfiguration.getUserSettingsFile();
+ mavenConfiguration.setUserSettingsFile(settingsFile);
+ return oldUserSettingsFile;
+ }
+
+ protected static String getUserSettings() {
+ IMavenConfiguration mavenConfiguration = MavenPlugin.getDefault().getMavenConfiguration();
+ return mavenConfiguration.getUserSettingsFile();
+ }
+
+ protected static void updateRepositoryRegistry() {
+ try {
+ ((RepositoryRegistry) MavenPlugin.getDefault()
+ .getRepositoryRegistry()).updateRegistry(monitor);
+ } catch (CoreException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ protected static void updateIndex(String repoUrl) {
+ IRepositoryRegistry repositoryRegistry = MavenPlugin.getDefault()
+ .getRepositoryRegistry();
+ for (IRepository repository : repositoryRegistry
+ .getRepositories(IRepositoryRegistry.SCOPE_SETTINGS)) {
+ if (repository.getUrl().equals(repoUrl)) {
+ try {
+ NexusIndexManager indexManager = (NexusIndexManager) MavenPlugin
+ .getDefault().getIndexManager();
+ indexManager.updateIndex(repository, true, monitor);
+ } catch (CoreException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+ }
+
+}
diff --git a/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/UIThreadTask.java b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/UIThreadTask.java
new file mode 100644
index 00000000..e233abbc
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/UIThreadTask.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.integration.tests.common;
+
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Executes a task on the UI thread. Task can return an object to caller, and
+ * any exceptions which occur will be re-thrown in the calling thread.
+ */
+public abstract class UIThreadTask implements Runnable {
+ private Object result = null;
+
+ private Exception exception = null;
+
+ final public void run() {
+ try {
+ result = runEx();
+ } catch (Exception ex) {
+ exception = ex;
+ }
+ }
+
+ public Exception getException() {
+ return exception;
+ }
+
+ public Object getResult() {
+ return result;
+ }
+
+ public abstract Object runEx() throws Exception;
+
+ public static Object executeOnEventQueue(UIThreadTask task)
+ throws Exception {
+ if (Display.getDefault().getThread() == Thread.currentThread()) {
+ task.run();
+ } else {
+ Display.getDefault().syncExec(task);
+ }
+ if (task.getException() != null) {
+ throw task.getException();
+ }
+ return task.getResult();
+ }
+}
diff --git a/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/matchers/ContainsMnemonic.java b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/matchers/ContainsMnemonic.java
new file mode 100644
index 00000000..1f9e82fa
--- /dev/null
+++ b/org.eclipse.m2e.integration.tests.common/src/org/eclipse/m2e/integration/tests/common/matchers/ContainsMnemonic.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.integration.tests.common.matchers;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swtbot.swt.finder.matchers.AbstractMatcher;
+import org.eclipse.swtbot.swt.finder.utils.SWTUtils;
+import org.hamcrest.Description;
+import org.hamcrest.Factory;
+import org.hamcrest.Matcher;
+
+public class ContainsMnemonic<T extends Widget> extends AbstractMatcher<T> {
+ private final String text;
+
+ ContainsMnemonic(String text) {
+ this.text = text;
+ }
+
+ String getText(Object obj) throws NoSuchMethodException,
+ IllegalAccessException, InvocationTargetException {
+ String text = ((String) SWTUtils.invokeMethod(obj, "getText"))
+ .replaceAll(Text.DELIMITER, "\n");
+ return text.replaceAll("&", "").split("\t")[0];
+ }
+
+ public void describeTo(Description description) {
+ description
+ .appendText("contains mnemonic '").appendText(text).appendText("'"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ protected boolean doMatch(Object obj) {
+ try {
+ return getText(obj).contains(text);
+ } catch (Exception e) {
+ // do nothing
+ }
+ return false;
+ }
+
+ @Factory
+ public static <T extends Widget> Matcher<T> containsMnemonic(String text) {
+ return new ContainsMnemonic<T>(text);
+ }
+
+}
diff --git a/org.eclipse.m2e.parent/pom.xml b/org.eclipse.m2e.parent/pom.xml
index 03cf956a..9df3582e 100644
--- a/org.eclipse.m2e.parent/pom.xml
+++ b/org.eclipse.m2e.parent/pom.xml
@@ -88,9 +88,9 @@
<module>../org.eclipse.m2e.editor.xml</module>
<module>../org.eclipse.m2e.editor</module>
- <!-- common test helpers
+ <!-- common test helpers -->
<module>../org.eclipse.m2e.tests.common</module>
- <module>../org.eclipse.m2e.integration.tests.common</module> -->
+ <module>../org.eclipse.m2e.integration.tests.common</module>
<!-- features -->
<module>../org.eclipse.m2e.feature</module>
diff --git a/org.eclipse.m2e.tests.common/.gitignore b/org.eclipse.m2e.tests.common/.gitignore
new file mode 100644
index 00000000..c34d2dd0
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/.gitignore
@@ -0,0 +1,3 @@
+/target
+/bin
+/.classpath
diff --git a/org.eclipse.m2e.tests.common/.project b/org.eclipse.m2e.tests.common/.project
new file mode 100644
index 00000000..1db61db5
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.m2e.tests.common</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.maven.ide.eclipse.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.maven.ide.eclipse.maven2Nature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.m2e.tests.common/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.m2e.tests.common/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000..f11a2c0a
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,359 @@
+#Thu Feb 04 10:56:12 EST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=enabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=enabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled
+org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,HIGH
+org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=2
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=1
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=1
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=2
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=false
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=false
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=120
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=2
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=true
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=2
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/org.eclipse.m2e.tests.common/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.m2e.tests.common/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 00000000..a3d127e5
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,14 @@
+#Tue Nov 30 18:53:25 EST 2010
+eclipse.preferences.version=1
+formatter_profile=_m2 plugin
+formatter_settings_version=11
+org.eclipse.jdt.ui.exception.name=ex
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;org.w3c;org.xml;org.apache;com;junit;org.eclipse;org.codehaus;org.apache.lucene;org.apache.maven;org.sonatype;org.eclipse.m2e;
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=true
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.overrideannotation=false
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return Returns the ${bare_field_name}.\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} The ${bare_field_name} to set.\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/*******************************************************************************&\#13;\n * Copyright (c) 2010 Sonatype, Inc.&\#13;\n * All rights reserved. This program and the accompanying materials&\#13;\n * are made available under the terms of the Eclipse Public License v1.0&\#13;\n * which accompanies this distribution, and is available at&\#13;\n * http\://www.eclipse.org/legal/epl-v10.html&\#13;\n *&\#13;\n * Contributors\:&\#13;\n * Sonatype, Inc. - initial API and implementation&\#13;\n *******************************************************************************/</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * ${type_name}\n *\n * @author ${user}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="false" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="false" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\nMavenLogger.log(${exception_var});</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method ${enclosing_method}\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="filecomment_context" deleted\="false" description\="Comment for created JavaScript files" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\n * \n */</template><template autoinsert\="true" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * @author ${user}\n *\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for vars" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding function" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding functions" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Jsdoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate functions" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="false" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\nMavenLogger.log(${exception_var});</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created function stubs" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated function stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.wst.jsdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
diff --git a/org.eclipse.m2e.tests.common/.settings/org.maven.ide.eclipse.prefs b/org.eclipse.m2e.tests.common/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 00000000..0029eebb
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Tue Nov 16 11:32:19 EST 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/org.eclipse.m2e.tests.common/META-INF/MANIFEST.MF b/org.eclipse.m2e.tests.common/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..ac9dd8f8
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/META-INF/MANIFEST.MF
@@ -0,0 +1,25 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name
+Bundle-SymbolicName: org.eclipse.m2e.tests.common;singleton:=true
+Bundle-Version: 0.13.0.qualifier
+Require-Bundle: org.junit,
+ org.eclipse.m2e.core;bundle-version="[0.13.0,0.14.0)",
+ org.eclipse.m2e.maven.runtime;bundle-version="[0.13.0,0.14.0)",
+ org.eclipse.m2e.jdt;bundle-version="[0.13.0,0.14.0)",
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ org.eclipse.jdt.core,
+ org.eclipse.debug.core,
+ org.eclipse.ui.workbench
+Eclipse-LazyStart: true
+Bundle-RequiredExecutionEnvironment: J2SE-1.5,
+ JavaSE-1.6
+Bundle-ClassPath: .,
+ jars/servlet-api-2.5-20081211.jar,
+ jars/jetty-util-6.1.22.jar,
+ jars/jetty-6.1.22.jar
+Bundle-Vendor: %Bundle-Vendor
+MavenArtifact-GroupId: org.eclipse.m2e
+MavenArtifact-ArtifactId: org.eclipse.m2e.tests.common
+Export-Package: org.eclipse.m2e.tests.common
diff --git a/org.eclipse.m2e.tests.common/OSGI-INF/l10n/bundle.properties b/org.eclipse.m2e.tests.common/OSGI-INF/l10n/bundle.properties
new file mode 100644
index 00000000..a9eef3ec
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/OSGI-INF/l10n/bundle.properties
@@ -0,0 +1,3 @@
+#Properties file for org.eclipse.m2e.tests.common
+Bundle-Vendor = Eclipse m2e
+Bundle-Name = M2E Testing Helpers \ No newline at end of file
diff --git a/org.eclipse.m2e.tests.common/about.html b/org.eclipse.m2e.tests.common/about.html
new file mode 100644
index 00000000..70e4b67c
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>October 29, 2010</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
diff --git a/org.eclipse.m2e.tests.common/build.properties b/org.eclipse.m2e.tests.common/build.properties
new file mode 100644
index 00000000..439b6c4a
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/build.properties
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2008-2010 Sonatype, Inc.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Sonatype, Inc. - initial API and implementation
+#
+
+source.. = src/
+output.. = target/classes/
+bin.includes = META-INF/,\
+ jars/,\
+ .,\
+ about.html,\
+ OSGI-INF/l10n/bundle.properties
diff --git a/org.eclipse.m2e.tests.common/jars/jetty-6.1.22.jar b/org.eclipse.m2e.tests.common/jars/jetty-6.1.22.jar
new file mode 100644
index 00000000..442861c1
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/jars/jetty-6.1.22.jar
Binary files differ
diff --git a/org.eclipse.m2e.tests.common/jars/jetty-util-6.1.22.jar b/org.eclipse.m2e.tests.common/jars/jetty-util-6.1.22.jar
new file mode 100644
index 00000000..7c2aef26
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/jars/jetty-util-6.1.22.jar
Binary files differ
diff --git a/org.eclipse.m2e.tests.common/jars/servlet-api-2.5-20081211.jar b/org.eclipse.m2e.tests.common/jars/servlet-api-2.5-20081211.jar
new file mode 100644
index 00000000..b0537c4d
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/jars/servlet-api-2.5-20081211.jar
Binary files differ
diff --git a/org.eclipse.m2e.tests.common/pom.xml b/org.eclipse.m2e.tests.common/pom.xml
new file mode 100644
index 00000000..11f9096c
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2008 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
+-->
+<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>org.eclipse.m2e.parent</artifactId>
+ <version>0.13.0-SNAPSHOT</version>
+ <relativePath>../org.eclipse.m2e.parent</relativePath>
+ </parent>
+
+ <artifactId>org.eclipse.m2e.tests.common</artifactId>
+ <packaging>eclipse-plugin</packaging>
+
+ <name>M2E Testing Helpers</name>
+
+ <build>
+ <sourceDirectory>src</sourceDirectory>
+ <resources>
+ <resource>
+ <directory>src</directory>
+ <excludes>
+ <exclude>**/*.java</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ </build>
+
+</project>
diff --git a/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/AbstractLifecycleMappingTest.java b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/AbstractLifecycleMappingTest.java
new file mode 100644
index 00000000..62c070d7
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/AbstractLifecycleMappingTest.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.tests.common;
+
+import org.eclipse.core.resources.IProject;
+
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.IProjectConfigurationManager;
+import org.eclipse.m2e.core.project.MavenProjectManager;
+import org.eclipse.m2e.core.project.ResolverConfiguration;
+
+public abstract class AbstractLifecycleMappingTest extends AbstractMavenProjectTestCase {
+ protected MavenProjectManager mavenProjectManager;
+ protected IProjectConfigurationManager projectConfigurationManager;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mavenProjectManager = MavenPlugin.getDefault().getMavenProjectManager();
+ projectConfigurationManager = MavenPlugin.getDefault().getProjectConfigurationManager();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ projectConfigurationManager = null;
+ mavenProjectManager = null;
+
+ super.tearDown();
+ }
+
+ protected IMavenProjectFacade importMavenProject(String basedir, String pomName) throws Exception {
+ ResolverConfiguration configuration = new ResolverConfiguration();
+ IProject[] project = importProjects(basedir, new String[] {pomName}, configuration);
+ waitForJobsToComplete();
+
+ return mavenProjectManager.create(project[0], monitor);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/AbstractMavenProjectTestCase.java b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/AbstractMavenProjectTestCase.java
new file mode 100644
index 00000000..376c1fc8
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/AbstractMavenProjectTestCase.java
@@ -0,0 +1,442 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.tests.common;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceDescription;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.IClasspathContainer;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.repository.ComponentDescriptor;
+import org.codehaus.plexus.util.IOUtil;
+
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.model.Model;
+import org.apache.maven.wagon.Wagon;
+
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.embedder.IMavenConfiguration;
+import org.eclipse.m2e.core.embedder.MavenModelManager;
+import org.eclipse.m2e.core.internal.embedder.MavenImpl;
+import org.eclipse.m2e.core.internal.project.registry.ProjectRegistryRefreshJob;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.IMavenProjectImportResult;
+import org.eclipse.m2e.core.project.MavenProjectInfo;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.m2e.core.project.ResolverConfiguration;
+import org.eclipse.m2e.jdt.BuildPathManager;
+import org.eclipse.m2e.jdt.MavenJdtPlugin;
+
+@SuppressWarnings( "restriction" )
+public abstract class AbstractMavenProjectTestCase extends TestCase {
+
+ public static final int DELETE_RETRY_COUNT = 10;
+ public static final long DELETE_RETRY_DELAY = 6000L;
+
+ protected static final IProgressMonitor monitor = new NullProgressMonitor();
+
+ protected IWorkspace workspace;
+ protected File repo;
+
+ protected ProjectRegistryRefreshJob projectRefreshJob;
+ protected Job downloadSourcesJob;
+
+ protected MavenPlugin plugin;
+
+ protected IMavenConfiguration mavenConfiguration;
+
+ @SuppressWarnings("unchecked")
+ protected void setUp() throws Exception {
+ super.setUp();
+ workspace = ResourcesPlugin.getWorkspace();
+ IWorkspaceDescription description = workspace.getDescription();
+ description.setAutoBuilding(false);
+ workspace.setDescription(description);
+
+ // lets not assume we've got subversion in the target platform
+ Hashtable<String, String> options = JavaCore.getOptions();
+ options.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, ".svn/");
+ JavaCore.setOptions(options);
+
+ plugin = MavenPlugin.getDefault();
+
+ projectRefreshJob = plugin.getProjectManagerRefreshJob();
+ projectRefreshJob.sleep();
+
+ downloadSourcesJob = MavenJdtPlugin.getDefault().getBuildpathManager().getDownloadSourcesJob();
+ downloadSourcesJob.sleep();
+
+ mavenConfiguration = MavenPlugin.getDefault().getMavenConfiguration();
+
+ File settings = new File("settings.xml").getCanonicalFile();
+ if (settings.canRead()) {
+ mavenConfiguration.setUserSettingsFile(settings.getAbsolutePath());
+ }
+
+ ArtifactRepository localRepository = MavenPlugin.getDefault().getMaven().getLocalRepository();
+ if(localRepository != null) {
+ repo = new File(localRepository.getBasedir());
+ } else {
+ fail("Cannot determine local repository path");
+ }
+
+ WorkspaceHelpers.cleanWorkspace();
+ }
+
+ protected void tearDown() throws Exception {
+ try {
+ waitForJobsToComplete();
+ WorkspaceHelpers.cleanWorkspace();
+
+ projectRefreshJob.wakeUp();
+ IWorkspaceDescription description = workspace.getDescription();
+ description.setAutoBuilding(true);
+ workspace.setDescription(description);
+ } finally {
+ super.tearDown();
+ }
+ }
+
+ protected void deleteProject(String projectName) throws CoreException, InterruptedException {
+ IProject project = workspace.getRoot().getProject(projectName);
+
+ deleteProject(project);
+ }
+
+ protected void deleteProject(IProject project) throws InterruptedException, CoreException {
+ Exception cause = null;
+ for (int i = 0; i < DELETE_RETRY_COUNT; i++) {
+ try {
+ doDeleteProject(project);
+ } catch (InterruptedException e) {
+ throw e;
+ } catch (OperationCanceledException e) {
+ throw e;
+ } catch (Exception e) {
+ cause = e;
+ Thread.sleep(DELETE_RETRY_DELAY);
+ continue;
+ }
+
+ // all clear
+ return;
+ }
+
+ // must be a timeout
+ throw new CoreException(new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, "Could not delete project", cause));
+ }
+
+ private void doDeleteProject(final IProject project) throws CoreException, InterruptedException {
+ waitForJobsToComplete(monitor);
+
+ workspace.run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ if(project.exists()) {
+ deleteMember(".classpath", project, monitor);
+ deleteMember(".project", project, monitor);
+ project.delete(false, true, monitor);
+ }
+ }
+
+ private void deleteMember(String name, final IProject project, IProgressMonitor monitor) throws CoreException {
+ IResource member = project.findMember(name);
+ if(member.exists()) {
+ member.delete(true, monitor);
+ }
+ }
+ }, new NullProgressMonitor());
+ }
+
+ protected IProject createProject(String projectName, final String pomResource) throws CoreException {
+ final IProject project = workspace.getRoot().getProject(projectName);
+
+ workspace.run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ project.create(monitor);
+
+ if(!project.isOpen()) {
+ project.open(monitor);
+ }
+
+ IFile pomFile = project.getFile("pom.xml");
+ if(!pomFile.exists()) {
+ InputStream is = null;
+ try {
+ is = new FileInputStream(pomResource);
+ pomFile.create(is, true, monitor);
+ } catch(FileNotFoundException ex) {
+ throw new CoreException(new Status(IStatus.ERROR, "", 0, ex.toString(), ex));
+ } finally {
+ IOUtil.close(is);
+ }
+ }
+ }
+ }, null);
+
+ return project;
+ }
+
+ protected IProject createExisting(String projectName, String projectLocation) throws IOException, CoreException {
+ File dir = new File(workspace.getRoot().getLocation().toFile(), projectName);
+ copyDir(new File(projectLocation), dir);
+
+ final IProject project = workspace.getRoot().getProject(projectName);
+
+ workspace.run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ if (!project.exists()) {
+ IProjectDescription projectDescription = workspace.newProjectDescription(project.getName());
+ projectDescription.setLocation(null);
+ project.create(projectDescription, monitor);
+ project.open(IResource.NONE, monitor);
+ } else {
+ project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
+ }
+ }
+ }, null);
+ return project;
+ }
+
+ /**
+ * Import a test project into the Eclipse workspace
+ *
+ * @param pomLocation - a relative location of the pom file for the project to import
+ * @return created project
+ */
+ protected IProject importProject(String pomLocation) throws IOException, CoreException {
+ return importProject(pomLocation, new ResolverConfiguration());
+ }
+
+ /**
+ * Import a test project into the Eclipse workspace
+ *
+ * @param pomLocation - a relative location of the pom file for the project to import
+ * @param configuration - a resolver configuration to be used to configure imported project
+ * @return created project
+ */
+ protected IProject importProject(String pomLocation, ResolverConfiguration configuration) throws IOException, CoreException {
+ File pomFile = new File(pomLocation);
+ return importProjects(pomFile.getParentFile().getCanonicalPath(), new String[] {pomFile.getName()}, configuration)[0];
+ }
+
+ /**
+ * Import test projects into the Eclipse workspace
+ *
+ * @param basedir - a base directory for all projects to import
+ * @param pomNames - a relative locations of the pom files for the projects to import
+ * @param configuration - a resolver configuration to be used to configure imported projects
+ * @return created projects
+ */
+ protected IProject[] importProjects(String basedir, String[] pomNames, ResolverConfiguration configuration) throws IOException, CoreException {
+ return importProjects(basedir, pomNames, configuration, false);
+ }
+
+ protected IProject[] importProjects(String basedir, String[] pomNames, ResolverConfiguration configuration, boolean skipSanityCheck) throws IOException, CoreException {
+ final MavenPlugin plugin = MavenPlugin.getDefault();
+ MavenModelManager mavenModelManager = plugin.getMavenModelManager();
+ IWorkspaceRoot root = workspace.getRoot();
+
+ File src = new File(basedir);
+ File dst = new File(root.getLocation().toFile(), src.getName());
+ copyDir(src, dst);
+
+ final ArrayList<MavenProjectInfo> projectInfos = new ArrayList<MavenProjectInfo>();
+ for(String pomName : pomNames) {
+ File pomFile = new File(dst, pomName);
+ Model model = mavenModelManager.readMavenModel(pomFile);
+ MavenProjectInfo projectInfo = new MavenProjectInfo(pomName, pomFile, model, null);
+ setBasedirRename(projectInfo);
+ projectInfos.add(projectInfo);
+ }
+
+ final ProjectImportConfiguration importConfiguration = new ProjectImportConfiguration(configuration);
+
+ final ArrayList<IMavenProjectImportResult> importResults = new ArrayList<IMavenProjectImportResult>();
+
+ workspace.run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ importResults.addAll(plugin.getProjectConfigurationManager().importProjects(projectInfos, importConfiguration, monitor));
+ }
+ }, plugin.getProjectConfigurationManager().getRule(), IWorkspace.AVOID_UPDATE, monitor);
+
+ IProject[] projects = new IProject[projectInfos.size()];
+ for (int i = 0; i < projectInfos.size(); i++) {
+ IMavenProjectImportResult importResult = importResults.get(i);
+ assertSame(projectInfos.get(i), importResult.getMavenProjectInfo());
+ projects[i] = importResult.getProject();
+ assertNotNull("Failed to import project " + projectInfos, projects[i]);
+
+ /*
+ * Sanity check: make sure they were all imported
+ */
+ if(!skipSanityCheck) {
+ Model model = projectInfos.get(0).getModel();
+ IMavenProjectFacade facade = plugin.getMavenProjectManager().create(projects[i], monitor);
+ assertNotNull("Project " + model.getGroupId() + "-" + model.getArtifactId() + "-" + model.getVersion()
+ + " was not imported.", facade);
+ }
+ }
+
+ return projects;
+ }
+
+ private void setBasedirRename(MavenProjectInfo projectInfo) throws IOException {
+ File workspaceRoot = workspace.getRoot().getLocation().toFile();
+ File basedir = projectInfo.getPomFile().getParentFile().getCanonicalFile();
+
+ projectInfo.setBasedirRename(basedir.getParentFile().equals(workspaceRoot)? MavenProjectInfo.RENAME_REQUIRED: MavenProjectInfo.RENAME_NO);
+ }
+
+ protected IProject importProject(String projectName, String projectLocation, ResolverConfiguration configuration) throws IOException, CoreException {
+ ProjectImportConfiguration importConfiguration = new ProjectImportConfiguration(configuration);
+ importConfiguration.setProjectNameTemplate(projectName);
+ return importProject(projectName, projectLocation, importConfiguration);
+ }
+
+ protected IProject importProject(String projectName, String projectLocation, final ProjectImportConfiguration importConfiguration) throws IOException, CoreException {
+ File dir = new File(workspace.getRoot().getLocation().toFile(), projectName);
+ copyDir(new File(projectLocation), dir);
+
+ File pomFile = new File(dir, IMavenConstants.POM_FILE_NAME);
+ Model model = MavenPlugin.getDefault().getMavenModelManager().readMavenModel(pomFile);
+ final MavenProjectInfo projectInfo = new MavenProjectInfo(projectName, pomFile, model, null);
+ setBasedirRename(projectInfo);
+
+ final MavenPlugin plugin = MavenPlugin.getDefault();
+
+ workspace.run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ plugin.getProjectConfigurationManager().importProjects(Collections.singleton(projectInfo), importConfiguration, monitor);
+ IProject project = workspace.getRoot().getProject(importConfiguration.getProjectName(projectInfo.getModel()));
+ assertNotNull("Failed to import project " + projectInfo, project);
+ }
+ }, plugin.getProjectConfigurationManager().getRule(), IWorkspace.AVOID_UPDATE, monitor);
+
+ return workspace.getRoot().getProject(projectName);
+ }
+
+ protected void waitForJobsToComplete() throws InterruptedException, CoreException {
+ waitForJobsToComplete(monitor);
+ }
+
+ public static void waitForJobsToComplete(IProgressMonitor monitor) throws InterruptedException, CoreException {
+ JobHelpers.waitForJobsToComplete(monitor);
+ }
+
+ protected IClasspathEntry[] getMavenContainerEntries(IProject project) throws JavaModelException {
+ IJavaProject javaProject = JavaCore.create(project);
+ IClasspathContainer container = BuildPathManager.getMaven2ClasspathContainer(javaProject);
+ return container.getClasspathEntries();
+ }
+
+ protected static String toString(IMarker[] markers) {
+ return WorkspaceHelpers.toString(markers);
+ }
+
+ protected static String toString(List<IMarker> markers) {
+ return WorkspaceHelpers.toString(markers);
+ }
+
+ protected void copyContent(IProject project, String from, String to) throws Exception {
+ copyContent(project, project.getFile(from).getContents(), to);
+ }
+
+ protected void copyContent(IProject project, File from, String to) throws Exception {
+ copyContent(project, new FileInputStream(from), to);
+ }
+
+ /**
+ * closes contents stream
+ */
+ private void copyContent(IProject project, InputStream contents, String to) throws CoreException, IOException,
+ InterruptedException {
+ try {
+ IFile file = project.getFile(to);
+ if (!file.exists()) {
+ file.create(contents, IResource.FORCE, monitor);
+ } else {
+ file.setContents(contents, IResource.FORCE, monitor);
+ }
+ } finally {
+ contents.close();
+ }
+ waitForJobsToComplete();
+ }
+
+ public static void copyDir(File src, File dst) throws IOException {
+ FileHelpers.copyDir(src, dst);
+ }
+
+ public static void copyDir(File src, File dst, FileFilter filter) throws IOException {
+ FileHelpers.copyDir(src, dst, filter);
+ }
+
+ protected static List<IMarker> findErrorMarkers(IProject project) throws CoreException {
+ return WorkspaceHelpers.findErrorMarkers(project);
+ }
+
+ protected static List<IMarker> findMarkers(IProject project, int targetSeverity) throws CoreException {
+ return WorkspaceHelpers.findMarkers(project, targetSeverity);
+ }
+
+ protected static void assertNoErrors(IProject project) throws CoreException {
+ WorkspaceHelpers.assertNoErrors(project);
+ }
+
+ protected void injectFilexWagon() throws Exception {
+ PlexusContainer container = ((MavenImpl) MavenPlugin.getDefault().getMaven()).getPlexusContainer();
+ if(container.getContainerRealm().getResource(FilexWagon.class.getName().replace('.', '/') + ".class") == null) {
+ container.getContainerRealm().importFrom(FilexWagon.class.getClassLoader(), FilexWagon.class.getName());
+ ComponentDescriptor<Wagon> descriptor = new ComponentDescriptor<Wagon>();
+ descriptor.setRealm(container.getContainerRealm());
+ descriptor.setRoleClass(Wagon.class);
+ descriptor.setImplementationClass(FilexWagon.class);
+ descriptor.setRoleHint("filex");
+ descriptor.setInstantiationStrategy("singleton");
+ container.addComponentDescriptor(descriptor);
+ }
+ }
+
+}
diff --git a/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/FileHelpers.java b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/FileHelpers.java
new file mode 100644
index 00000000..16705be9
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/FileHelpers.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.tests.common;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.Map;
+
+import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.IOUtil;
+import org.codehaus.plexus.util.ReaderFactory;
+import org.codehaus.plexus.util.WriterFactory;
+
+
+public class FileHelpers {
+
+ public static void copyDir(File src, File dst) throws IOException {
+ copyDir(src, dst, new FileFilter() {
+ public boolean accept(File pathname) {
+ return !".svn".equals(pathname.getName());
+ }
+ });
+ }
+
+ public static void copyDir(File src, File dst, FileFilter filter) throws IOException {
+ copyDir(src, dst, filter, true);
+ }
+
+ private static void copyDir(File src, File dst, FileFilter filter, boolean deleteDst) throws IOException {
+ if(!src.isDirectory()) {
+ throw new IllegalArgumentException("Not a directory:" + src.getAbsolutePath());
+ }
+ if(deleteDst) {
+ FileUtils.deleteDirectory(dst);
+ }
+ dst.mkdirs();
+ File[] files = src.listFiles(filter);
+ if(files != null) {
+ for(int i = 0; i < files.length; i++ ) {
+ File file = files[i];
+ if(file.canRead()) {
+ File dstChild = new File(dst, file.getName());
+ if(file.isDirectory()) {
+ copyDir(file, dstChild, filter, false);
+ } else {
+ copyFile(file, dstChild);
+ }
+ }
+ }
+ }
+ }
+
+ private static void copyFile(File src, File dst) throws IOException {
+ BufferedInputStream in = new BufferedInputStream(new FileInputStream(src));
+ BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dst));
+
+ byte[] buf = new byte[10240];
+ int len;
+ while((len = in.read(buf)) != -1) {
+ out.write(buf, 0, len);
+ }
+
+ out.close();
+ in.close();
+ }
+
+ public static void filterXmlFile(File src, File dst, Map<String, String> tokens) throws IOException {
+ String text;
+
+ Reader reader = ReaderFactory.newXmlReader(src);
+ try {
+ text = IOUtil.toString(reader);
+ } finally {
+ reader.close();
+ }
+
+ for(String token : tokens.keySet()) {
+ text = text.replace(token, tokens.get(token));
+ }
+
+ dst.getParentFile().mkdirs();
+ Writer writer = WriterFactory.newXmlWriter(dst);
+ try {
+ writer.write(text);
+ } finally {
+ writer.close();
+ }
+ }
+
+ public static boolean deleteDirectory(File directory) {
+ try {
+ FileUtils.deleteDirectory(directory);
+ return true;
+ } catch(IOException e) {
+ return false;
+ }
+ }
+
+}
diff --git a/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/FilexWagon.java b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/FilexWagon.java
new file mode 100644
index 00000000..797d0f79
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/FilexWagon.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.tests.common;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.maven.wagon.ConnectionException;
+import org.apache.maven.wagon.InputData;
+import org.apache.maven.wagon.OutputData;
+import org.apache.maven.wagon.ResourceDoesNotExistException;
+import org.apache.maven.wagon.TransferFailedException;
+import org.apache.maven.wagon.authentication.AuthenticationException;
+import org.apache.maven.wagon.authentication.AuthenticationInfo;
+import org.apache.maven.wagon.providers.file.FileWagon;
+import org.apache.maven.wagon.proxy.ProxyInfoProvider;
+import org.apache.maven.wagon.repository.Repository;
+import org.apache.maven.wagon.resource.Resource;
+
+
+/**
+ * A special wagon for testing that allows to record the requests made to a repository. Use
+ * {@link #setRequestFilterPattern(String, boolean)} to configure what to record and to optionally clear previous
+ * records. The repository URL to use with this wagon looks like {@code filex://localhost/<path-relative-to-project>}.
+ */
+public class FilexWagon extends FileWagon {
+
+ private static List<String> requests = new ArrayList<String>();
+
+ private static String requestFilterPattern;
+
+ public static List<String> getRequests() {
+ return requests;
+ }
+
+ public static void setRequestFilterPattern(String regex, boolean clear) {
+ requestFilterPattern = regex;
+ if(clear) {
+ requests.clear();
+ }
+ }
+
+ public void connect(Repository repository, AuthenticationInfo authenticationInfo, ProxyInfoProvider proxyInfoProvider)
+ throws ConnectionException, AuthenticationException {
+ String basedir = repository.getBasedir();
+ if(basedir != null && basedir.startsWith("/")) {
+ repository.setBasedir(basedir.substring(1));
+ }
+
+ super.connect(repository, authenticationInfo, proxyInfoProvider);
+ }
+
+ public void fillInputData(InputData inputData) throws TransferFailedException, ResourceDoesNotExistException {
+ record("GET", inputData.getResource());
+
+ super.fillInputData(inputData);
+ }
+
+ public void fillOutputData(OutputData outputData) throws TransferFailedException {
+ record("PUT", outputData.getResource());
+
+ super.fillOutputData(outputData);
+ }
+
+ private static void record(String op, Resource resource) {
+ String name = resource.getName();
+ if(requestFilterPattern == null || name.matches(requestFilterPattern)) {
+ requests.add(op + " " + name);
+ }
+ }
+
+}
diff --git a/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/HttpServer.java b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/HttpServer.java
new file mode 100644
index 00000000..e6ba0b52
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/HttpServer.java
@@ -0,0 +1,747 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.tests.common;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.mortbay.jetty.Connector;
+import org.mortbay.jetty.Handler;
+import org.mortbay.jetty.HttpMethods;
+import org.mortbay.jetty.Request;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.handler.AbstractHandler;
+import org.mortbay.jetty.handler.DefaultHandler;
+import org.mortbay.jetty.handler.HandlerList;
+import org.mortbay.jetty.nio.SelectChannelConnector;
+import org.mortbay.jetty.security.B64Code;
+import org.mortbay.jetty.security.Constraint;
+import org.mortbay.jetty.security.ConstraintMapping;
+import org.mortbay.jetty.security.HashUserRealm;
+import org.mortbay.jetty.security.SecurityHandler;
+import org.mortbay.jetty.security.SslSocketConnector;
+import org.mortbay.util.IO;
+import org.mortbay.util.URIUtil;
+
+
+/**
+ * A helper for the tests to start an embedded HTTP server powered by Jetty. Create an instance of this class, use its
+ * mutators to configure the server and finally call {@link #start()}.
+ *
+ * @author Benjamin Bentmann
+ */
+@SuppressWarnings("synthetic-access")
+public class HttpServer {
+
+ private Server server;
+
+ private int httpPort;
+
+ private int httpsPort = -1;
+
+ private String keyStoreLocation = "resources/ssl/keystore";
+
+ private String keyStorePassword;
+
+ private String trustStoreLocation;
+
+ private String trustStorePassword;
+
+ private boolean needClientAuth;
+
+ private String proxyUsername;
+
+ private String proxyPassword;
+
+ private boolean redirectToHttps;
+
+ private long latency;
+
+ private Map<String, String> userPasswords = new HashMap<String, String>();
+
+ private Map<String, String[]> userRoles = new HashMap<String, String[]>();
+
+ private Map<String, String[]> securedRealms = new HashMap<String, String[]>();
+
+ private Map<String, File> resourceDirs = new TreeMap<String, File>(Collections.reverseOrder());
+
+ private Map<String, String[]> resourceFilters = new HashMap<String, String[]>();
+
+ private Map<String, String> filterTokens = new HashMap<String, String>();
+
+ private Collection<String> recordedPatterns = new HashSet<String>();
+
+ private List<String> recordedRequests = new ArrayList<String>();
+
+ private Map<String, Map<String, String>> recordedHeaders = new HashMap<String, Map<String, String>>();
+
+ private String storePassword;
+
+ protected Connector newHttpConnector() {
+ SelectChannelConnector connector = new SelectChannelConnector();
+ connector.setPort(httpPort);
+ return connector;
+ }
+
+ protected Connector newHttpsConnector() {
+ SslSocketConnector connector = new SslSocketConnector();
+ connector.setPort(httpsPort);
+ connector.setKeystore(new File(keyStoreLocation).getAbsolutePath());
+ connector.setPassword(storePassword);
+ connector.setKeyPassword(keyStorePassword);
+ if (trustStoreLocation != null && !trustStoreLocation.equals("")) {
+ connector.setTruststore(new File(trustStoreLocation).getAbsolutePath());
+ }
+ if (trustStorePassword != null && !trustStoreLocation.equals("")) {
+ connector.setTrustPassword(trustStorePassword);
+ }
+ connector.setNeedClientAuth(needClientAuth);
+ return connector;
+ }
+
+ /**
+ * Sets the port to use for HTTP connections.
+ *
+ * @param httpPort The port to use, may be {@code 0} to pick a random port (default), if negative the HTTP connector
+ * will be disabled.
+ * @return This server, never {@code null}.
+ */
+ public HttpServer setHttpPort(int httpPort) {
+ this.httpPort = httpPort;
+
+ return this;
+ }
+
+ /**
+ * Gets the port number of the server's HTTP connector.
+ *
+ * @return The port number of the server's HTTP connector.
+ */
+ public int getHttpPort() {
+ if(httpPort >= 0 && server != null && server.isRunning()) {
+ return server.getConnectors()[0].getLocalPort();
+ }
+ return httpPort;
+ }
+
+ /**
+ * Gets the base URL to the server's HTTP connector, e.g. {@code "http://localhost:8080"}.
+ *
+ * @return The base URL without trailing slash to the server's HTTP connector, never {@code null}.
+ */
+ public String getHttpUrl() {
+ return "http://localhost:" + getHttpPort();
+ }
+
+ /**
+ * Sets the port to use for HTTPS connections.
+ *
+ * @param httpPort The port to use, may be {@code 0} to pick a random port, if negative the HTTPS connector will be
+ * disabled (default).
+ * @return This server, never {@code null}.
+ */
+ public HttpServer setHttpsPort(int httpsPort) {
+ this.httpsPort = httpsPort;
+
+ return this;
+ }
+
+ /**
+ * Gets the port number of the server's HTTPS connector.
+ *
+ * @return The port number of the server's HTTPS connector.
+ */
+ public int getHttpsPort() {
+ if(httpsPort >= 0 && server != null && server.isRunning()) {
+ return server.getConnectors()[(httpPort < 0) ? 0 : 1].getLocalPort();
+ }
+ return httpsPort;
+ }
+
+ /**
+ * Gets the base URL to the server's HTTPS connector, e.g. {@code "https://localhost:8080"}.
+ *
+ * @return The base URL without trailing slash to the server's HTTPS connector, never {@code null}.
+ */
+ public String getHttpsUrl() {
+ return "https://localhost:" + getHttpsPort();
+ }
+
+ /**
+ * Sets the keystore to use for the server certificate on the SSL connector.
+ * Also sets the storePassword value to be password, if it has not been set previously.
+ *
+ * @param path The path to the keystore to use for the server certificate, may be {@code null}.
+ * @param password The password for the keystore, may be {@code null}.
+ * @return This server, never {@code null}.
+ */
+ public HttpServer setKeyStore(String path, String password) {
+ keyStoreLocation = path;
+ keyStorePassword = password;
+ if (storePassword == null) {
+ storePassword = keyStorePassword;
+ }
+ return this;
+ }
+
+ /**
+ * Sets the truststore to use for validating client credentials via the SSL connector.
+ *
+ * @param path The path to the truststore to use for the trusted client certificates, may be {@code null}.
+ * @param password The password for the truststore, may be {@code null}.
+ * @return This server, never {@code null}.
+ */
+ public HttpServer setTrustStore(String path, String password) {
+ trustStoreLocation = path;
+ trustStorePassword = password;
+ return this;
+ }
+
+ /**
+ * Sets the password to use for the SSL connector store.
+ *
+ * @param password The password for the store, may be {@code null}.
+ * @return This server, never {@code null}.
+ */
+ public HttpServer setStorePassword(String password) {
+ this.storePassword = password;
+ return this;
+ }
+
+ /**
+ * Enables/disables client-side certificate authentication.
+ *
+ * @param needClientAuth Whether the server should reject clients whose certificate can't be verified via the
+ * truststore.
+ * @return This server, never {@code null}.
+ */
+ public HttpServer setNeedClientAuth(boolean needClientAuth) {
+ this.needClientAuth = needClientAuth;
+ return this;
+ }
+
+ /**
+ * Sets the credentials to use for proxy authentication. If either username or password is {@code null}, no proxy
+ * authentication is required.
+ *
+ * @param username The username, may be {@code null}.
+ * @param password The password, may be {@code null}.
+ * @return This server, never {@code null}.
+ */
+ public HttpServer setProxyAuth(String username, String password) {
+ this.proxyUsername = username;
+ this.proxyPassword = password;
+
+ return this;
+ }
+
+ protected Handler newProxyHandler() {
+ return new AbstractHandler() {
+ public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch)
+ throws IOException {
+ String auth = request.getHeader("Proxy-Authorization");
+ if(auth != null) {
+ auth = auth.substring(auth.indexOf(' ') + 1).trim();
+ auth = B64Code.decode(auth);
+ }
+
+ if(!(proxyUsername + ':' + proxyPassword).equals(auth)) {
+ response.setStatus(HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED);
+ response.addHeader("Proxy-Authenticate", "Basic realm=\"Squid proxy-caching web server\"");
+ response.getWriter().println("Proxy authentication required");
+
+ ((Request) request).setHandled(true);
+ }
+ }
+ };
+ }
+
+ /**
+ * Enforces redirection from HTTP to HTTPS.
+ *
+ * @param redirectToHttps {@code true} to redirect any HTTP requests to HTTPS, {@code false} to handle HTTP normally.
+ * @return This server, never {@code null}.
+ */
+ public HttpServer setRedirectToHttps(boolean redirectToHttps) {
+ this.redirectToHttps = redirectToHttps;
+
+ return this;
+ }
+
+ protected Handler newSslRedirectHandler() {
+ return new AbstractHandler() {
+
+ public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) {
+ int httpsPort = getHttpsPort();
+ if(!((Request) request).isHandled() && request.getServerPort() != httpsPort) {
+ String url = "https://" + request.getServerName() + ":" + httpsPort + request.getRequestURI();
+
+ response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
+ response.setHeader("Location", url);
+ ((Request) request).setHandled(true);
+ }
+ }
+
+ };
+ }
+
+ /**
+ * Registers a user.
+ *
+ * @param username The username, must not be {@code null}.
+ * @param password The password, must not be {@code null}.
+ * @param roles The roles of the user, may be empty or {@code null}.
+ * @return This server, never {@code null}.
+ */
+ public HttpServer addUser(String username, String password, String... roles) {
+ userPasswords.put(username, password);
+ userRoles.put(username, (roles == null) ? new String[0] : roles);
+
+ return this;
+ }
+
+ /**
+ * Sets up a security realm.
+ *
+ * @param pathSpec The path to secure, e.g. {@code "/files/*"}, must not be {@code null}.
+ * @param roles The roles that have access to the realm, may be empty or {@code null}.
+ * @return This server, never {@code null}.
+ */
+ public HttpServer addSecuredRealm(String pathSpec, String... roles) {
+ securedRealms.put(pathSpec, (roles == null) ? new String[0] : roles);
+
+ return this;
+ }
+
+ protected Handler newSecurityHandler() {
+ List<ConstraintMapping> mappings = new ArrayList<ConstraintMapping>();
+
+ for(String pathSpec : securedRealms.keySet()) {
+ String[] roles = securedRealms.get(pathSpec);
+
+ Constraint constraint = new Constraint();
+ constraint.setName(Constraint.__BASIC_AUTH);
+ constraint.setRoles(roles);
+ constraint.setAuthenticate(true);
+
+ ConstraintMapping constraintMapping = new ConstraintMapping();
+ constraintMapping.setConstraint(constraint);
+ constraintMapping.setPathSpec(pathSpec);
+
+ mappings.add(constraintMapping);
+ }
+
+ HashUserRealm userRealm = new HashUserRealm("TestRealm");
+ for(String username : userPasswords.keySet()) {
+ String password = userPasswords.get(username);
+ String[] roles = userRoles.get(username);
+
+ userRealm.put(username, password);
+ if(roles != null) {
+ for(String role : roles) {
+ userRealm.addUserToRole(username, role);
+ }
+ }
+ }
+
+ SecurityHandler securityHandler = new SecurityHandler();
+ securityHandler.setUserRealm(userRealm);
+ securityHandler.setConstraintMappings(mappings.toArray(new ConstraintMapping[mappings.size()]));
+
+ return securityHandler;
+ }
+
+ /**
+ * Adds resources to the server. Resources can be filtered upon serving using the tokens set via
+ * {@link #setFilterToken(String, String)}. The directory mounted into the server via this method will also be used to
+ * store files sent via PUT. Upon requests, the server will try to match the context roots in reverse alphabetical
+ * order, thereby giving longer path prefix matches precedence.
+ *
+ * @param contextRoot The context root to make the resources accessible at, must not be {@code null}.
+ * @param baseDirectory The local base directory whose files should be served, must not be {@code null}.
+ * @param filteredExtensions A list of extensions for files to filter, e.g. {@code "xml, "properties"}, may be {@code null}.
+ * @return This server, never {@code null}.
+ */
+ public HttpServer addResources(String contextRoot, String baseDirectory, String... filteredExtensions) {
+ contextRoot = normalizeContextRoot(contextRoot);
+
+ File basedir = new File(baseDirectory).getAbsoluteFile();
+
+ resourceDirs.put(contextRoot, basedir);
+ resourceFilters.put(contextRoot, (filteredExtensions == null) ? new String[0] : filteredExtensions);
+
+ return this;
+ }
+
+ /**
+ * Enables request recording for the specified URI patterns. Recorded requests can be retrieved via
+ * {@link #getRecordedRequests()}.
+ *
+ * @param patterns The regular expressions denoting URIs to monitor, e.g. {@code "/context/.*"}, must not be {@code null}.
+ * @return This server, never {@code null}.
+ */
+ public HttpServer enableRecording(String... patterns) {
+ for(String pattern : patterns) {
+ recordedPatterns.add(pattern);
+ }
+
+ return this;
+ }
+
+ /**
+ * Gets the sequence of requests that have been issued against context roots for which
+ * {@link #enableRecording(String...)} was called. A request is encoded in the form {@code <METHOD> <URI>}, e.g.
+ * {@code GET /context/some.jar}.
+ *
+ * @return The sequence of requests since the server was started, can be empty but never {@code null}.
+ */
+ public List<String> getRecordedRequests() {
+ return recordedRequests;
+ }
+
+ /**
+ * Gets the headers sent in the most recent request to the specified path.
+ *
+ * @param uri the path
+ * @return the http request headers
+ */
+ public Map<String, String> getRecordedHeaders(String uri) {
+ return recordedHeaders.get(uri);
+ }
+
+ /**
+ * Sets a token to replace during resource filtering. Upon server start, the following tokens will be defined
+ * automatically: <code>@basedir@</code>, <code>@baseurl@</code>, <code>@baseuri@</code>, <code>@port.http@</code> and
+ * <code>@port.https@</code>.
+ *
+ * @param token The token to replace, e.g. <code>@basedir@</code>, must not be {@code null}.
+ * @param value The replacement text of the token, may be {@code null}.
+ * @return This server, never {@code null}.
+ */
+ public HttpServer setFilterToken(String token, String value) {
+ if(value == null) {
+ filterTokens.remove(token);
+ } else {
+ filterTokens.put(token, value);
+ }
+
+ return this;
+ }
+
+ protected Handler newResourceHandler() {
+ return new ResHandler();
+ }
+
+ /**
+ * Sets the latency of the server.
+ *
+ * @param millis The latency in milliseconds, maybe negative for infinite delay.
+ * @return This server, never {@code null}.
+ */
+ public HttpServer setLatency(long millis) {
+ this.latency = millis;
+ return this;
+ }
+
+ protected Handler newSleepHandler(final long millis) {
+ return new AbstractHandler() {
+
+ public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) {
+ if(millis >= 0) {
+ try {
+ Thread.sleep(millis);
+ } catch(InterruptedException e) {
+ e.printStackTrace();
+ }
+ } else {
+ synchronized(this) {
+ try {
+ wait();
+ } catch(InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ };
+ }
+
+ /**
+ * Starts the server. Trying to start an already running server has no effect.
+ *
+ * @throws Exception If the server could not be started.
+ * @return This server, never {@code null}.
+ */
+ public HttpServer start() throws Exception {
+ if(server != null) {
+ return this;
+ }
+
+ recordedRequests.clear();
+
+ List<Connector> connectors = new ArrayList<Connector>();
+ if(httpPort >= 0) {
+ connectors.add(newHttpConnector());
+ }
+ if(httpsPort >= 0 && keyStoreLocation != null) {
+ connectors.add(newHttpsConnector());
+ }
+
+ HandlerList handlerList = new HandlerList();
+ if(!recordedPatterns.isEmpty()) {
+ handlerList.addHandler(new RecordingHandler());
+ }
+ if(latency != 0) {
+ handlerList.addHandler(newSleepHandler(latency));
+ }
+ if(redirectToHttps) {
+ handlerList.addHandler(newSslRedirectHandler());
+ }
+ if(proxyUsername != null && proxyPassword != null) {
+ handlerList.addHandler(newProxyHandler());
+ }
+ if(!securedRealms.isEmpty()) {
+ handlerList.addHandler(newSecurityHandler());
+ }
+ if(!resourceDirs.isEmpty()) {
+ handlerList.addHandler(newResourceHandler());
+ }
+ handlerList.addHandler(new DefaultHandler());
+
+ server = new Server(0);
+ server.setHandler(handlerList);
+ server.setConnectors(connectors.toArray(new Connector[connectors.size()]));
+ server.start();
+
+ waitForConnectors();
+
+ addDefaultFilterTokens();
+
+ return this;
+ }
+
+ protected void waitForConnectors() throws Exception {
+ // for unknown reasons, the connectors occasionally don't start properly, this tries hard to ensure they are up
+
+ List<Connector> badConnectors = new ArrayList<Connector>(2);
+
+ for(int r = 10; r > 0; r-- ) {
+ // wait some seconds for the connectors to come up
+ for(int i = 200; i > 0; i-- ) {
+ badConnectors.clear();
+ for(Connector connector : server.getConnectors()) {
+ if(connector.getLocalPort() < 0) {
+ badConnectors.add(connector);
+ }
+ }
+ if(badConnectors.isEmpty()) {
+ return;
+ }
+ try {
+ Thread.sleep(15);
+ } catch(InterruptedException e) {
+ return;
+ }
+ }
+
+ // restart the broken connectors and hope they make it this time
+ System.err.println("WARNING: " + badConnectors + " did not start properly, restarting");
+ for(Connector connector : badConnectors) {
+ connector.stop();
+ connector.start();
+ }
+ }
+ }
+
+ protected void addDefaultFilterTokens() {
+ if(!filterTokens.containsKey("@basedir@")) {
+ filterTokens.put("@basedir@", new File("").getAbsolutePath());
+ }
+ if(!filterTokens.containsKey("@baseurl@")) {
+ String baseurl = "file://" + new File("").toURI().getPath();
+ if(baseurl.endsWith("/")) {
+ baseurl = baseurl.substring(0, baseurl.length() - 1);
+ }
+ filterTokens.put("@baseurl@", baseurl);
+ }
+ if(!filterTokens.containsKey("@baseuri@")) {
+ String baseuri = "file://" + new File("").toURI().getRawPath();
+ if(baseuri.endsWith("/")) {
+ baseuri = baseuri.substring(0, baseuri.length() - 1);
+ }
+ filterTokens.put("@baseuri@", baseuri);
+ }
+ if(!filterTokens.containsKey("@port.http@")) {
+ filterTokens.put("@port.http@", Integer.toString(getHttpPort()));
+ }
+ if(!filterTokens.containsKey("@port.https@")) {
+ filterTokens.put("@port.https@", Integer.toString(getHttpsPort()));
+ }
+ }
+
+ /**
+ * Stops the server. Stopping an already stopped server has no effect.
+ */
+ public void stop() {
+ if(server != null) {
+ try {
+ server.stop();
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ server = null;
+ }
+ }
+
+ class ResHandler extends AbstractHandler {
+
+ public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch)
+ throws IOException {
+ String uri = request.getRequestURI();
+
+ for(String contextRoot : resourceDirs.keySet()) {
+ String path = URIUtil.decodePath(trimContextRoot(uri, contextRoot));
+ if(path != null) {
+ File basedir = resourceDirs.get(contextRoot);
+ File file = new File(basedir, path);
+
+ if(HttpMethods.HEAD.equals(request.getMethod())) {
+ if(file.exists())
+ response.setStatus(HttpServletResponse.SC_OK);
+ else
+ response.setStatus(HttpServletResponse.SC_NOT_FOUND);
+ ((Request) request).setHandled(true);
+ return;
+ } else if(HttpMethods.PUT.equals(request.getMethod()) || HttpMethods.POST.equals(request.getMethod())) {
+ file.getParentFile().mkdirs();
+ FileOutputStream os = new FileOutputStream(file);
+ try {
+ IO.copy(request.getInputStream(), os);
+ } finally {
+ os.close();
+ }
+
+ response.setStatus(HttpServletResponse.SC_CREATED);
+ ((Request) request).setHandled(true);
+ } else if(file.isFile()) {
+ FileInputStream is = new FileInputStream(file);
+
+ try {
+ String filterEncoding = getFilterEncoding(path, resourceFilters.get(contextRoot));
+ if(filterEncoding == null) {
+ IO.copy(is, response.getOutputStream());
+ } else {
+ String text = IO.toString(is, filterEncoding);
+ text = filter(text, filterTokens);
+ response.getOutputStream().write(text.getBytes(filterEncoding));
+ }
+ } finally {
+ is.close();
+ }
+
+ response.setStatus(HttpServletResponse.SC_OK);
+ ((Request) request).setHandled(true);
+ }
+
+ break;
+ }
+ }
+
+ }
+
+ private String getExtension(String path) {
+ return path.substring(path.lastIndexOf('.') + 1);
+ }
+
+ private String getFilterEncoding(String path, String[] filteredExtensions) {
+ String ext = getExtension(path);
+ if(filteredExtensions != null) {
+ for(String filteredExtension : filteredExtensions) {
+ if(filteredExtension.startsWith(".")) {
+ filteredExtension = filteredExtension.substring(1);
+ }
+ if(filteredExtension.equalsIgnoreCase(ext)) {
+ return "properties".equalsIgnoreCase(ext) ? "ISO-8859-1" : "UTF-8";
+ }
+ }
+ }
+ return null;
+ }
+
+ private String filter(String str, Map<String, String> tokens) {
+ for(String token : tokens.keySet()) {
+ str = str.replace(token, tokens.get(token));
+ }
+ return str;
+ }
+
+ }
+
+ class RecordingHandler extends AbstractHandler {
+
+ public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) {
+ String uri = request.getRequestURI();
+
+ for(String pattern : recordedPatterns) {
+ if(uri.matches(pattern)) {
+ String req = request.getMethod() + " " + uri;
+ recordedRequests.add(req);
+
+ Map<String, String> headers = new HashMap<String, String>();
+ recordedHeaders.put(uri, headers);
+ for(Enumeration<String> h = request.getHeaderNames(); h.hasMoreElements();) {
+ String headername = h.nextElement();
+ headers.put(headername, request.getHeader(headername));
+ }
+ }
+ }
+ }
+
+ }
+
+ private static String normalizeContextRoot(String contextRoot) {
+ if(contextRoot.endsWith("/")) {
+ contextRoot = contextRoot.substring(0, contextRoot.length() - 1);
+ }
+ if(!contextRoot.startsWith("/")) {
+ contextRoot = "/" + contextRoot;
+ }
+ return contextRoot;
+ }
+
+ private static String trimContextRoot(String uri, String contextRoot) {
+ if(uri.startsWith(contextRoot)) {
+ if(contextRoot.length() == 1) {
+ return uri.substring(1);
+ } else if(uri.length() > contextRoot.length() && uri.charAt(contextRoot.length()) == '/') {
+ return uri.substring(contextRoot.length() + 1);
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/JobHelpers.java b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/JobHelpers.java
new file mode 100644
index 00000000..57fe3f6e
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/JobHelpers.java
@@ -0,0 +1,211 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.tests.common;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.Assert;
+
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.resources.WorkspaceJob;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.jobs.IJobManager;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+
+import org.eclipse.m2e.core.jobs.IBackgroundProcessingQueue;
+
+public class JobHelpers {
+
+ private static final int POLLING_DELAY = 10;
+
+ public static void waitForJobsToComplete() {
+ try {
+ waitForJobsToComplete(new NullProgressMonitor());
+ } catch(Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ public static void waitForJobsToComplete(IProgressMonitor monitor) throws InterruptedException, CoreException {
+ waitForBuildJobs();
+
+ /*
+ * First, make sure refresh job gets all resource change events
+ *
+ * Resource change events are delivered after WorkspaceJob#runInWorkspace returns
+ * and during IWorkspace#run. Each change notification is delivered by
+ * only one thread/job, so we make sure no other workspaceJob is running then
+ * call IWorkspace#run from this thread.
+ *
+ * Unfortunately, this does not catch other jobs and threads that call IWorkspace#run
+ * so we have to hard-code workarounds
+ *
+ * See http://www.eclipse.org/articles/Article-Resource-deltas/resource-deltas.html
+ */
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ IJobManager jobManager = Job.getJobManager();
+ jobManager.suspend();
+ try {
+ Job[] jobs = jobManager.find(null);
+ for (int i = 0; i < jobs.length; i++) {
+ if(jobs[i] instanceof WorkspaceJob || jobs[i].getClass().getName().endsWith("JREUpdateJob")) {
+ jobs[i].join();
+ }
+ }
+ workspace.run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) {
+ }
+ }, workspace.getRoot(), 0, monitor);
+
+ // Now we flush all background processing queues
+ boolean processed = flushProcessingQueues(jobManager, monitor);
+ for (int i = 0; i < 10 && processed; i++) {
+ processed = flushProcessingQueues(jobManager, monitor);
+ }
+
+ Assert.assertFalse("Could not flush background processing queues: " + getProcessingQueues(jobManager), processed);
+ } finally {
+ jobManager.resume();
+ }
+
+ waitForBuildJobs();
+ }
+
+ private static boolean flushProcessingQueues(IJobManager jobManager, IProgressMonitor monitor) throws InterruptedException, CoreException {
+ boolean processed = false;
+ for (IBackgroundProcessingQueue queue : getProcessingQueues(jobManager)) {
+ queue.join();
+ if (!queue.isEmpty()) {
+ IStatus status = queue.run(monitor);
+ if (!status.isOK()) {
+ throw new CoreException(status);
+ }
+ processed = true;
+ }
+ if (queue.isEmpty()) {
+ queue.cancel();
+ }
+ }
+ return processed;
+ }
+
+ private static List<IBackgroundProcessingQueue> getProcessingQueues(IJobManager jobManager) {
+ ArrayList<IBackgroundProcessingQueue> queues = new ArrayList<IBackgroundProcessingQueue>();
+ for (Job job : jobManager.find(null)) {
+ if (job instanceof IBackgroundProcessingQueue) {
+ queues.add((IBackgroundProcessingQueue) job);
+ }
+ }
+ return queues;
+ }
+
+ private static void waitForBuildJobs() {
+ waitForJobs(BuildJobMatcher.INSTANCE, 60 * 1000);
+ }
+
+ public static void waitForJobs(IJobMatcher matcher, int maxWaitMillis) {
+ final long limit = System.currentTimeMillis() + maxWaitMillis;
+ while(true) {
+ Job job = getJob(matcher);
+ if(job == null) {
+ return;
+ }
+ boolean timeout = System.currentTimeMillis() > limit;
+ Assert.assertFalse("Timeout while waiting for completion of job: " + job, timeout);
+ job.wakeUp();
+ try {
+ Thread.sleep(POLLING_DELAY);
+ } catch(InterruptedException e) {
+ // ignore and keep waiting
+ }
+ }
+ }
+
+ private static Job getJob(IJobMatcher matcher) {
+ Job[] jobs = Job.getJobManager().find(null);
+ for(Job job : jobs) {
+ if(matcher.matches(job)) {
+ return job;
+ }
+ }
+ return null;
+ }
+
+ public static void waitForLaunchesToComplete(int maxWaitMillis) {
+ // wait for any jobs that actually start the launch
+ waitForJobs(LaunchJobMatcher.INSTANCE, maxWaitMillis);
+
+ // wait for the launches themselves
+ final long limit = System.currentTimeMillis() + maxWaitMillis;
+ while(true) {
+ ILaunch launch = getActiveLaunch();
+ if(launch == null) {
+ return;
+ }
+ boolean timeout = System.currentTimeMillis() > limit;
+ Assert.assertFalse("Timeout while waiting for completion of launch: " + launch.getLaunchConfiguration(), timeout);
+ try {
+ Thread.sleep(POLLING_DELAY);
+ } catch(InterruptedException e) {
+ // ignore and keep waiting
+ }
+ }
+ }
+
+ private static ILaunch getActiveLaunch() {
+ ILaunch[] launches = DebugPlugin.getDefault().getLaunchManager().getLaunches();
+ if(launches != null) {
+ for(ILaunch launch : launches) {
+ if(!launch.isTerminated()) {
+ return launch;
+ }
+ }
+ }
+ return null;
+ }
+
+ public static interface IJobMatcher {
+
+ boolean matches(Job job);
+
+ }
+
+ static class LaunchJobMatcher implements IJobMatcher {
+
+ public static final IJobMatcher INSTANCE = new LaunchJobMatcher();
+
+ public boolean matches(Job job) {
+ return job.getClass().getName().matches("(.*\\.DebugUIPlugin.*)");
+ }
+
+ }
+
+ static class BuildJobMatcher implements IJobMatcher {
+
+ public static final IJobMatcher INSTANCE = new BuildJobMatcher();
+
+ public boolean matches(Job job) {
+ return (job instanceof WorkspaceJob) || job.getClass().getName().matches("(.*\\.AutoBuild.*)")
+ || job.getClass().getName().endsWith("JREUpdateJob");
+ }
+
+ }
+
+}
diff --git a/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/MavenHelpers.java b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/MavenHelpers.java
new file mode 100644
index 00000000..636c0310
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/MavenHelpers.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.tests.common;
+
+import java.io.File;
+
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.embedder.IMavenConfiguration;
+
+
+public class MavenHelpers {
+
+ public static String setUserSettings(String settingsFile) {
+ if(settingsFile != null && settingsFile.length() > 0) {
+ settingsFile = new File(settingsFile).getAbsolutePath();
+ }
+ IMavenConfiguration mavenConfiguration = MavenPlugin.getDefault().getMavenConfiguration();
+ String oldUserSettingsFile = mavenConfiguration.getUserSettingsFile();
+ mavenConfiguration.setUserSettingsFile(settingsFile);
+ return oldUserSettingsFile;
+ }
+
+ public static String getUserSettings() {
+ IMavenConfiguration mavenConfiguration = MavenPlugin.getDefault().getMavenConfiguration();
+ return mavenConfiguration.getUserSettingsFile();
+ }
+
+}
diff --git a/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/WorkspaceHelpers.java b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/WorkspaceHelpers.java
new file mode 100644
index 00000000..379d1223
--- /dev/null
+++ b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/WorkspaceHelpers.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.tests.common;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import junit.framework.Assert;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+
+import org.codehaus.plexus.util.FileUtils;
+
+import org.eclipse.m2e.core.core.IMavenConstants;
+
+
+public class WorkspaceHelpers {
+
+ public static void cleanWorkspace() throws InterruptedException, CoreException {
+ Exception cause = null;
+ int i;
+ for(i = 0; i < 10; i++ ) {
+ try {
+ System.gc();
+ doCleanWorkspace();
+ } catch(InterruptedException e) {
+ throw e;
+ } catch(OperationCanceledException e) {
+ throw e;
+ } catch(Exception e) {
+ cause = e;
+ e.printStackTrace();
+ System.out.println(i);
+ Thread.sleep(6 * 1000);
+ continue;
+ }
+
+ // all clear
+ return;
+ }
+
+ // must be a timeout
+ throw new CoreException(new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID,
+ "Could not delete workspace resources (after " + i + " retries): "
+ + Arrays.asList(ResourcesPlugin.getWorkspace().getRoot().getProjects()), cause));
+ }
+
+ private static void doCleanWorkspace() throws InterruptedException, CoreException, IOException {
+ final IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ workspace.run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ IProject[] projects = workspace.getRoot().getProjects();
+ for(int i = 0; i < projects.length; i++ ) {
+ projects[i].delete(true, true, monitor);
+ }
+ }
+ }, new NullProgressMonitor());
+
+ JobHelpers.waitForJobsToComplete(new NullProgressMonitor());
+
+ File[] files = workspace.getRoot().getLocation().toFile().listFiles();
+ if(files != null) {
+ for(File file : files) {
+ if(!".metadata".equals(file.getName())) {
+ if(file.isDirectory()) {
+ FileUtils.deleteDirectory(file);
+ } else {
+ if(!file.delete()) {
+ throw new IOException("Could not delete file " + file.getCanonicalPath());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public static String toString(IMarker[] markers) {
+ if (markers != null) {
+ return toString(Arrays.asList(markers));
+ }
+ return "";
+ }
+
+ public static String toString(List<IMarker> markers) {
+ String sep = "";
+ StringBuilder sb = new StringBuilder();
+ if (markers != null) {
+ for(IMarker marker : markers) {
+ try {
+ sb.append(sep).append(toString(marker));
+ } catch(CoreException ex) {
+ // ignore
+ }
+ sep = ", ";
+ }
+ }
+ return sb.toString();
+ }
+
+ protected static String toString(IMarker marker) throws CoreException {
+ return "Type=" + marker.getType() + ":Message=" + marker.getAttribute(IMarker.MESSAGE) + ":LineNumber="
+ + marker.getAttribute(IMarker.LINE_NUMBER);
+ }
+
+ public static List<IMarker> findMarkers(IProject project, int targetSeverity)
+ throws CoreException {
+ return findMarkers(project, targetSeverity, null /*withAttribute*/);
+ }
+
+ public static List<IMarker> findMarkers(IProject project, int targetSeverity, String withAttribute)
+ throws CoreException {
+ SortedMap<IMarker, IMarker> errors = new TreeMap<IMarker, IMarker>(new Comparator<IMarker>() {
+ public int compare(IMarker o1, IMarker o2) {
+ int lineNumber1 = o1.getAttribute(IMarker.LINE_NUMBER, -1);
+ int lineNumber2 = o2.getAttribute(IMarker.LINE_NUMBER, -1);
+ if(lineNumber1 < lineNumber2) {
+ return -1;
+ }
+ if(lineNumber1 > lineNumber2) {
+ return 1;
+ }
+ // Markers on the same line
+ String message1 = o1.getAttribute(IMarker.MESSAGE, "");
+ String message2 = o2.getAttribute(IMarker.MESSAGE, "");
+ return message1.compareTo(message2);
+ }
+ });
+ for(IMarker marker : project.findMarkers(null /* all markers */, true /* subtypes */, IResource.DEPTH_INFINITE)) {
+ int severity = marker.getAttribute(IMarker.SEVERITY, 0);
+ if(severity != targetSeverity) {
+ continue;
+ }
+ if(withAttribute != null) {
+ String attribute = marker.getAttribute(withAttribute, null);
+ if(attribute == null) {
+ continue;
+ }
+ }
+ errors.put(marker, marker);
+ }
+ List<IMarker> result = new ArrayList<IMarker>();
+ result.addAll(errors.keySet());
+ return result;
+ }
+
+ public static List<IMarker> findErrorMarkers(IProject project) throws CoreException {
+ return findMarkers(project, IMarker.SEVERITY_ERROR);
+ }
+
+ public static void assertNoErrors(IProject project) throws CoreException {
+ List<IMarker> markers = findErrorMarkers(project);
+ Assert.assertEquals("Unexpected error markers " + toString(markers), 0, markers.size());
+ }
+
+ public static void assertErrorMarker(String type, String message, Integer lineNumber, IProject project)
+ throws Exception {
+ List<IMarker> errorMarkers = WorkspaceHelpers.findErrorMarkers(project);
+ Assert.assertNotNull(errorMarkers);
+ Assert.assertEquals(WorkspaceHelpers.toString(errorMarkers), 1, errorMarkers.size());
+ assertErrorMarker(type, message, lineNumber, errorMarkers.get(0));
+ }
+
+ public static void assertErrorMarker(String type, String message, Integer lineNumber, IMarker actual)
+ throws Exception {
+ Assert.assertNotNull("Expected not null error marker", actual);
+ String sMarker = toString(actual);
+ Assert.assertEquals(sMarker, type, actual.getType());
+ String actualMessage = actual.getAttribute(IMarker.MESSAGE, "");
+ Assert.assertTrue(sMarker, actualMessage.startsWith(message));
+ if(lineNumber != null) {
+ Assert.assertEquals(sMarker, lineNumber, actual.getAttribute(IMarker.LINE_NUMBER));
+ }
+ if(type != null && type.startsWith(IMavenConstants.MARKER_ID)) {
+ Assert.assertEquals(sMarker, false, actual.getAttribute(IMarker.TRANSIENT));
+ }
+ }
+}

Back to the top