diff options
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 ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). 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, "Program" 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 ("Redistributor") 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 ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). 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, "Program" 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 ("Redistributor") 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 Binary files differnew file mode 100644 index 00000000..442861c1 --- /dev/null +++ b/org.eclipse.m2e.tests.common/jars/jetty-6.1.22.jar 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 Binary files differnew file mode 100644 index 00000000..7c2aef26 --- /dev/null +++ b/org.eclipse.m2e.tests.common/jars/jetty-util-6.1.22.jar 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 Binary files differnew file mode 100644 index 00000000..b0537c4d --- /dev/null +++ b/org.eclipse.m2e.tests.common/jars/servlet-api-2.5-20081211.jar 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)); + } + } +} |