| /******************************************************************************* |
| * Copyright (c) 2008-2014 Sonatype, Inc. and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Sonatype, Inc. - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.m2e.core.ui.internal.wizards; |
| |
| import java.io.File; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Objects; |
| import java.util.TreeSet; |
| |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| 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.Status; |
| import org.eclipse.core.runtime.jobs.IJobChangeEvent; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.core.runtime.jobs.JobChangeAdapter; |
| import org.eclipse.jface.viewers.ComboViewer; |
| import org.eclipse.jface.viewers.IElementComparer; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.IStructuredContentProvider; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.ITableLabelProvider; |
| import org.eclipse.jface.viewers.LabelProvider; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.viewers.TableViewer; |
| import org.eclipse.jface.viewers.Viewer; |
| import org.eclipse.jface.viewers.ViewerComparator; |
| import org.eclipse.jface.viewers.ViewerFilter; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.jface.wizard.IWizardContainer; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.SashForm; |
| import org.eclipse.swt.events.KeyAdapter; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.ModifyEvent; |
| import org.eclipse.swt.events.ModifyListener; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.events.SelectionListener; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Table; |
| import org.eclipse.swt.widgets.TableColumn; |
| import org.eclipse.swt.widgets.Text; |
| import org.eclipse.swt.widgets.ToolBar; |
| import org.eclipse.swt.widgets.ToolItem; |
| import org.eclipse.ui.ISharedImages; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.dialogs.PreferencesUtil; |
| |
| import org.apache.maven.archetype.catalog.Archetype; |
| import org.apache.maven.archetype.catalog.ArchetypeCatalog; |
| import org.apache.maven.artifact.Artifact; |
| import org.apache.maven.artifact.repository.ArtifactRepository; |
| import org.apache.maven.artifact.versioning.ArtifactVersion; |
| import org.apache.maven.artifact.versioning.DefaultArtifactVersion; |
| |
| import org.eclipse.m2e.core.MavenPlugin; |
| import org.eclipse.m2e.core.archetype.ArchetypeUtil; |
| import org.eclipse.m2e.core.embedder.ArtifactKey; |
| import org.eclipse.m2e.core.embedder.IMaven; |
| import org.eclipse.m2e.core.internal.MavenPluginActivator; |
| import org.eclipse.m2e.core.internal.archetype.ArchetypeCatalogFactory; |
| import org.eclipse.m2e.core.internal.archetype.ArchetypeManager; |
| import org.eclipse.m2e.core.internal.index.IMutableIndex; |
| import org.eclipse.m2e.core.internal.index.IndexListener; |
| import org.eclipse.m2e.core.internal.index.IndexManager; |
| import org.eclipse.m2e.core.project.ProjectImportConfiguration; |
| import org.eclipse.m2e.core.repository.IRepository; |
| import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator; |
| import org.eclipse.m2e.core.ui.internal.Messages; |
| import org.eclipse.m2e.core.ui.internal.util.M2EUIUtils; |
| |
| |
| /** |
| * Maven Archetype selection wizard page presents the user with a list of available Maven Archetypes available for |
| * creating new project. |
| */ |
| public class MavenProjectWizardArchetypePage extends AbstractMavenWizardPage implements IndexListener { |
| private static final Logger log = LoggerFactory.getLogger(MavenProjectWizardArchetypePage.class); |
| |
| private static final String KEY_CATALOG = "catalog"; //$NON-NLS-1$ |
| |
| private static final String ALL_CATALOGS = org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_all; |
| |
| public static final Comparator<Archetype> ARCHETYPE_COMPARATOR = (a1, a2) -> { |
| String g1 = a1.getGroupId(); |
| String g2 = a2.getGroupId(); |
| int res = g1.compareTo(g2); |
| if(res != 0) { |
| return res; |
| } |
| |
| String i1 = a1.getArtifactId(); |
| String i2 = a2.getArtifactId(); |
| res = i1.compareTo(i2); |
| if(res != 0) { |
| return res; |
| } |
| |
| String v1 = a1.getVersion(); |
| String v2 = a2.getVersion(); |
| if(v1 == null) { |
| return v2 == null ? 0 : -1; |
| } |
| return v1.compareTo(v2); |
| }; |
| |
| private static final boolean DEFAULT_SHOW_LAST_VERSION = true; |
| |
| private static final boolean DEFAULT_INCLUDE_SNAPSHOTS = false; |
| |
| private Map<String, List<Archetype>> archetypesCache = new HashMap<>(); |
| |
| ComboViewer catalogsComboViewer; |
| |
| Text filterText; |
| |
| /** the archetype table viewer */ |
| TableViewer viewer; |
| |
| /** the description value label */ |
| Text descriptionText; |
| |
| Button showLastVersionButton; |
| |
| Button includeShapshotsButton; |
| |
| Button addArchetypeButton; |
| |
| /** the list of available archetypes */ |
| volatile Collection<Archetype> archetypes; |
| |
| /** |
| * Archetype key to known archetype versions map. Versions are sorted in newest-to-oldest order. |
| */ |
| Map<String, List<ArtifactVersion>> archetypeVersions; |
| |
| /** a flag indicating if the archetype selection is actually used in the wizard */ |
| private boolean isUsed = true; |
| |
| ArchetypeCatalogFactory catalogFactory = null; |
| |
| private RetrievingArchetypesJob job; |
| |
| /** |
| * Default constructor. Sets the title and description of this wizard page and marks it as not being complete as user |
| * input is required for continuing. |
| */ |
| public MavenProjectWizardArchetypePage(ProjectImportConfiguration projectImportConfiguration) { |
| super("MavenProjectWizardArchetypePage", projectImportConfiguration); //$NON-NLS-1$ |
| setTitle(Messages.wizardProjectPageArchetypeTitle); |
| setDescription(Messages.wizardProjectPageArchetypeDescription); |
| setPageComplete(false); |
| } |
| |
| /** Creates the page controls. */ |
| public void createControl(Composite parent) { |
| archetypesCache.clear(); |
| Composite composite = new Composite(parent, SWT.NONE); |
| composite.setLayout(new GridLayout(3, false)); |
| |
| createViewer(composite); |
| |
| createAdvancedSettings(composite, new GridData(SWT.FILL, SWT.TOP, true, false, 3, 1)); |
| |
| MavenPlugin.getIndexManager().addIndexListener(this); |
| setControl(composite); |
| } |
| |
| /** Creates the archetype table viewer. */ |
| @SuppressWarnings({"unchecked", "rawtypes"}) |
| private void createViewer(Composite parent) { |
| Label catalogsLabel = new Label(parent, SWT.NONE); |
| catalogsLabel.setText(org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_lblCatalog); |
| |
| Composite catalogsComposite = new Composite(parent, SWT.NONE); |
| GridLayout catalogsCompositeLayout = new GridLayout(); |
| catalogsCompositeLayout.marginWidth = 0; |
| catalogsCompositeLayout.marginHeight = 0; |
| catalogsCompositeLayout.numColumns = 2; |
| catalogsComposite.setLayout(catalogsCompositeLayout); |
| catalogsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1)); |
| |
| catalogsComboViewer = new ComboViewer(catalogsComposite); |
| catalogsComboViewer.getControl().setData("name", "catalogsCombo"); //$NON-NLS-1$ //$NON-NLS-2$ |
| catalogsComboViewer.getCombo().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| catalogsComboViewer.setContentProvider(new IStructuredContentProvider() { |
| public Object[] getElements(Object input) { |
| |
| if(input instanceof Collection) { |
| return ((Collection<?>) input).toArray(); |
| } |
| return new Object[0]; |
| } |
| |
| public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { |
| } |
| |
| public void dispose() { |
| } |
| }); |
| |
| catalogsComboViewer.setLabelProvider(new LabelProvider() { |
| public String getText(Object element) { |
| if(element instanceof ArchetypeCatalogFactory) { |
| return ((ArchetypeCatalogFactory) element).getDescription(); |
| } else if(element instanceof String) { |
| return element.toString(); |
| } |
| return super.getText(element); |
| } |
| }); |
| |
| catalogsComboViewer.addSelectionChangedListener(event -> { |
| ISelection selection = event.getSelection(); |
| boolean loadAll = false; |
| //hide previous archetypes when switching catalog |
| if(selection instanceof IStructuredSelection) { |
| Object factory = ((IStructuredSelection) selection).getFirstElement(); |
| ArchetypeCatalogFactory newCatalogFactory = null; |
| if(factory instanceof ArchetypeCatalogFactory) { |
| newCatalogFactory = (ArchetypeCatalogFactory) factory; |
| } |
| if(factory != null && newCatalogFactory == null) { |
| loadAll = true; |
| } else if(Objects.equals(catalogFactory, newCatalogFactory) && viewer.getInput() != null) { |
| return; |
| } |
| catalogFactory = newCatalogFactory; |
| viewer.setInput(null); |
| reloadViewer(); |
| } else { |
| loadAll = true; |
| } |
| if(loadAll) { |
| catalogFactory = null; |
| viewer.setInput(null); |
| loadArchetypes(null, null, null); |
| } |
| //remember what was switched to here |
| if(dialogSettings != null) { |
| if(catalogFactory != null) |
| dialogSettings.put(KEY_CATALOG, catalogFactory.getId()); |
| else |
| dialogSettings.put(KEY_CATALOG, ALL_CATALOGS); |
| } |
| }); |
| |
| final ArchetypeManager archetypeManager = MavenPluginActivator.getDefault().getArchetypeManager(); |
| ArrayList allCatalogs = new ArrayList(archetypeManager.getActiveArchetypeCatalogs()); |
| allCatalogs.add(0, ALL_CATALOGS); |
| catalogsComboViewer.setInput(allCatalogs); |
| |
| Button configureButton = new Button(catalogsComposite, SWT.NONE); |
| configureButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); |
| configureButton.setText(org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_btnConfigure); |
| configureButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> { |
| |
| Collection<ArchetypeCatalogFactory> oldCatalogs = archetypeManager.getActiveArchetypeCatalogs(); |
| |
| PreferencesUtil.createPreferenceDialogOn(getShell(), |
| "org.eclipse.m2e.core.preferences.MavenArchetypesPreferencePage", null, null).open(); //$NON-NLS-1$ |
| |
| Collection<ArchetypeCatalogFactory> newCatalogs = archetypeManager.getActiveArchetypeCatalogs(); |
| |
| //Deselect removed catalog if needed |
| if(catalogFactory != null && !newCatalogs.contains(catalogFactory)) { |
| catalogFactory = null; |
| } |
| |
| //Select 1st new catalog |
| ArchetypeCatalogFactory selectedCatalog = catalogFactory; |
| for(ArchetypeCatalogFactory newCatalog : newCatalogs) { |
| if(!oldCatalogs.contains(newCatalog)) { |
| selectedCatalog = newCatalog; |
| break; |
| } |
| } |
| |
| ArrayList allCatalogs1 = new ArrayList(newCatalogs); |
| allCatalogs1.add(0, ALL_CATALOGS); |
| catalogsComboViewer.setInput(allCatalogs1); |
| catalogsComboViewer |
| .setSelection(new StructuredSelection(selectedCatalog == null ? ALL_CATALOGS : selectedCatalog)); |
| |
| })); |
| |
| Label filterLabel = new Label(parent, SWT.NONE); |
| filterLabel.setLayoutData(new GridData()); |
| filterLabel.setText(org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_lblFilter); |
| |
| QuickViewerFilter quickViewerFilter = new QuickViewerFilter(); |
| VersionsFilter versionFilter = new VersionsFilter(DEFAULT_SHOW_LAST_VERSION, DEFAULT_INCLUDE_SNAPSHOTS); |
| |
| filterText = new Text(parent, SWT.BORDER | SWT.SEARCH); |
| filterText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| filterText.addModifyListener(quickViewerFilter); |
| filterText.addKeyListener(new KeyAdapter() { |
| public void keyPressed(KeyEvent e) { |
| if(e.keyCode == SWT.ARROW_DOWN) { |
| viewer.getTable().setFocus(); |
| viewer.getTable().setSelection(0); |
| |
| viewer.setSelection(new StructuredSelection(viewer.getElementAt(0)), true); |
| } |
| } |
| }); |
| |
| ToolBar toolBar = new ToolBar(parent, SWT.FLAT); |
| toolBar.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); |
| |
| final ToolItem clearToolItem = new ToolItem(toolBar, SWT.PUSH); |
| clearToolItem.setEnabled(false); |
| clearToolItem.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_ELCL_REMOVE)); |
| clearToolItem |
| .setDisabledImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_ELCL_REMOVE_DISABLED)); |
| clearToolItem.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> { |
| filterText.setText(""); //$NON-NLS-1$ |
| })); |
| |
| filterText.addModifyListener(e -> clearToolItem.setEnabled(filterText.getText().length() > 0)); |
| |
| SashForm sashForm = new SashForm(parent, SWT.VERTICAL); |
| GridData gd_sashForm = new GridData(SWT.FILL, SWT.FILL, false, true, 3, 1); |
| // gd_sashForm.widthHint = 500; |
| gd_sashForm.heightHint = 200; |
| sashForm.setLayoutData(gd_sashForm); |
| sashForm.setLayout(new GridLayout()); |
| |
| Composite composite1 = new Composite(sashForm, SWT.NONE); |
| GridLayout gridLayout1 = new GridLayout(); |
| gridLayout1.horizontalSpacing = 0; |
| gridLayout1.marginWidth = 0; |
| gridLayout1.marginHeight = 0; |
| composite1.setLayout(gridLayout1); |
| |
| viewer = new TableViewer(composite1, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION); |
| Table table = viewer.getTable(); |
| table.setData("name", "archetypesTable"); //$NON-NLS-1$ //$NON-NLS-2$ |
| table.setHeaderVisible(true); |
| |
| TableColumn column1 = new TableColumn(table, SWT.LEFT); |
| column1.setWidth(150); |
| column1.setText(Messages.wizardProjectPageArchetypeColumnGroupId); |
| |
| TableColumn column0 = new TableColumn(table, SWT.LEFT); |
| column0.setWidth(150); |
| column0.setText(Messages.wizardProjectPageArchetypeColumnArtifactId); |
| |
| TableColumn column2 = new TableColumn(table, SWT.LEFT); |
| column2.setWidth(100); |
| column2.setText(Messages.wizardProjectPageArchetypeColumnVersion); |
| |
| GridData tableData = new GridData(SWT.FILL, SWT.FILL, true, true); |
| tableData.widthHint = 400; |
| tableData.heightHint = 200; |
| table.setLayoutData(tableData); |
| |
| viewer.setLabelProvider(new ArchetypeLabelProvider()); |
| |
| viewer.setComparator(new ViewerComparator() { |
| public int compare(Viewer viewer, Object e1, Object e2) { |
| return ARCHETYPE_COMPARATOR.compare((Archetype) e1, (Archetype) e2); |
| } |
| }); |
| |
| viewer.setComparer(new IElementComparer() { |
| public int hashCode(Object obj) { |
| if(obj instanceof Archetype) { |
| return ArchetypeUtil.getHashCode((Archetype) obj); |
| } |
| return obj.hashCode(); |
| } |
| |
| public boolean equals(Object one, Object another) { |
| if(one instanceof Archetype && another instanceof Archetype) { |
| return ArchetypeUtil.areEqual((Archetype) one, (Archetype) another); |
| } |
| return one.equals(another); |
| } |
| }); |
| |
| viewer.setFilters(new ViewerFilter[] {versionFilter, quickViewerFilter}); |
| |
| viewer.setContentProvider(new IStructuredContentProvider() { |
| public Object[] getElements(Object inputElement) { |
| if(inputElement instanceof Collection) { |
| return ((Collection<?>) inputElement).toArray(); |
| } |
| return new Object[0]; |
| } |
| |
| public void dispose() { |
| } |
| |
| public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { |
| } |
| }); |
| |
| viewer.addSelectionChangedListener(event -> { |
| Archetype archetype = getArchetype(); |
| if(archetype != null) { |
| String repositoryUrl = archetype.getRepository(); |
| String description = archetype.getDescription(); |
| |
| String text = description == null ? "" : description; //$NON-NLS-1$ |
| text = text.replaceAll("\n", "").replaceAll("\\s{2,}", " "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
| |
| if(repositoryUrl != null) { |
| text += text.length() > 0 ? "\n" + repositoryUrl : repositoryUrl; //$NON-NLS-1$ |
| } |
| |
| descriptionText.setText(text); |
| setPageComplete(true); |
| } else { |
| descriptionText.setText(""); //$NON-NLS-1$ |
| setPageComplete(false); |
| } |
| }); |
| |
| viewer.addOpenListener(openevent -> { |
| if(canFlipToNextPage()) { |
| getContainer().showPage(getNextPage()); |
| } |
| }); |
| |
| Composite composite2 = new Composite(sashForm, SWT.NONE); |
| GridLayout gridLayout2 = new GridLayout(); |
| gridLayout2.marginHeight = 0; |
| gridLayout2.marginWidth = 0; |
| gridLayout2.horizontalSpacing = 0; |
| composite2.setLayout(gridLayout2); |
| |
| descriptionText = new Text(composite2, SWT.WRAP | SWT.V_SCROLL | SWT.READ_ONLY | SWT.MULTI | SWT.BORDER); |
| |
| GridData descriptionTextData = new GridData(SWT.FILL, SWT.FILL, true, true); |
| descriptionTextData.heightHint = 40; |
| descriptionText.setLayoutData(descriptionTextData); |
| //whole dialog resizes badly without the width hint to the desc text |
| descriptionTextData.widthHint = 250; |
| sashForm.setWeights(new int[] {80, 20}); |
| |
| Composite buttonComposite = new Composite(parent, SWT.NONE); |
| GridData gd_buttonComposite = new GridData(SWT.FILL, SWT.CENTER, false, false, 3, 1); |
| buttonComposite.setLayoutData(gd_buttonComposite); |
| GridLayout gridLayout = new GridLayout(); |
| gridLayout.marginHeight = 0; |
| gridLayout.marginWidth = 0; |
| gridLayout.numColumns = 3; |
| buttonComposite.setLayout(gridLayout); |
| |
| showLastVersionButton = new Button(buttonComposite, SWT.CHECK); |
| showLastVersionButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false)); |
| showLastVersionButton.setText(org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_btnLast); |
| showLastVersionButton.setSelection(DEFAULT_SHOW_LAST_VERSION); |
| showLastVersionButton.addSelectionListener(versionFilter); |
| |
| includeShapshotsButton = new Button(buttonComposite, SWT.CHECK); |
| GridData buttonData = new GridData(SWT.LEFT, SWT.CENTER, true, false); |
| buttonData.horizontalIndent = 25; |
| includeShapshotsButton.setLayoutData(buttonData); |
| includeShapshotsButton |
| .setText(org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_btnSnapshots); |
| includeShapshotsButton.setSelection(DEFAULT_INCLUDE_SNAPSHOTS); |
| includeShapshotsButton.addSelectionListener(versionFilter); |
| |
| addArchetypeButton = new Button(buttonComposite, SWT.NONE); |
| addArchetypeButton.setText(org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_btnAdd); |
| addArchetypeButton.setData("name", "addArchetypeButton"); //$NON-NLS-1$ //$NON-NLS-2$ |
| buttonData = new GridData(SWT.RIGHT, SWT.CENTER, true, false); |
| buttonData.horizontalIndent = 35; |
| addArchetypeButton.setLayoutData(buttonData); |
| |
| addArchetypeButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> { |
| CustomArchetypeDialog dialog = new CustomArchetypeDialog(getShell(), |
| org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_add_title); |
| if(dialog.open() == Window.OK) { |
| String archetypeGroupId = dialog.getArchetypeGroupId(); |
| String archetypeArtifactId = dialog.getArchetypeArtifactId(); |
| String archetypeVersion = dialog.getArchetypeVersion(); |
| String repositoryUrl = dialog.getRepositoryUrl(); |
| downloadArchetype(archetypeGroupId, archetypeArtifactId, archetypeVersion, repositoryUrl); |
| } |
| })); |
| } |
| |
| protected IWizardContainer getContainer() { |
| return super.getContainer(); |
| } |
| |
| public void addArchetypeSelectionListener(ISelectionChangedListener listener) { |
| viewer.addSelectionChangedListener(listener); |
| } |
| |
| public void dispose() { |
| if(job != null) { |
| job.cancel(); |
| job = null; |
| } |
| MavenPlugin.getIndexManager().removeIndexListener(this); |
| archetypesCache.clear(); |
| super.dispose(); |
| } |
| |
| public List<Archetype> getArchetypesForCatalog() { |
| try { |
| return getArchetypesForCatalog(catalogFactory, null); |
| } catch(CoreException ce) { |
| setErrorMessage(org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_error_read); |
| return null; |
| } |
| } |
| |
| public List<Archetype> getArchetypesForCatalog(ArchetypeCatalogFactory archCatalogFactory, IProgressMonitor monitor) |
| throws CoreException { |
| if(archCatalogFactory == null) { |
| return getAllArchetypes(monitor); |
| } |
| String catalogId = archCatalogFactory.getId(); |
| List<Archetype> archs = archetypesCache.get(catalogId); |
| if(archs == null) { |
| archs = archCatalogFactory.getArchetypeCatalog().getArchetypes(); |
| if(archs == null) { |
| archs = Collections.emptyList(); |
| } |
| archetypesCache.put(catalogId, archs); |
| } |
| return archs; |
| } |
| |
| @SuppressWarnings("unchecked") |
| private List<Archetype> getAllArchetypes(IProgressMonitor monitor) { |
| ArchetypeManager manager = MavenPluginActivator.getDefault().getArchetypeManager(); |
| Collection<ArchetypeCatalogFactory> archetypeCatalogs = manager.getActiveArchetypeCatalogs(); |
| |
| ArrayList<Archetype> list = new ArrayList<>(); |
| |
| if(monitor == null) { |
| monitor = new NullProgressMonitor(); |
| } |
| |
| for(ArchetypeCatalogFactory catalog : archetypeCatalogs) { |
| if(monitor.isCanceled()) { |
| return Collections.emptyList(); |
| } |
| try { |
| //temporary hack to get around 'Test Remote Catalog' blowing up on download |
| //described in https://issues.sonatype.org/browse/MNGECLIPSE-1792 |
| if(catalog.getDescription().startsWith("Test")) { //$NON-NLS-1$ |
| continue; |
| } |
| @SuppressWarnings("rawtypes") |
| List arcs = getArchetypesForCatalog(catalog, monitor); |
| if(arcs != null) { |
| list.addAll(arcs); |
| } |
| } catch(Exception ce) { |
| log.error("Unable to read archetype catalog: " + catalog.getId(), ce); //$NON-NLS-1$ |
| } |
| } |
| return list; |
| } |
| |
| /** Loads the available archetypes. */ |
| void loadArchetypes(final String groupId, final String artifactId, final String version) { |
| if(job != null) { |
| job.cancel(); |
| } |
| job = new RetrievingArchetypesJob(catalogFactory); |
| job.addJobChangeListener(new JobChangeAdapter() { |
| public void done(IJobChangeEvent event) { |
| |
| final RetrievingArchetypesJob thisJob = (RetrievingArchetypesJob) event.getJob(); |
| if(IStatus.CANCEL == event.getResult().getSeverity() || !isCurrentPage()) { |
| return; |
| } |
| List<Archetype> catalogArchetypes = thisJob.catalogArchetypes; |
| |
| final String error; |
| if(IStatus.ERROR == event.getResult().getSeverity()) { |
| error = event.getResult().getMessage(); |
| } else if((catalogArchetypes == null || catalogArchetypes.isEmpty())) { |
| ArchetypeManager archetypeManager = MavenPluginActivator.getDefault().getArchetypeManager(); |
| Collection<ArchetypeCatalogFactory> catalogs = archetypeManager.getActiveArchetypeCatalogs(); |
| if(catalogs.isEmpty()) { |
| error = Messages.MavenProjectWizardArchetypePage_error_noEnabledCatalogs; |
| } else if(catalogFactory != null && "Nexus Indexer".equals(catalogFactory.getDescription())) { //$NON-NLS-1$ |
| error = Messages.MavenProjectWizardArchetypePage_error_emptyNexusIndexer; |
| } else { |
| error = Messages.MavenProjectWizardArchetypePage_error_emptyCatalog; |
| } |
| } else { |
| error = null; |
| } |
| |
| Display.getDefault().asyncExec(() -> setErrorMessage(error)); |
| TreeSet<Archetype> archs = new TreeSet<Archetype>(ARCHETYPE_COMPARATOR); |
| if(catalogArchetypes != null) { |
| archs.addAll(catalogArchetypes); |
| } |
| archetypes = archs; |
| |
| Display.getDefault().asyncExec(() -> updateViewer(groupId, artifactId, version)); |
| } |
| }); |
| job.schedule(); |
| } |
| |
| private static String getArchetypeKey(Archetype archetype) { |
| return new StringBuilder(archetype.getGroupId()).append(":").append(archetype.getArtifactId()).toString(); //$NON-NLS-1$ |
| } |
| |
| ArchetypeCatalog getArchetypeCatalog() throws CoreException { |
| return catalogFactory == null ? null : catalogFactory.getArchetypeCatalog(); |
| } |
| |
| /** Sets the flag that the archetype selection is used in the wizard. */ |
| public void setUsed(boolean isUsed) { |
| this.isUsed = isUsed; |
| } |
| |
| /** Overrides the default to return "true" if the page is not used. */ |
| public boolean isPageComplete() { |
| return !isUsed || super.isPageComplete(); |
| } |
| |
| /** Sets the focus to the table component. */ |
| public void setVisible(boolean visible) { |
| super.setVisible(visible); |
| |
| if(visible) { |
| ArchetypeManager archetypeManager = MavenPluginActivator.getDefault().getArchetypeManager(); |
| String catalogId = dialogSettings.get(KEY_CATALOG); |
| catalogFactory = null; |
| if(catalogId != null && !catalogId.equals(ALL_CATALOGS)) { |
| catalogFactory = archetypeManager.getArchetypeCatalogFactory(catalogId); |
| } |
| if(catalogsComboViewer.getSelection().isEmpty()) { |
| catalogsComboViewer |
| .setSelection(new StructuredSelection(catalogFactory == null ? ALL_CATALOGS : catalogFactory)); |
| } |
| |
| viewer.getTable().setFocus(); |
| Archetype selected = getArchetype(); |
| if(selected != null) { |
| viewer.reveal(selected); |
| } |
| } else { |
| if(job != null) { |
| job.cancel(); |
| job = null; |
| } |
| } |
| } |
| |
| /** Returns the selected archetype. */ |
| public Archetype getArchetype() { |
| return (Archetype) ((IStructuredSelection) viewer.getSelection()).getFirstElement(); |
| } |
| |
| void updateViewer(String groupId, String artifactId, String version) { |
| if(viewer.getControl().isDisposed()) { |
| return; |
| } |
| |
| archetypeVersions = getArchetypeVersions(archetypes); |
| |
| viewer.setInput(archetypes); |
| |
| if(isCurrentPage()) { |
| selectArchetype(groupId, artifactId, version); |
| } |
| |
| Table table = viewer.getTable(); |
| int columnCount = table.getColumnCount(); |
| int width = 0; |
| for(int i = 0; i < columnCount; i++ ) { |
| TableColumn column = table.getColumn(i); |
| column.pack(); |
| width += column.getWidth(); |
| } |
| GridData tableData = (GridData) table.getLayoutData(); |
| int oldHint = tableData.widthHint; |
| if(width > oldHint) { |
| tableData.widthHint = width; |
| } |
| getShell().pack(true); |
| tableData.widthHint = oldHint; |
| } |
| |
| private static Map<String, List<ArtifactVersion>> getArchetypeVersions(Collection<Archetype> archetypes) { |
| HashMap<String, List<ArtifactVersion>> archetypeVersions = new HashMap<>(archetypes.size()); |
| |
| HashMap<String, ArtifactVersion> versionFactory = new HashMap<>(); |
| |
| for(Archetype currentArchetype : archetypes) { |
| String version = currentArchetype.getVersion(); |
| if(M2EUIUtils.nullOrEmpty(version)) { |
| // we don't know how to handle null/empty versions |
| continue; |
| } |
| String key = getArchetypeKey(currentArchetype); |
| |
| List<ArtifactVersion> versions = archetypeVersions.get(key); |
| if(versions == null) { |
| versions = new ArrayList<ArtifactVersion>(); |
| archetypeVersions.put(key, versions); |
| } |
| ArtifactVersion v = versionFactory.get(version); |
| if(v == null) { |
| v = new DefaultArtifactVersion(version); |
| versionFactory.put(version, v); |
| } |
| versions.add(v); |
| } |
| |
| final Comparator<ArtifactVersion> comparator = (v1, v2) -> v2.compareTo(v1); |
| |
| for(List<ArtifactVersion> versions : archetypeVersions.values()) { |
| Collections.sort(versions, comparator); |
| } |
| return archetypeVersions; |
| } |
| |
| protected void selectArchetype(String groupId, String artifactId, String version) { |
| Archetype archetype = findArchetype(groupId, artifactId, version); |
| |
| Table table = viewer.getTable(); |
| if(archetype != null) { |
| viewer.setSelection(new StructuredSelection(archetype), true); |
| |
| int n = table.getSelectionIndex(); |
| table.setSelection(n); |
| } |
| } |
| |
| /** Locates an archetype with given ids. */ |
| protected Archetype findArchetype(String groupId, String artifactId, String version) { |
| for(Archetype archetype : archetypes) { |
| if(archetype.getGroupId().equals(groupId) && archetype.getArtifactId().equals(artifactId)) { |
| if(version == null || version.equals(archetype.getVersion())) { |
| return archetype; |
| } |
| } |
| } |
| |
| return version == null ? null : findArchetype(groupId, artifactId, null); |
| } |
| |
| protected void downloadArchetype(final String archetypeGroupId, final String archetypeArtifactId, |
| final String archetypeVersion, final String repositoryUrl) { |
| if(getContainer() == null) { |
| return;//page has been disposed |
| } |
| final String archetypeName = archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion; //$NON-NLS-1$ //$NON-NLS-2$ |
| try { |
| getContainer().run(true, true, monitor -> { |
| monitor.beginTask( |
| org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_task_downloading + archetypeName, |
| IProgressMonitor.UNKNOWN); |
| |
| try { |
| final IMaven maven = MavenPlugin.getMaven(); |
| |
| final List<ArtifactRepository> remoteRepositories; |
| if(repositoryUrl.length() == 0) { |
| remoteRepositories = maven.getArtifactRepositories(); // XXX should use ArchetypeManager.getArchetypeRepositories() |
| } else { |
| //Use id = archetypeArtifactId+"-repo" to enable mirror/proxy authentication |
| //see http://maven.apache.org/archetype/maven-archetype-plugin/faq.html |
| ArtifactRepository repository = maven.createArtifactRepository(archetypeArtifactId + "-repo", //$NON-NLS-1$ |
| repositoryUrl); |
| |
| remoteRepositories = Collections.singletonList(repository); |
| } |
| |
| monitor.subTask(org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_task_resolving); |
| Artifact pomArtifact = maven.resolve(archetypeGroupId, archetypeArtifactId, archetypeVersion, "pom", null, //$NON-NLS-1$ |
| remoteRepositories, monitor); |
| monitor.worked(1); |
| if(monitor.isCanceled()) { |
| throw new InterruptedException(); |
| } |
| |
| File pomFile = pomArtifact.getFile(); |
| if(pomFile.exists()) { |
| monitor.subTask(org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_task_resolving2); |
| Artifact jarArtifact = maven.resolve(archetypeGroupId, archetypeArtifactId, archetypeVersion, "jar", null, //$NON-NLS-1$ |
| remoteRepositories, monitor); |
| monitor.worked(1); |
| if(monitor.isCanceled()) { |
| throw new InterruptedException(); |
| } |
| |
| File jarFile = jarArtifact.getFile(); |
| |
| monitor.subTask(org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_task_reading); |
| monitor.worked(1); |
| if(monitor.isCanceled()) { |
| throw new InterruptedException(); |
| } |
| |
| monitor.subTask(org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_task_indexing); |
| IndexManager indexManager = MavenPlugin.getIndexManager(); |
| IMutableIndex localIndex = indexManager.getLocalIndex(); |
| localIndex.addArtifact(jarFile, new ArtifactKey(pomArtifact)); |
| |
| //save out the archetype |
| //TODO move this logic out of UI code! |
| Archetype archetype = new Archetype(); |
| archetype.setGroupId(archetypeGroupId); |
| archetype.setArtifactId(archetypeArtifactId); |
| archetype.setVersion(archetypeVersion); |
| archetype.setRepository(repositoryUrl); |
| org.apache.maven.archetype.ArchetypeManager archetyper = MavenPluginActivator.getDefault() |
| .getArchetypeManager().getArchetyper(); |
| archetyper.updateLocalCatalog(archetype); |
| |
| archetypesCache.clear(); |
| |
| loadArchetypes(archetypeGroupId, archetypeArtifactId, archetypeVersion); |
| } else { |
| final Artifact pom = pomArtifact; |
| //the user tried to add an archetype that couldn't be resolved on the server |
| getShell().getDisplay() |
| .asyncExec(() -> setErrorMessage( |
| NLS.bind(org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_error_resolve, |
| pom.toString()))); |
| } |
| |
| } catch(InterruptedException ex1) { |
| throw ex1; |
| |
| } catch(final Exception ex2) { |
| final String msg = NLS.bind( |
| org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_error_resolve2, archetypeName); |
| log.error(msg, ex2); |
| getShell().getDisplay().asyncExec(() -> setErrorMessage(msg + "\n" + ex2.toString())); |
| |
| } finally { |
| monitor.done(); |
| |
| } |
| }); |
| |
| } catch(InterruptedException ex) { |
| // ignore |
| |
| } catch(InvocationTargetException ex) { |
| String msg = NLS.bind(org.eclipse.m2e.core.ui.internal.Messages.MavenProjectWizardArchetypePage_error_resolve2, |
| archetypeName); |
| log.error(msg, ex); |
| setErrorMessage(msg + "\n" + ex.toString()); //$NON-NLS-1$ |
| |
| } |
| } |
| |
| /** |
| * ArchetypeLabelProvider |
| */ |
| protected static class ArchetypeLabelProvider extends LabelProvider implements ITableLabelProvider { |
| /** Returns the element text */ |
| public String getColumnText(Object element, int columnIndex) { |
| if(element instanceof Archetype) { |
| Archetype archetype = (Archetype) element; |
| switch(columnIndex) { |
| case 0: |
| return archetype.getGroupId(); |
| case 1: |
| return archetype.getArtifactId(); |
| case 2: |
| return archetype.getVersion(); |
| } |
| } |
| return super.getText(element); |
| } |
| |
| /** Returns the element text */ |
| public Image getColumnImage(Object element, int columnIndex) { |
| return null; |
| } |
| } |
| |
| /** |
| * QuickViewerFilter |
| */ |
| protected class QuickViewerFilter extends ViewerFilter implements ModifyListener { |
| |
| private String currentFilter; |
| |
| public boolean select(Viewer viewer, Object parentElement, Object element) { |
| if(currentFilter == null || currentFilter.length() == 0) { |
| return true; |
| } |
| Archetype archetype = (Archetype) element; |
| return archetype.getGroupId().toLowerCase().indexOf(currentFilter) > -1 |
| || archetype.getArtifactId().toLowerCase().indexOf(currentFilter) > -1; |
| } |
| |
| public void modifyText(ModifyEvent e) { |
| this.currentFilter = filterText.getText().trim().toLowerCase(); |
| viewer.refresh(); |
| } |
| } |
| |
| protected class VersionsFilter extends ViewerFilter implements SelectionListener { |
| |
| private boolean showLastVersion; |
| |
| private boolean includeSnapshots; |
| |
| public VersionsFilter(boolean showLastVersion, boolean includeSnapshots) { |
| this.showLastVersion = showLastVersion; |
| this.includeSnapshots = includeSnapshots; |
| } |
| |
| public boolean select(Viewer viewer, Object parentElement, Object element) { |
| if(!(element instanceof Archetype)) { |
| return false; |
| } |
| |
| Archetype archetype = (Archetype) element; |
| String version = archetype.getVersion(); |
| |
| if(!includeSnapshots) { |
| if(isSnapshotVersion(version)) { |
| return false; |
| } |
| } |
| |
| if(!showLastVersion) { |
| return true; |
| } |
| |
| // need to find latest version, skipping snapshots depending on includeSnapshots |
| List<ArtifactVersion> versions = archetypeVersions.get(getArchetypeKey(archetype)); |
| |
| if(versions == null || versions.isEmpty()) { |
| return false; // can't really happen |
| } |
| |
| for(ArtifactVersion otherVersion : versions) { |
| if(includeSnapshots || !isSnapshotVersion(otherVersion.toString())) { |
| if(otherVersion.toString().equals(version)) { |
| return true; |
| } |
| break; |
| } |
| } |
| |
| return false; |
| } |
| |
| boolean isSnapshotVersion(String version) { |
| return !M2EUIUtils.nullOrEmpty(version) && version.endsWith("SNAPSHOT"); //$NON-NLS-1$ |
| } |
| |
| public void widgetSelected(SelectionEvent e) { |
| this.showLastVersion = showLastVersionButton.getSelection(); |
| this.includeSnapshots = includeShapshotsButton.getSelection(); |
| viewer.refresh(); |
| Archetype archetype = getArchetype(); |
| //can be null in some cases, don't try to reveal |
| if(archetype != null) { |
| viewer.reveal(archetype); |
| } |
| viewer.getTable().setSelection(viewer.getTable().getSelectionIndex()); |
| viewer.getTable().setFocus(); |
| } |
| |
| public void widgetDefaultSelected(SelectionEvent e) { |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.m2e.index.IndexListener#indexAdded(org.eclipse.m2e.repository.IRepository) |
| */ |
| public void indexAdded(IRepository repository) { |
| |
| } |
| |
| //reload the table when index updating finishes |
| //try to preserve selection in case this is a rebuild |
| protected void reloadViewer() { |
| Display.getDefault().asyncExec(() -> { |
| if(isCurrentPage()) { |
| StructuredSelection sel = (StructuredSelection) viewer.getSelection(); |
| Archetype selArchetype = null; |
| if(sel != null && sel.getFirstElement() != null) { |
| selArchetype = (Archetype) sel.getFirstElement(); |
| } |
| if(selArchetype != null) { |
| loadArchetypes(selArchetype.getGroupId(), selArchetype.getArtifactId(), selArchetype.getVersion()); |
| } else { |
| loadArchetypes("org.apache.maven.archetypes", "maven-archetype-quickstart", "1.0"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| } |
| }); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.m2e.index.IndexListener#indexChanged(org.eclipse.m2e.repository.IRepository) |
| */ |
| public void indexChanged(IRepository repository) { |
| reloadViewer(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.m2e.index.IndexListener#indexRemoved(org.eclipse.m2e.repository.IRepository) |
| */ |
| public void indexRemoved(IRepository repository) { |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.m2e.index.IndexListener#indexUpdating(org.eclipse.m2e.repository.IRepository) |
| */ |
| public void indexUpdating(IRepository repository) { |
| } |
| |
| private class RetrievingArchetypesJob extends Job { |
| |
| List<Archetype> catalogArchetypes; |
| |
| private ArchetypeCatalogFactory archetypeCatalogFactory; |
| |
| public RetrievingArchetypesJob(ArchetypeCatalogFactory catalogFactory) { |
| super(Messages.wizardProjectPageArchetypeRetrievingArchetypes); |
| this.archetypeCatalogFactory = catalogFactory; |
| } |
| |
| protected IStatus run(IProgressMonitor monitor) { |
| try { |
| catalogArchetypes = getArchetypesForCatalog(archetypeCatalogFactory, monitor); |
| } catch(Exception e) { |
| monitor.done(); |
| return new Status(IStatus.ERROR, M2EUIPluginActivator.PLUGIN_ID, |
| Messages.MavenProjectWizardArchetypePage_ErrorRetrievingArchetypes, e); |
| } |
| return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS; |
| } |
| |
| } |
| } |