diff options
30 files changed, 2341 insertions, 0 deletions
diff --git a/org.eclipse.m2e.feature/feature.xml b/org.eclipse.m2e.feature/feature.xml index d2c8226b..54269180 100644 --- a/org.eclipse.m2e.feature/feature.xml +++ b/org.eclipse.m2e.feature/feature.xml @@ -140,4 +140,18 @@ version="0.0.0" unpack="false"/> + <plugin + id="org.eclipse.m2e.profiles.core" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.m2e.profiles.ui" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + </feature> diff --git a/org.eclipse.m2e.profiles.core/META-INF/MANIFEST.MF b/org.eclipse.m2e.profiles.core/META-INF/MANIFEST.MF new file mode 100644 index 00000000..8be8df74 --- /dev/null +++ b/org.eclipse.m2e.profiles.core/META-INF/MANIFEST.MF @@ -0,0 +1,16 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Bundle-SymbolicName: org.eclipse.m2e.profiles.core;singleton:=true +Bundle-Version: 1.5.0.qualifier +Bundle-Localization: plugin +Bundle-Activator: org.eclipse.m2e.profiles.core.internal.MavenProfilesCoreActivator +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.7.0", + org.eclipse.core.resources;bundle-version="3.6.0";visibility:=reexport, + org.eclipse.m2e.core;bundle-version="[1.5.0,1.6.0)";visibility:=reexport, + org.eclipse.m2e.maven.runtime;bundle-version="[1.5.0,1.6.0)";visibility:=reexport +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-Vendor: %Bundle-Vendor +Export-Package: org.eclipse.m2e.profiles.core.internal;x-friends:="org.eclipse.m2e.profiles.ui", + org.eclipse.m2e.profiles.core.internal.management;x-internal:=true diff --git a/org.eclipse.m2e.profiles.core/about.html b/org.eclipse.m2e.profiles.core/about.html new file mode 100644 index 00000000..091e5d04 --- /dev/null +++ b/org.eclipse.m2e.profiles.core/about.html @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> +<title>Maven Profile Management</title> +<style type="text/css" media="screen"> +<!-- + body { + font-family: Sans-serif, Arial, Helvetica; + } + +--> +</style> +</head> +<body> +<h1>Maven Profile Management</h1> + +<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.profiles.core/build.properties b/org.eclipse.m2e.profiles.core/build.properties new file mode 100644 index 00000000..a589df16 --- /dev/null +++ b/org.eclipse.m2e.profiles.core/build.properties @@ -0,0 +1,7 @@ +source.. = src/ +output.. = target/classes/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + plugin.properties,\ + about.html diff --git a/org.eclipse.m2e.profiles.core/plugin.properties b/org.eclipse.m2e.profiles.core/plugin.properties new file mode 100644 index 00000000..ae6534ba --- /dev/null +++ b/org.eclipse.m2e.profiles.core/plugin.properties @@ -0,0 +1,2 @@ +Bundle-Vendor = Eclipse.org - m2e +Bundle-Name = Maven Profiles Management
\ No newline at end of file diff --git a/org.eclipse.m2e.profiles.core/plugin.xml b/org.eclipse.m2e.profiles.core/plugin.xml new file mode 100644 index 00000000..f422d55d --- /dev/null +++ b/org.eclipse.m2e.profiles.core/plugin.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.4"?> +<plugin> +</plugin> diff --git a/org.eclipse.m2e.profiles.core/pom.xml b/org.eclipse.m2e.profiles.core/pom.xml new file mode 100644 index 00000000..d1978522 --- /dev/null +++ b/org.eclipse.m2e.profiles.core/pom.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.eclipse.m2e</groupId> + <artifactId>m2e-core</artifactId> + <version>1.5.0-SNAPSHOT</version> + </parent> + + <artifactId>org.eclipse.m2e.profiles.core</artifactId> + + <packaging>eclipse-plugin</packaging> + + <name>Maven Profile Manager Core</name> +</project>
\ No newline at end of file diff --git a/org.eclipse.m2e.profiles.core/src/org/eclipse/m2e/profiles/core/internal/IProfileManager.java b/org.eclipse.m2e.profiles.core/src/org/eclipse/m2e/profiles/core/internal/IProfileManager.java new file mode 100644 index 00000000..6a9ad8c5 --- /dev/null +++ b/org.eclipse.m2e.profiles.core/src/org/eclipse/m2e/profiles/core/internal/IProfileManager.java @@ -0,0 +1,63 @@ +/************************************************************************************* + * Copyright (c) 2011-2014 Red Hat, Inc. and others. + * 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: + * Fred Bricon / JBoss by Red Hat - Initial implementation. + ************************************************************************************/ +package org.eclipse.m2e.profiles.core.internal; + +import java.util.List; +import java.util.Map; + +import org.apache.maven.model.Profile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.m2e.core.project.IMavenProjectFacade; + +/** + * Retrieves and updates Maven profile informations for Maven Projects + * + * @author Fred Bricon + * @noimplement This interface is not intended to be implemented by clients. + * @since 1.5.0 + */ +public interface IProfileManager { + + /** + * Returns a List of {@link ProfileData} for the given mavenProjectFacade + * + * @param mavenProjectFacade a facade of the maven project + * @param monitor a progress monitor + * @return a List of {@link ProfileData} for the given mavenProjectFacade. + * @throws CoreException + */ + List<ProfileData> getProfileDatas(IMavenProjectFacade mavenProjectFacade, IProgressMonitor monitor) throws CoreException; + + /** + * Returns an unmodifiable {@link Map} of all available {@link Profile}s converted from the + * {@link org.apache.maven.profiles.Profile}s as defined in settings.xml.<br/> + * The value of each {@link Entry} indicates if the profile is active. + * + * @return an unmodifiable {@link Map} of all the available profiles for a given project. + * @throws CoreException + */ + Map<Profile, Boolean> getAvailableSettingsProfiles() throws CoreException; + + /** + * Update the profiles of the resolver configuration of a {@link IMavenProjectFacade} synchronously. + * + * @param mavenProjectFacade a facade of the maven project + * @param profiles the profile ids to use in the project's resolver configuration + * @param isOffline indicates if the maven request must be executed offline + * @param isForceUpdate indicates if a check for updated releases and snapshots on remote repositories must be forced. + * @param monitor a progress monitor + * @throws CoreException + */ + void updateActiveProfiles(IMavenProjectFacade mavenProjectFacade, + List<String> profiles, boolean isOffline, boolean isForceUpdate, IProgressMonitor monitor) + throws CoreException; +} diff --git a/org.eclipse.m2e.profiles.core/src/org/eclipse/m2e/profiles/core/internal/MavenProfilesCoreActivator.java b/org.eclipse.m2e.profiles.core/src/org/eclipse/m2e/profiles/core/internal/MavenProfilesCoreActivator.java new file mode 100644 index 00000000..a5cef10f --- /dev/null +++ b/org.eclipse.m2e.profiles.core/src/org/eclipse/m2e/profiles/core/internal/MavenProfilesCoreActivator.java @@ -0,0 +1,90 @@ +/************************************************************************************* + * Copyright (c) 2008-2011 Red Hat, Inc. and others. + * 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: + * Fred Bricon / JBoss by Red Hat - Initial implementation. + ************************************************************************************/ +package org.eclipse.m2e.profiles.core.internal; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Plugin; +import org.eclipse.core.runtime.Status; +import org.eclipse.m2e.profiles.core.internal.management.ProfileManager; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + * + * @author Fred Bricon + * @since 1.5.0 + */ +public class MavenProfilesCoreActivator extends Plugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.m2e.profiles.core.internal"; //$NON-NLS-1$ + + private IProfileManager profileManager; + + // The shared instance + private static MavenProfilesCoreActivator plugin; + + /** + * The constructor + */ + public MavenProfilesCoreActivator() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + profileManager = new ProfileManager(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static MavenProfilesCoreActivator getDefault() { + return plugin; + } + + public static IStatus getStatus(String message) { + return new Status(IStatus.ERROR, PLUGIN_ID, message); + } + + public static IStatus getStatus(String message, Throwable e) { + return new Status(IStatus.ERROR, PLUGIN_ID, message,e); + } + + public static void log(Throwable e) { + IStatus status = new Status(IStatus.ERROR, PLUGIN_ID, e.getLocalizedMessage(), e); + getDefault().getLog().log(status); + } + + public static void log(String message) { + IStatus status = new Status(IStatus.ERROR, PLUGIN_ID, message); + getDefault().getLog().log(status); + } + + public IProfileManager getProfileManager() { + return profileManager; + } +} diff --git a/org.eclipse.m2e.profiles.core/src/org/eclipse/m2e/profiles/core/internal/ProfileData.java b/org.eclipse.m2e.profiles.core/src/org/eclipse/m2e/profiles/core/internal/ProfileData.java new file mode 100644 index 00000000..2c608e71 --- /dev/null +++ b/org.eclipse.m2e.profiles.core/src/org/eclipse/m2e/profiles/core/internal/ProfileData.java @@ -0,0 +1,138 @@ +/************************************************************************************* + * Copyright (c) 2011-2014 Red Hat, Inc. and others. + * 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: + * Fred Bricon / JBoss by Red Hat - Initial implementation. + ************************************************************************************/ +package org.eclipse.m2e.profiles.core.internal; + +/** + * Model wrapping Maven Profile informations. + * + * @author Fred Bricon + * @since 1.5.0 + */ +public class ProfileData { + private String id; + private boolean autoActive; + private boolean userSelected; + private ProfileState activationState; + private String source; + + /** + * Constructor + * @param id the profile id + */ + public ProfileData(String id) { + this.id = id; + } + + /** + * @return the Maven profile id + */ + public String getId() { + return id; + } + + /** + * Sets the Maven profile id + */ + public void setId(String id) { + this.id = id; + } + + /** + * @return <code>true</code> if the profile is active automatically + */ + public boolean isAutoActive() { + return autoActive; + } + + public void setAutoActive(boolean autoActive) { + this.autoActive = autoActive; + } + + /** + * @return the activation state of the profile (Active, Inactive, Disabled, Unknown) + */ + public ProfileState getActivationState() { + return activationState; + } + + public void setActivationState(ProfileState activationState) { + this.activationState = activationState; + } + + /** + * @return the source defining the profile (settings.xml or artifactId defining the profile) + */ + public String getSource() { + return source; + } + public void setSource(String source) { + this.source = source; + } + + /** + * @return true if the profile was set in Eclipse UI + */ + public boolean isUserSelected() { + return userSelected; + } + + public void setUserSelected(boolean userSelected) { + this.userSelected = userSelected; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((activationState == null) ? 0 : activationState.hashCode()); + result = prime * result + (autoActive ? 1231 : 1237); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((source == null) ? 0 : source.hashCode()); + result = prime * result + (userSelected ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ProfileData other = (ProfileData) obj; + if (activationState != other.activationState) + return false; + if (autoActive != other.autoActive) + return false; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (source == null) { + if (other.source != null) + return false; + } else if (!source.equals(other.source)) + return false; + if (userSelected != other.userSelected) + return false; + return true; + } + + @Override + public String toString() { + return "ProfileData [id=" + id + ", autoActive=" + autoActive + + ", userSelected=" + userSelected + ", activationState=" + + activationState + ", source=" + source + "]"; + } +} diff --git a/org.eclipse.m2e.profiles.core/src/org/eclipse/m2e/profiles/core/internal/ProfileState.java b/org.eclipse.m2e.profiles.core/src/org/eclipse/m2e/profiles/core/internal/ProfileState.java new file mode 100644 index 00000000..96a87287 --- /dev/null +++ b/org.eclipse.m2e.profiles.core/src/org/eclipse/m2e/profiles/core/internal/ProfileState.java @@ -0,0 +1,41 @@ +/************************************************************************************* + * Copyright (c) 2011-2014 Red Hat, Inc. and others. + * 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: + * Fred Bricon / JBoss by Red Hat - Initial implementation. + ************************************************************************************/ +package org.eclipse.m2e.profiles.core.internal; + +/** + * Enum of all possible Profile states : + * <ul> + * <li>Active : the profile is active</li> + * <li>Inactive : the profile is not active</li> + * <li>Disabled : the profile is not active</li> + * </ul> + * @author Fred Bricon + * @since 1.5.0 + */ +public enum ProfileState { + Disabled(false), + Inactive(false), + Active(true); + + private boolean active; + + ProfileState(boolean active) { + this.active = active; + } + + /** + * @return true if the Profile is active + */ + public boolean isActive() { + return active; + } + +} diff --git a/org.eclipse.m2e.profiles.core/src/org/eclipse/m2e/profiles/core/internal/management/ProfileManager.java b/org.eclipse.m2e.profiles.core/src/org/eclipse/m2e/profiles/core/internal/management/ProfileManager.java new file mode 100644 index 00000000..3c15d8c0 --- /dev/null +++ b/org.eclipse.m2e.profiles.core/src/org/eclipse/m2e/profiles/core/internal/management/ProfileManager.java @@ -0,0 +1,348 @@ +/************************************************************************************* + * Copyright (c) 2011-2014 Red Hat, Inc. and others. + * 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: + * Fred Bricon / JBoss by Red Hat - Initial implementation. + ************************************************************************************/ +package org.eclipse.m2e.profiles.core.internal.management; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.InvalidRepositoryException; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.model.Model; +import org.apache.maven.model.Parent; +import org.apache.maven.model.Profile; +import org.apache.maven.model.Repository; +import org.apache.maven.project.MavenProject; +import org.apache.maven.repository.RepositorySystem; +import org.apache.maven.settings.Settings; +import org.apache.maven.settings.SettingsUtils; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.codehaus.plexus.util.StringUtils; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.m2e.core.MavenPlugin; +import org.eclipse.m2e.core.embedder.IMaven; +import org.eclipse.m2e.core.internal.MavenPluginActivator; +import org.eclipse.m2e.core.internal.NoSuchComponentException; +import org.eclipse.m2e.core.project.IMavenProjectFacade; +import org.eclipse.m2e.core.project.IProjectConfigurationManager; +import org.eclipse.m2e.core.project.MavenUpdateRequest; +import org.eclipse.m2e.core.project.ResolverConfiguration; +import org.eclipse.m2e.profiles.core.internal.IProfileManager; +import org.eclipse.m2e.profiles.core.internal.MavenProfilesCoreActivator; +import org.eclipse.m2e.profiles.core.internal.ProfileState; +import org.eclipse.m2e.profiles.core.internal.ProfileData; +import org.eclipse.osgi.util.NLS; + +/** + * Maven Profile Manager + * + * @author Fred Bricon + * @since 1.5.0 + */ +public class ProfileManager implements IProfileManager { + + public void updateActiveProfiles(final IMavenProjectFacade mavenProjectFacade, + final List<String> profiles, + final boolean isOffline, + final boolean isForceUpdate, + IProgressMonitor monitor) throws CoreException { + if (mavenProjectFacade == null) { + return; + } + final IProjectConfigurationManager configurationManager = MavenPlugin.getProjectConfigurationManager(); + + IProject project = mavenProjectFacade.getProject(); + + final ResolverConfiguration configuration =configurationManager.getResolverConfiguration(project); + + final String profilesAsString = getAsString(profiles); + if (profilesAsString.equals(configuration.getSelectedProfiles())) { + //Nothing changed + return; + } + + configuration.setSelectedProfiles(profilesAsString); + boolean isSet = configurationManager.setResolverConfiguration(project, configuration); + if (isSet) { + MavenUpdateRequest request = new MavenUpdateRequest(project, isOffline, isForceUpdate); + configurationManager.updateProjectConfiguration(request, monitor); + } + + } + + private String getAsString(List<String> profiles) { + StringBuilder sb = new StringBuilder(); + boolean addComma = false; + if (profiles != null){ + for (String p : profiles) { + if (addComma) { + sb.append(", "); //$NON-NLS-1$ + } + sb.append(p); + addComma = true; + } + } + return sb.toString(); + } + + public Map<Profile, Boolean> getAvailableSettingsProfiles() throws CoreException { + Map<Profile, Boolean> settingsProfiles = new LinkedHashMap<Profile, Boolean>(); + Settings settings = MavenPlugin.getMaven().getSettings(); + List<String> activeProfiles = settings.getActiveProfiles(); + + for (org.apache.maven.settings.Profile sp : settings.getProfiles()) { + Profile p = SettingsUtils.convertFromSettingsProfile(sp); + boolean isAutomaticallyActivated = isActive(sp, activeProfiles); + settingsProfiles.put(p, isAutomaticallyActivated); + } + return Collections.unmodifiableMap(settingsProfiles); + } + + private boolean isActive(Profile p, List<Profile> activeProfiles) { + for (Profile activeProfile : activeProfiles) { + if (activeProfile.getId().equals(p.getId())) { + return true; + } + } + return false; + } + + private boolean isActive(org.apache.maven.settings.Profile p, List<String> activeProfiles) { + if (p.getActivation() != null && p.getActivation().isActiveByDefault()){ + return true; + } + for (String activeProfile : activeProfiles) { + if (activeProfile.equals(p.getId())) { + return true; + } + } + return false; + } + + public List<ProfileData> getProfileDatas( + IMavenProjectFacade facade, + IProgressMonitor monitor + ) throws CoreException { + if (facade == null) { + return Collections.emptyList(); + } + + ResolverConfiguration resolverConfiguration = MavenPlugin.getProjectConfigurationManager() + .getResolverConfiguration(facade.getProject()); + + List<String> configuredProfiles = toList(resolverConfiguration.getSelectedProfiles()); + + MavenProject mavenProject = facade.getMavenProject(monitor); + + List<Model> modelHierarchy = new ArrayList<Model>(); + + getModelHierarchy(modelHierarchy, mavenProject.getModel(), monitor); + + List<Profile> availableProfiles = collectAvailableProfiles(modelHierarchy, monitor); + + final Map<Profile, Boolean> availableSettingsProfiles = getAvailableSettingsProfiles(); + + Set<Profile> settingsProfiles = new HashSet<Profile>(availableSettingsProfiles.keySet()); + + List<ProfileData> statuses = new ArrayList<ProfileData>(); + + //First we put user configured profiles + for (String pId : configuredProfiles) { + if (StringUtils.isEmpty(pId)) continue; + boolean isDisabled = pId.startsWith("!"); + String id = (isDisabled)?pId.substring(1):pId; + ProfileData status = new ProfileData(id); + status.setUserSelected(true); + ProfileState state = isDisabled?ProfileState.Disabled:ProfileState.Active; + status.setActivationState(state); + + Profile p = get(id, availableProfiles); + + if (p == null){ + p = get(id, settingsProfiles); + if(p != null){ + status.setAutoActive(availableSettingsProfiles.get(p)); + } + } + + status.setSource(findSource(p, modelHierarchy)); + statuses.add(status); + } + + final List<Profile> activeProfiles = mavenProject.getActiveProfiles(); + //Iterate on the remaining project profiles + addStatuses(statuses, availableProfiles, modelHierarchy, new ActivationPredicate() { + @Override + boolean isActive(Profile p) { + return ProfileManager.this.isActive(p, activeProfiles); + } + }); + + //Iterate on the remaining settings profiles + addStatuses(statuses, settingsProfiles, modelHierarchy, new ActivationPredicate() { + @Override + boolean isActive(Profile p) { + return availableSettingsProfiles.get(p); + } + }); + return Collections.unmodifiableList(statuses); + } + + private List<String> toList(String profilesAsText) { + List<String> profiles; + if (profilesAsText != null && profilesAsText.trim().length() > 0) { + String[] profilesArray = profilesAsText.split("[,\\s\\|]"); + profiles = new ArrayList<String>(profilesArray.length); + for (String profile : profilesArray) { + profiles.add(profile); + } + } else { + profiles = new ArrayList<String>(0); + } + return profiles; + } + + private String findSource(Profile profile, List<Model> modelHierarchy) { + if (profile != null) { + if ("settings.xml".equals(profile.getSource())) { //$NON-NLS-1$ + return profile.getSource(); + } + for (Model m : modelHierarchy) { + for (Profile p : m.getProfiles()) { + if(p.equals(profile)) { + return m.getArtifactId(); + } + } + } + } + return "undefined"; //$NON-NLS-1$ + } + + protected List<Profile> collectAvailableProfiles(List<Model> models, IProgressMonitor monitor) throws CoreException { + List<Profile> profiles = new ArrayList<Profile>(); + for (Model m : models) { + profiles.addAll(m.getProfiles()); + } + return profiles; + } + + protected List<Model> getModelHierarchy(List<Model> models, Model projectModel, IProgressMonitor monitor) throws CoreException { + if (projectModel == null) { + return null; + } + models.add(projectModel); + Parent p = projectModel.getParent(); + if (p != null) { + + IMaven maven = MavenPlugin.getMaven(); + + List<ArtifactRepository> repositories = new ArrayList<ArtifactRepository>(); + repositories.addAll(getProjectRepositories(projectModel)); + repositories.addAll(maven.getArtifactRepositories()); + + Model parentModel = resolvePomModel(p.getGroupId(), p.getArtifactId(), p.getVersion(), repositories, monitor); + if (parentModel != null) { + getModelHierarchy(models, parentModel, monitor); + } + } + return models; + } + + private List<ArtifactRepository> getProjectRepositories(Model projectModel) { + List<ArtifactRepository> repos = new ArrayList<ArtifactRepository>(); + List<Repository> modelRepos = projectModel.getRepositories(); + if (modelRepos != null && !modelRepos.isEmpty()) { + RepositorySystem repositorySystem = getRepositorySystem(); + for (Repository modelRepo : modelRepos) { + ArtifactRepository ar; + try { + ar = repositorySystem.buildArtifactRepository(modelRepo); + if (ar != null) { + repos.add(ar); + } + } catch (InvalidRepositoryException e) { + MavenProfilesCoreActivator.log(e); + } + } + } + return repos; + } + + private RepositorySystem getRepositorySystem() { + try { + //TODO find an alternative way to get the Maven RepositorySystem, or use Aether directly to resolve models?? + return MavenPluginActivator.getDefault().getPlexusContainer().lookup(RepositorySystem.class); + } catch (ComponentLookupException e) { + throw new NoSuchComponentException(e); + } + } + + private Model resolvePomModel(String groupId, String artifactId, String version, List<ArtifactRepository> repositories, IProgressMonitor monitor) + throws CoreException { + monitor.subTask(NLS.bind("Resolving {0}:{1}:{2}", new Object[] { groupId, artifactId, version})); + + IMavenProjectFacade facade = MavenPlugin.getMavenProjectRegistry().getMavenProject(groupId, artifactId, version); + IMaven maven = MavenPlugin.getMaven(); + + if (facade != null) { + return facade.getMavenProject(monitor).getModel(); + } + + Artifact artifact = maven.resolve(groupId, artifactId, version, "pom", null, repositories, monitor); //$NON-NLS-1$ + File file = artifact.getFile(); + if(file == null) { + return null; + } + + return maven.readModel(file); + } + + private void addStatuses(List<ProfileData> statuses, Collection<Profile> profiles, List<Model> modelHierarchy, ActivationPredicate predicate) { + for (Profile p : profiles) { + ProfileData status = new ProfileData(p.getId()); + status.setSource(findSource(p, modelHierarchy)); + boolean isActive = predicate.isActive(p); + ProfileState activationState = (isActive)?ProfileState.Active:ProfileState.Inactive; + status.setAutoActive(isActive); + status.setActivationState(activationState); + statuses.add(status); + } + } + + private Profile get(String id, Collection<Profile> profiles) { + Iterator<Profile> ite = profiles.iterator(); + Profile found = null; + while(ite.hasNext()) { + Profile p = ite.next(); + if(id.equals(p.getId())) { + found = p; + ite.remove(); + break; + } + } + return found; + } + + private abstract class ActivationPredicate { + abstract boolean isActive(Profile p); + } +} diff --git a/org.eclipse.m2e.profiles.ui/META-INF/MANIFEST.MF b/org.eclipse.m2e.profiles.ui/META-INF/MANIFEST.MF new file mode 100644 index 00000000..380606a1 --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/META-INF/MANIFEST.MF @@ -0,0 +1,19 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Bundle-SymbolicName: org.eclipse.m2e.profiles.ui;singleton:=true +Bundle-Version: 1.5.0.qualifier +Bundle-Localization: plugin +Bundle-Activator: org.eclipse.m2e.profiles.ui.internal.MavenProfilesUIActivator +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.core.resources, + org.eclipse.m2e.core.ui;bundle-version="[1.5.0,1.6.0)", + org.eclipse.ui.ide, + org.eclipse.jface.text, + org.eclipse.m2e.profiles.core;bundle-version="[1.5.0,1.6.0)", + org.slf4j.api;bundle-version="1.6.2" +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-Vendor: %Bundle-Vendor +Export-Package: org.eclipse.m2e.profiles.ui.internal;x-internal:=true diff --git a/org.eclipse.m2e.profiles.ui/about.html b/org.eclipse.m2e.profiles.ui/about.html new file mode 100644 index 00000000..091e5d04 --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/about.html @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> +<title>Maven Profile Management</title> +<style type="text/css" media="screen"> +<!-- + body { + font-family: Sans-serif, Arial, Helvetica; + } + +--> +</style> +</head> +<body> +<h1>Maven Profile Management</h1> + +<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.profiles.ui/build.properties b/org.eclipse.m2e.profiles.ui/build.properties new file mode 100644 index 00000000..0198093c --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/build.properties @@ -0,0 +1,8 @@ +source.. = src/ +output.. = target/classes/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + about.html,\ + plugin.properties,\ + icons/ diff --git a/org.eclipse.m2e.profiles.ui/icons/maven-profiles.gif b/org.eclipse.m2e.profiles.ui/icons/maven-profiles.gif Binary files differnew file mode 100644 index 00000000..31f4413f --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/icons/maven-profiles.gif diff --git a/org.eclipse.m2e.profiles.ui/plugin.properties b/org.eclipse.m2e.profiles.ui/plugin.properties new file mode 100644 index 00000000..6c1cb0de --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/plugin.properties @@ -0,0 +1,6 @@ +Bundle-Vendor = Eclipse.org - m2e +Bundle-Name = Maven Profiles Management UI + +#Maven Profile selection menu +Select_Maven_Profiles_Cmd= Select Maven Profiles +Select_Maven_Profiles_Menu= Select Maven Profiles... diff --git a/org.eclipse.m2e.profiles.ui/plugin.xml b/org.eclipse.m2e.profiles.ui/plugin.xml new file mode 100644 index 00000000..62eb934a --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/plugin.xml @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.4"?> +<plugin> + <!-- Maven Profile Selection--> + <extension + point="org.eclipse.ui.commands"> + <command + categoryId="org.eclipse.ui.category.window" + id="org.eclipse.m2e.profiles.ui.commands.selectMavenProfileCommand" + name="%Select_Maven_Profiles_Cmd"> + </command> + </extension> + + <extension + point="org.eclipse.ui.handlers"> + <handler + class="org.eclipse.m2e.profiles.ui.internal.actions.ProfileSelectionHandler" + commandId="org.eclipse.m2e.profiles.ui.commands.selectMavenProfileCommand"> + </handler> + </extension> + <extension + point="org.eclipse.ui.bindings"> + <key + commandId="org.eclipse.m2e.profiles.ui.commands.selectMavenProfileCommand" + contextId="org.eclipse.ui.contexts.window" + schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" + sequence="Ctrl+Alt+P"> + </key> + </extension> + + <extension point="org.eclipse.ui.popupMenus"> + <objectContribution id="org.eclipse.m2e.profiles.ui.profiles.selectFromProject" + objectClass="org.eclipse.core.resources.IProject" + adaptable="true"> + <action id="org.eclipse.m2e.profiles.ui.commands.selectMavenProfileAction" + class="org.eclipse.m2e.profiles.ui.internal.actions.GenericCommandActionDelegate:org.eclipse.m2e.profiles.ui.commands.selectMavenProfileCommand" + label="%Select_Maven_Profiles_Menu" + style="push" + definitionId="org.eclipse.m2e.profiles.ui.commands.selectMavenProfileCommand" + menubarPath="org.eclipse.m2e.core.mavenMenu/open" + enablesFor="+"/> + <visibility> + <and> + <objectState name="open" value="true"/> + <objectState name="nature" value="org.eclipse.m2e.core.maven2Nature"/> + </and> + </visibility> + </objectContribution> + + <objectContribution id="org.eclipse.m2e.profiles.ui.profiles.selectFromPom" + objectClass="org.eclipse.core.resources.IFile" + adaptable="true"> + <action id="org.eclipse.m2e.profiles.ui.commands.selectMavenProfileAction" + class="org.eclipse.m2e.profiles.ui.internal.actions.GenericCommandActionDelegate:org.eclipse.m2e.profiles.ui.commands.selectMavenProfileCommand" + label="%Select_Maven_Profiles_Menu" + style="push" + definitionId="org.eclipse.m2e.profiles.ui.commands.selectMavenProfileCommand" + menubarPath="org.eclipse.m2e.core.fileMenu/open" + enablesFor="+"/> + <visibility> + <objectState name="name" value="pom.xml"/> + </visibility> + </objectContribution> + + <objectContribution id="org.eclipse.m2e.profiles.ui.profiles.selectFromWorkingSet" + adaptable="true" + objectClass="org.eclipse.ui.IWorkingSet"> + <action id="org.eclipse.m2e.profiles.ui.commands.selectMavenProfileAction" + class="org.eclipse.m2e.profiles.ui.internal.actions.GenericCommandActionDelegate:org.eclipse.m2e.profiles.ui.commands.selectMavenProfileCommand" + label="%Select_Maven_Profiles_Menu" + style="push" + definitionId="org.eclipse.m2e.profiles.ui.commands.selectMavenProfileCommand" + menubarPath="org.eclipse.m2e.core.workingSetMenu/open" + enablesFor="+"/> + </objectContribution> + + </extension> + <extension + point="org.eclipse.ui.menus"> + <menuContribution + locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions"> + <toolbar + id="org.eclipse.m2e.profiles.ui.toolbars.selectMavenProfilesToolbar"> + <command + commandId="org.eclipse.m2e.profiles.ui.commands.selectMavenProfileCommand" + icon="icons/maven-profiles.gif" + id="org.eclipse.m2e.profiles.ui.toolbars.selectMavenProfilesCommand" + tooltip="%Select_Maven_Profiles_Cmd"> + </command> + </toolbar> + </menuContribution> + </extension> +</plugin> diff --git a/org.eclipse.m2e.profiles.ui/pom.xml b/org.eclipse.m2e.profiles.ui/pom.xml new file mode 100644 index 00000000..d4957bdc --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/pom.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.eclipse.m2e</groupId> + <artifactId>m2e-core</artifactId> + <version>1.5.0-SNAPSHOT</version> + </parent> + + <artifactId>org.eclipse.m2e.profiles.ui</artifactId> + + <name>Maven Profile Manager UI</name> + + <packaging>eclipse-plugin</packaging> +</project>
\ No newline at end of file diff --git a/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/MavenProfilesUIActivator.java b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/MavenProfilesUIActivator.java new file mode 100644 index 00000000..73929686 --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/MavenProfilesUIActivator.java @@ -0,0 +1,29 @@ +/************************************************************************************* + * Copyright (c) 2011-2014 Red Hat, Inc. and others. + * 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: + * Fred Bricon / JBoss by Red Hat - Initial implementation. + ************************************************************************************/ +package org.eclipse.m2e.profiles.ui.internal; + +import org.eclipse.ui.plugin.AbstractUIPlugin; + +/** + * The activator class controls the plug-in life cycle + * + * @since 1.5.0 + */ +public class MavenProfilesUIActivator extends AbstractUIPlugin { + + public static final String PLUGIN_ID = "org.eclipse.m2e.profiles.ui"; + + /** + * The constructor + */ + public MavenProfilesUIActivator() { + } +} diff --git a/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/Messages.java b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/Messages.java new file mode 100644 index 00000000..b64d567d --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/Messages.java @@ -0,0 +1,59 @@ +/************************************************************************************* + * Copyright (c) 2011-2014 Red Hat, Inc. and others. + * 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: + * Fred Bricon / JBoss by Red Hat - Initial implementation. + ************************************************************************************/ +package org.eclipse.m2e.profiles.ui.internal; + +import org.eclipse.osgi.util.NLS; + +/** + * + * @author Fred Bricon + * @since 1.5.0 + */ +public class Messages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.m2e.profiles.ui.internal.messages"; //$NON-NLS-1$ + + public static String ProfileManager_Updating_maven_profiles; + public static String ProfileSelectionHandler_Loading_maven_profiles; + public static String ProfileSelectionHandler_Maven_Builder_still_processing; + public static String ProfileSelectionHandler_multiple_definitions; + public static String ProfileSelectionHandler_Select_some_maven_projects; + public static String ProfileSelectionHandler_Unable_to_open_profile_dialog; + public static String SelectProfilesDialog_autoactivated; + public static String SelectProfilesDialog_Activate_menu; + public static String SelectProfilesDialog_Active_Profiles_for_Project; + public static String SelectProfilesDialog_Available_profiles; + public static String SelectProfilesDialog_Warning_Common_profiles; + public static String SelectProfilesDialog_deactivated; + public static String SelectProfilesDialog_Deactivate_menu; + public static String SelectProfilesDialog_DeselectAll; + public static String SelectProfilesDialog_Force_update; + public static String SelectProfilesDialog_Maven_profile_selection; + public static String SelectProfilesDialog_Move_Down; + public static String SelectProfilesDialog_Move_Up; + public static String SelectProfilesDialog_No_Common_Profiles; + public static String SelectProfilesDialog_Offline; + public static String SelectProfilesDialog_Profile_id_header; + public static String SelectProfilesDialog_Profile_source_header; + public static String SelectProfilesDialog_Project_has_no_available_profiles; + public static String SelectProfilesDialog_Read_Only_profiles; + public static String SelectProfilesDialog_Select_active_profiles_for_selected_projects; + public static String SelectProfilesDialog_Select_Maven_profiles; + public static String SelectProfilesDialog_Select_the_active_Maven_profiles; + public static String SelectProfilesDialog_SelectAll; + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/actions/GenericCommandActionDelegate.java b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/actions/GenericCommandActionDelegate.java new file mode 100644 index 00000000..532c64ad --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/actions/GenericCommandActionDelegate.java @@ -0,0 +1,248 @@ +/******************************************************************************* + * Copyright (c) 2006 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + * Fred Bricon / Red Hat - minor refactoring + * + * Original code taken from <a href="http://wiki.eclipse.org/Platform_Command_Framework#Using_an_IActionDelegate_to_execute_a_command"> + * http://wiki.eclipse.org/Platform_Command_Framework#Using_an_IActionDelegate_to_execute_a_command</a> + ******************************************************************************/ +package org.eclipse.m2e.profiles.ui.internal.actions; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.IParameter; +import org.eclipse.core.commands.Parameterization; +import org.eclipse.core.commands.ParameterizedCommand; +import org.eclipse.core.commands.common.NotDefinedException; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExecutableExtension; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IEditorActionDelegate; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants; + +/** + * This action delegate can be used to specify a command with or without + * parameters be called from an <action/> specified in actionSets, + * editorActions, viewActions, or popupMenus. + */ +public class GenericCommandActionDelegate implements + IWorkbenchWindowActionDelegate, IViewActionDelegate, + IEditorActionDelegate, IObjectActionDelegate, IExecutableExtension { + + /** + * The commandId parameter needed when using the <class/> form for + * this IActionDelegate. Value is "commandId". + */ + public static final String PARM_COMMAND_ID = "commandId"; //$NON-NLS-1$ + + private String commandId = null; + + private Map<?, ?> parameterMap = null; + + private ParameterizedCommand parameterizedCommand = null; + + private IHandlerService handlerService = null; + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose() + */ + public void dispose() { + handlerService = null; + parameterizedCommand = null; + parameterMap = null; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction) + */ + public void run(IAction action) { + if (handlerService == null) { + // what, no handler service ... no problem + return; + } + try { + if (commandId != null) { + handlerService.executeCommand(commandId, null); + } else if (parameterizedCommand != null) { + handlerService.executeCommand(parameterizedCommand, null); + } + // else there is no command for this delegate + } catch (Exception e) { + // exceptions reduced for brevity + // and we won't just do a print out :-) + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, + * org.eclipse.jface.viewers.ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + // we don't care, handlers get their selection from the + // ExecutionEvent application context + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, + * java.lang.String, java.lang.Object) + */ + public void setInitializationData(IConfigurationElement config, + String propertyName, Object data) throws CoreException { + String id = config.getAttribute(IWorkbenchRegistryConstants.ATT_ID); + // save the data until our init(*) call, where we can get + // the services. + if (data instanceof String) { + commandId = (String) data; + } else if (data instanceof Map) { + parameterMap = (Map<?, ?>) data; + if (parameterMap.get(PARM_COMMAND_ID) == null) { + Status status = new Status(IStatus.ERROR, + "org.jboss.tools.maven.ui.generic", "The '" + id + + "' action won't work without a commandId"); + throw new CoreException(status); + } + } else { + Status status = new Status( + IStatus.ERROR, + "org.jboss.tools.maven.ui.generic", + "The '" + + id + + "' action won't work without some initialization parameters"); + throw new CoreException(status); + } + } + + /** + * Build a command from the executable extension information. + * + * @param commandService + * to get the Command object + */ + private void createCommand(ICommandService commandService) { + String id = (String) parameterMap.get(PARM_COMMAND_ID); + if (id == null) { + return; + } + if (parameterMap.size() == 1) { + commandId = id; + return; + } + try { + Command cmd = commandService.getCommand(id); + if (!cmd.isDefined()) { + // command not defined? no problem ... + return; + } + ArrayList<Parameterization> parameters = new ArrayList<Parameterization>(); + Iterator<?> i = parameterMap.keySet().iterator(); + while (i.hasNext()) { + String parmName = (String) i.next(); + if (PARM_COMMAND_ID.equals(parmName)) { + continue; + } + IParameter parm = cmd.getParameter(parmName); + if (parm == null) { + // asking for a bogus parameter? No problem + return; + } + parameters.add(new Parameterization(parm, (String) parameterMap + .get(parmName))); + } + parameterizedCommand = new ParameterizedCommand(cmd, + (Parameterization[]) parameters + .toArray(new Parameterization[parameters.size()])); + } catch (NotDefinedException e) { + // command is bogus? No problem, we'll do nothing. + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow) + */ + public void init(IWorkbenchWindow window) { + if (handlerService != null) { + // already initialized + return; + } + + handlerService = (IHandlerService) window + .getService(IHandlerService.class); + if (parameterMap != null) { + ICommandService commandService = (ICommandService) window + .getService(ICommandService.class); + createCommand(commandService); + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IViewActionDelegate#init(org.eclipse.ui.IViewPart) + */ + public void init(IViewPart view) { + init(view.getSite().getWorkbenchWindow()); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IEditorActionDelegate#setActiveEditor(org.eclipse.jface.action.IAction, + * org.eclipse.ui.IEditorPart) + */ + public void setActiveEditor(IAction action, IEditorPart targetEditor) { + // we don't actually care about the active editor, since that + // information is in the ExecutionEvent application context + // but we need to make sure we're initialized. + if (targetEditor != null) { + init(targetEditor.getSite().getWorkbenchWindow()); + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction, + * org.eclipse.ui.IWorkbenchPart) + */ + public void setActivePart(IAction action, IWorkbenchPart targetPart) { + // we don't actually care about the active part, since that + // information is in the ExecutionEvent application context + // but we need to make sure we're initialized. + if (targetPart != null) { + init(targetPart.getSite().getWorkbenchWindow()); + } + } +} + diff --git a/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/actions/ProfileSelectionHandler.java b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/actions/ProfileSelectionHandler.java new file mode 100644 index 00000000..43493c1c --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/actions/ProfileSelectionHandler.java @@ -0,0 +1,368 @@ +/************************************************************************************* + * Copyright (c) 2011-2014 Red Hat, Inc. and others. + * 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: + * Fred Bricon / JBoss by Red Hat - Initial implementation. + ************************************************************************************/ +package org.eclipse.m2e.profiles.ui.internal.actions; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.WorkspaceJob; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +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.SubMonitor; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.IJobChangeListener; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.m2e.core.MavenPlugin; +import org.eclipse.m2e.core.internal.IMavenConstants; +import org.eclipse.m2e.core.project.IMavenProjectFacade; +import org.eclipse.m2e.core.ui.internal.actions.SelectionUtil; +import org.eclipse.m2e.profiles.core.internal.IProfileManager; +import org.eclipse.m2e.profiles.core.internal.MavenProfilesCoreActivator; +import org.eclipse.m2e.profiles.core.internal.ProfileState; +import org.eclipse.m2e.profiles.core.internal.ProfileData; +import org.eclipse.m2e.profiles.ui.internal.MavenProfilesUIActivator; +import org.eclipse.m2e.profiles.ui.internal.Messages; +import org.eclipse.m2e.profiles.ui.internal.dialog.ProfileSelection; +import org.eclipse.m2e.profiles.ui.internal.dialog.SelectProfilesDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkingSet; +import org.eclipse.ui.handlers.HandlerUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Handles profile selection commands. + * + * @author Fred Bricon + * @since 1.5.0 + */ +public class ProfileSelectionHandler extends AbstractHandler { + + private static final Logger log = LoggerFactory.getLogger(ProfileSelectionHandler.class); + + /** + * Opens the Maven profile selection Dialog window. + */ + public Object execute(ExecutionEvent event) throws ExecutionException { + IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event); + Set<IMavenProjectFacade> facades = getSelectedMavenProjects(event); + + if (facades.isEmpty()) { + display(window, Messages.ProfileSelectionHandler_Select_some_maven_projects); + return null; + } + + final IProfileManager profileManager = MavenProfilesCoreActivator.getDefault().getProfileManager(); + + GetProfilesJob getProfilesJob = new GetProfilesJob(facades, profileManager); + getProfilesJob.addJobChangeListener(onProfilesFetched(getProfilesJob, facades, profileManager, window.getShell())); + getProfilesJob.setUser(true); + getProfilesJob.schedule(); + return Status.OK_STATUS; + } + + private IJobChangeListener onProfilesFetched(final GetProfilesJob getProfilesJob, final Set<IMavenProjectFacade> facades, final IProfileManager profileManager, final Shell shell) { + return new JobChangeAdapter() { + + @Override + public void done(IJobChangeEvent event) { + if (getProfilesJob.getResult().isOK()) { + shell.getDisplay().syncExec(new Runnable() { + + public void run() { + List<ProfileSelection> sharedProfiles = getProfilesJob.getSharedProfiles(); + Map<IMavenProjectFacade, List<ProfileData>> allProfiles = getProfilesJob.getAllProfiles(); + final SelectProfilesDialog dialog = new SelectProfilesDialog(shell, + facades, + sharedProfiles); + if(dialog.open() == Dialog.OK) { + Job job = new UpdateProfilesJob(allProfiles, sharedProfiles, profileManager, dialog); + job.setRule( MavenPlugin.getProjectConfigurationManager().getRule()); + job.schedule(); + } + } + }); + + } + } + }; + } + + private void display(IWorkbenchWindow window, String message) { + MessageDialog.openInformation( + window.getShell(), + Messages.SelectProfilesDialog_Select_Maven_profiles, + message); + } + + /** + * Returns an IMavenProjectFacade from the selected IResource, or from the + * active editor + * + * @param event + * @return the selected IMavenProjectFacade + */ + private Set<IMavenProjectFacade> getSelectedMavenProjects(ExecutionEvent event) { + ISelection selection = HandlerUtil.getCurrentSelection(event); + IProject[] projects = SelectionUtil.getProjects(selection, false); + Set<IMavenProjectFacade> facades = new HashSet<IMavenProjectFacade>(); + try { + if (projects.length == 0) { + IEditorInput input = HandlerUtil.getActiveEditorInput(event); + if (input instanceof IFileEditorInput) { + IFileEditorInput fileInput = (IFileEditorInput) input; + projects = new IProject[] { fileInput.getFile().getProject() }; + } + } + IProgressMonitor monitor = new NullProgressMonitor(); + for (IProject p : projects) { + if (p != null && p.isAccessible() && p.hasNature(IMavenConstants.NATURE_ID)) { + IFile pom = p.getFile(IMavenConstants.POM_FILE_NAME); + IMavenProjectFacade facade = MavenPlugin.getMavenProjectRegistry().create(pom, true, monitor); + facades.add(facade); + } + } + } catch (CoreException e) { + log.error("Unable to select Maven projects", e); + } + + return facades; + } + + class GetProfilesJob extends Job { + + private IProfileManager profileManager; + private Set<IMavenProjectFacade> facades; + private Map<IMavenProjectFacade, List<ProfileData>> allProfiles; + private List<ProfileSelection> sharedProfiles; + + private GetProfilesJob(final Set<IMavenProjectFacade> facades, IProfileManager profileManager) { + super(Messages.ProfileSelectionHandler_Loading_maven_profiles); + this.facades = facades; + this.profileManager = profileManager; + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + this.allProfiles = getAllProfiles(facades, profileManager); + this.sharedProfiles = getSharedProfiles(allProfiles); + } catch (CoreException e) { + return new Status(IStatus.ERROR, MavenProfilesUIActivator.PLUGIN_ID, + Messages.ProfileSelectionHandler_Unable_to_open_profile_dialog, e); + } + return Status.OK_STATUS; + } + + private List<ProfileSelection> getSharedProfiles( + Map<IMavenProjectFacade, List<ProfileData>> projectProfilesMap) { + + List<ProfileData> currentSelection = null; + List<List<ProfileData>> projectProfiles = new ArrayList<List<ProfileData>>(projectProfilesMap.values()); + int smallestSize = Integer.MAX_VALUE; + for (List<ProfileData> profiles : projectProfiles) { + int size = profiles.size(); + if (size < smallestSize) { + smallestSize = size; + currentSelection = profiles; + } + } + projectProfiles.remove(currentSelection); + + // Init the smallest profiles selection possible + List<ProfileSelection> selection = new ArrayList<ProfileSelection>(); + for (ProfileData p : currentSelection) { + ProfileSelection ps = new ProfileSelection(); + ps.setId(p.getId()); + ps.setActivationState(p.getActivationState()); + ps.setAutoActive(p.isAutoActive()); + ps.setSource(p.getSource()); + ps.setSelected(p.isUserSelected()); + selection.add(ps); + } + + if (!projectProfiles.isEmpty()) { + // Restrict to the common profiles only + Iterator<ProfileSelection> ite = selection.iterator(); + + while (ite.hasNext()) { + ProfileSelection p = ite.next(); + for (List<ProfileData> statuses : projectProfiles) { + ProfileData s = hasProfile(p.getId(), statuses); + if (s == null) { + // remove any non-common profile selection + ite.remove(); + break; + } + // reset non common settings + if (p.getAutoActive() != null && !p.getAutoActive().equals(s.isAutoActive())) { + p.setAutoActive(null); + } + if (p.getSource() != null && !p.getSource().equals(s.getSource())) { + p.setSource(Messages.ProfileSelectionHandler_multiple_definitions); + } + if (p.getSelected() != null && !p.getSelected().equals(s.isUserSelected())) { + p.setSelected(null); + } + if (p.getActivationState() != null && !p.getActivationState().equals(s.getActivationState())) { + p.setActivationState(null); + p.setAutoActive(null); + } + } + } + } + + return selection; + } + + private ProfileData hasProfile(String id, List<ProfileData> statuses) { + for (ProfileData p : statuses) { + if (id.equals(p.getId())) { + return p; + } + } + return null; + } + + private Map<IMavenProjectFacade, List<ProfileData>> getAllProfiles(final Set<IMavenProjectFacade> facades, + final IProfileManager profileManager) throws CoreException { + Map<IMavenProjectFacade, List<ProfileData>> allProfiles = + new HashMap<IMavenProjectFacade, List<ProfileData>>(facades.size()); + IProgressMonitor monitor = new NullProgressMonitor(); + for (IMavenProjectFacade facade : facades) { + allProfiles.put(facade, profileManager.getProfileDatas(facade, monitor)); + } + return allProfiles; + } + + public List<ProfileSelection> getSharedProfiles() { + return sharedProfiles; + } + + public Map<IMavenProjectFacade, List<ProfileData>> getAllProfiles() { + return allProfiles; + } + } + + class UpdateProfilesJob extends WorkspaceJob { + + private Map<IMavenProjectFacade, List<ProfileData>> allProfiles; + private List<ProfileSelection> sharedProfiles; + private IProfileManager profileManager; + private SelectProfilesDialog dialog; + + private UpdateProfilesJob(Map<IMavenProjectFacade, List<ProfileData>> allProfiles, + List<ProfileSelection> sharedProfiles, IProfileManager profileManager, SelectProfilesDialog dialog) { + super(Messages.ProfileManager_Updating_maven_profiles); + this.allProfiles = allProfiles; + this.sharedProfiles = sharedProfiles; + this.profileManager = profileManager; + this.dialog = dialog; + } + + public IStatus runInWorkspace(IProgressMonitor monitor) { + try { + SubMonitor progress = SubMonitor.convert(monitor, Messages.ProfileManager_Updating_maven_profiles, 100); + SubMonitor subProgress = SubMonitor.convert(progress.newChild(5), allProfiles.size() * 100); + for (Map.Entry<IMavenProjectFacade, List<ProfileData>> entry : allProfiles.entrySet()) { + if (progress.isCanceled()) { + throw new OperationCanceledException(); + } + IMavenProjectFacade facade = entry.getKey(); + List<String> activeProfiles = getActiveProfiles(sharedProfiles, entry.getValue()); + + profileManager.updateActiveProfiles(facade, activeProfiles, + dialog.isOffline(), dialog.isForceUpdate(), subProgress.newChild(100)); + } + } catch (CoreException ex) { + log.error("Unable to update Maven profiles", ex); + return ex.getStatus(); + } + return Status.OK_STATUS; + } + + private List<String> getActiveProfiles( + List<ProfileSelection> sharedProfiles, + List<ProfileData> availableProfiles) { + List<String> ids = new ArrayList<String>(); + + for (ProfileData st : availableProfiles) { + ProfileSelection selection = findSelectedProfile(st.getId(), sharedProfiles); + String id = null; + boolean isDisabled = false; + if (selection == null) { + // was not displayed. Use existing value. + if (st.isUserSelected()) { + id = st.getId(); + isDisabled = st.getActivationState().equals(ProfileState.Disabled); + } + } else { + if (null == selection.getSelected()) { + // Value was displayed but its state is unknown, use + // previous state + if (st.isUserSelected()) { + id = st.getId(); + isDisabled = st.getActivationState().equals(ProfileState.Disabled); + } + } else { + // Value was displayed and is consistent + if (Boolean.TRUE.equals(selection.getSelected())) { + id = selection.getId(); + isDisabled = selection.getActivationState().equals(ProfileState.Disabled); + } + } + } + + if (id != null) { + if (isDisabled) { + id = "!" + id; //$NON-NLS-1$ + } + ids.add(id); + } + } + return ids; + } + + private ProfileSelection findSelectedProfile(String id, + List<ProfileSelection> sharedProfiles) { + for (ProfileSelection sel : sharedProfiles) { + if (id.equals(sel.getId())) { + return sel; + } + } + return null; + } + } +} diff --git a/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/dialog/ProfileSelection.java b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/dialog/ProfileSelection.java new file mode 100644 index 00000000..a6443126 --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/dialog/ProfileSelection.java @@ -0,0 +1,64 @@ +/************************************************************************************* + * Copyright (c) 2011-2014 Red Hat, Inc. and others. + * 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: + * Fred Bricon / JBoss by Red Hat - Initial implementation. + ************************************************************************************/ +package org.eclipse.m2e.profiles.ui.internal.dialog; + +import org.eclipse.m2e.profiles.core.internal.ProfileState; + +/* Model of a Maven Profile Selection + * + * @author Fred Bricon + * @since 1.5.0 + */ +public class ProfileSelection { + private String id; + private Boolean autoActive; + private Boolean selected; + private ProfileState activationState; + private String source; + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + public Boolean getAutoActive() { + return autoActive; + } + public void setAutoActive(Boolean autoActive) { + this.autoActive = autoActive; + } + public Boolean getSelected() { + return selected; + } + public void setSelected(Boolean selected) { + this.selected = selected; + } + public ProfileState getActivationState() { + return activationState; + } + public void setActivationState(ProfileState activationState) { + this.activationState = activationState; + } + public String getSource() { + return source; + } + public void setSource(String source) { + this.source = source; + } + + public String toMavenString() { + String s = id; + if (ProfileState.Disabled == activationState) { + s = "!"+id; + } + return s; + } +} diff --git a/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/dialog/ProfileSelectionStatus.java b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/dialog/ProfileSelectionStatus.java new file mode 100644 index 00000000..dafe292d --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/dialog/ProfileSelectionStatus.java @@ -0,0 +1,21 @@ +/************************************************************************************* + * Copyright (c) 2011-2014 Red Hat, Inc. and others. + * 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: + * Fred Bricon / JBoss by Red Hat - Initial implementation. + ************************************************************************************/ +package org.eclipse.m2e.profiles.ui.internal.dialog; + +/** + * Enumeration of all valid Profile selection statuses. + * + * @author Fred Bricon + * @since 1.5.0 + */ +public enum ProfileSelectionStatus { + Undefined, Inactivated, Activated, Disabled +} diff --git a/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/dialog/ProfileUtil.java b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/dialog/ProfileUtil.java new file mode 100644 index 00000000..12932715 --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/dialog/ProfileUtil.java @@ -0,0 +1,47 @@ +/************************************************************************************* + * Copyright (c) 2011-2014 Red Hat, Inc. and others. + * 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: + * JBoss by Red Hat - Initial implementation. + ************************************************************************************/ +package org.eclipse.m2e.profiles.ui.internal.dialog; + +import java.util.Collection; + +/** + * Utility class to manipulate Profiles + * + * @author Fred Bricon + * @since 1.5.0 + */ +public class ProfileUtil { + + private ProfileUtil(){} + + private static final String COMMA = ", "; + + /** + * Turns a {@link ProfileSelection} collection as a String, joined by a comma separator. + */ + public static String toString(Collection<ProfileSelection> profiles) { + StringBuilder sb = new StringBuilder(); + if(profiles != null && !profiles.isEmpty()) { + boolean addComma = false; + for (ProfileSelection ps : profiles) { + if (ps !=null && Boolean.TRUE.equals(ps.getSelected())) { + if (addComma) { + sb.append(COMMA); + } + sb.append(ps.toMavenString()); + addComma = true; + } + } + } + return sb.toString(); + } + +} diff --git a/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/dialog/SelectProfilesDialog.java b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/dialog/SelectProfilesDialog.java new file mode 100644 index 00000000..7c011272 --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/dialog/SelectProfilesDialog.java @@ -0,0 +1,502 @@ +/************************************************************************************* + * Copyright (c) 2011-2014 Red Hat, Inc. and others. + * 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: + * Fred Bricon / JBoss by Red Hat - Initial implementation. + ************************************************************************************/ +package org.eclipse.m2e.profiles.ui.internal.dialog; + +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITableColorProvider; +import org.eclipse.jface.viewers.ITableFontProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.m2e.core.MavenPlugin; +import org.eclipse.m2e.core.project.IMavenProjectFacade; +import org.eclipse.m2e.profiles.core.internal.ProfileState; +import org.eclipse.m2e.profiles.ui.internal.Messages; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +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.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; + +/** + * Maven Profile selection dialog. + * + * @author Fred Bricon + * @since 1.5.0 + */ +@SuppressWarnings("synthetic-access") +public class SelectProfilesDialog extends TitleAreaDialog implements + IMenuListener { + + private static int PROFILE_ID_COLUMN = 0; + private static int SOURCE_COLUMN = 1; + + private CheckboxTableViewer profileTableViewer; + private Button offlineModeBtn; + private Button forceUpdateBtn; + private Text profilesText; + + private boolean offlineMode ; + private boolean forceUpdate; + + List<ProfileSelection> sharedProfiles; + Set<IMavenProjectFacade> facades; + IMavenProjectFacade facade; + + final Action activationAction = new ChangeProfileStateAction(ProfileState.Active); + + final Action deActivationAction = new ChangeProfileStateAction(ProfileState.Disabled); + private Label warningImg; + private Label warningLabel; + + public SelectProfilesDialog(Shell parentShell, Set<IMavenProjectFacade> facades, + List<ProfileSelection> sharedProfiles) { + super(parentShell); + setShellStyle(super.getShellStyle() | SWT.RESIZE | SWT.MODELESS); + offlineMode = MavenPlugin.getMavenConfiguration().isOffline(); + this.facades = facades; + if(facades.size() == 1){ + facade = facades.iterator().next(); + } + this.sharedProfiles = sharedProfiles; + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText(Messages.SelectProfilesDialog_Select_Maven_profiles); + } + + + + @Override + protected Control createDialogArea(Composite parent) { + Composite area = (Composite) super.createDialogArea(parent); + + Composite container = new Composite(area, SWT.NONE); + container.setEnabled(true); + + GridLayout layout = new GridLayout(3, false); + layout.marginLeft = 12; + container.setLayout(layout); + container.setLayoutData(new GridData(GridData.FILL_BOTH)); + + setTitle(Messages.SelectProfilesDialog_Maven_profile_selection); + String text; + boolean hasProfiles = !sharedProfiles.isEmpty(); + if (facade == null) { + text = NLS.bind(Messages.SelectProfilesDialog_Select_active_profiles_for_selected_projects, + facades.size() + ); + } else { + text = NLS.bind( + Messages.SelectProfilesDialog_Select_the_active_Maven_profiles, + facade.getProject().getName()); + if (hasProfiles) { + displayProfilesAsText(container); + } + } + setMessage(text); + + if (hasProfiles && facade == null) { + displayWarning(container); + } + + Label lblAvailable = new Label(container, SWT.NONE); + lblAvailable.setLayoutData(new GridData(SWT.WRAP, SWT.CENTER, true, + false, 2, 1)); + + String textLabel = getAvailableText(hasProfiles); + lblAvailable.setText(textLabel); + + if (hasProfiles) { + + displayProfilesTable(container); + + addSelectionButton(container, Messages.SelectProfilesDialog_SelectAll, true); + addSelectionButton(container, Messages.SelectProfilesDialog_DeselectAll, false); + addActivationButton(container, "Activate", ProfileState.Active); + addActivationButton(container, "Deactivate", ProfileState.Disabled); + offlineModeBtn = addCheckButton(container, Messages.SelectProfilesDialog_Offline, offlineMode); + forceUpdateBtn = addCheckButton(container, Messages.SelectProfilesDialog_Force_update, forceUpdate); + } + + return area; + } + + private void displayWarning(Composite container) { + warningImg = new Label(container, SWT.CENTER); + warningLabel = new Label(container, SWT.NONE); + warningLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1)); + GridDataFactory.fillDefaults().align(SWT.LEFT, SWT.CENTER).applyTo(warningImg); + warningImg.setImage(JFaceResources.getImage(DLG_IMG_MESSAGE_WARNING)); + warningLabel.setText( Messages.SelectProfilesDialog_Warning_Common_profiles); + } + + private String getAvailableText(boolean hasProfiles) { + String textLabel; + if (hasProfiles) { + textLabel = Messages.SelectProfilesDialog_Available_profiles; + } else { + if (facade == null) { + textLabel = NLS.bind(Messages.SelectProfilesDialog_No_Common_Profiles, + facades.size()); + } else { + textLabel = + NLS.bind(Messages.SelectProfilesDialog_Project_has_no_available_profiles, + facade.getProject().getName()); + } + } + return textLabel; + } + + private void displayProfilesTable(Composite container) { + GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 4); + gd.heightHint = 200; + gd.widthHint = 500; + + profileTableViewer = CheckboxTableViewer.newCheckList(container, SWT.BORDER | SWT.MULTI); + Table table = profileTableViewer.getTable(); + table.setFocus(); + table.setLayoutData(gd); + table.setLinesVisible(true); + table.setHeaderVisible(true); + + TableColumn profileColumn = new TableColumn(table, SWT.NONE); + profileColumn.setText(Messages.SelectProfilesDialog_Profile_id_header); + profileColumn.setWidth(350); + + TableColumn sourceColumn = new TableColumn(table, SWT.NONE); + sourceColumn.setText(Messages.SelectProfilesDialog_Profile_source_header); + sourceColumn.setWidth(120); + + + profileTableViewer.setContentProvider(ArrayContentProvider.getInstance()); + + profileTableViewer.setLabelProvider(new ProfileLabelProvider(container + .getFont())); + + + profileTableViewer.addCheckStateListener(new ICheckStateListener() { + + public void checkStateChanged(CheckStateChangedEvent event) { + ProfileSelection profile = (ProfileSelection) event.getElement(); + if (profileTableViewer.getGrayed(profile)) { + profileTableViewer.setGrayed(profile, false); + } + profile.setSelected(profileTableViewer.getChecked(profile)); + if (Boolean.FALSE.equals(profile.getSelected()) + || profile.getActivationState() == null) { + profile.setActivationState(ProfileState.Active); + } + + updateProfilesAsText(); + profileTableViewer.refresh(); + } + }); + + profileTableViewer.setInput(sharedProfiles); + + createMenu(); + } + + private void displayProfilesAsText(Composite container) { + Label profilesLabel = new Label(container, SWT.NONE); + profilesLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1)); + profilesLabel.setText(NLS.bind(Messages.SelectProfilesDialog_Active_Profiles_for_Project, + facade.getProject().getName())); + + profilesText = new Text(container, SWT.BORDER); + profilesText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1)); + profilesText.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GRAY)); + profilesText.setEditable(false); + profilesText.setToolTipText(Messages.SelectProfilesDialog_Read_Only_profiles); + + updateProfilesAsText(); + } + + private void updateProfilesAsText() { + if (profilesText != null) { + profilesText.setText(ProfileUtil.toString(sharedProfiles)); + } + } + + private Button addCheckButton(Composite container, String label, boolean selected) { + Button checkBtn = new Button(container, SWT.CHECK); + checkBtn.setText(label); + checkBtn.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, + true, false, 2, 1)); + checkBtn.setSelection(selected); + return checkBtn; + } + + private Button addSelectionButton(Composite container, String label, final boolean ischecked) { + Button button = new Button(container, SWT.NONE); + button.setLayoutData(new GridData(SWT.FILL, SWT.UP, + false, false, 1, 1)); + button.setText(label); + button.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + profileTableViewer.setAllGrayed(false); + for (ProfileSelection profile : sharedProfiles) { + profileTableViewer.setChecked(profile, ischecked); + profile.setSelected(ischecked); + if (!ischecked || profile.getActivationState() == null) { + profile.setActivationState(ProfileState.Active); + } + } + refresh(); + } + + public void widgetDefaultSelected(SelectionEvent e) { + + } + }); + + return button; + } + + private Button addActivationButton(Composite container, String label, final ProfileState state) { + Button button = new Button(container, SWT.NONE); + button.setLayoutData(new GridData(SWT.FILL, SWT.UP, + false, false, 1, 1)); + button.setText(label); + button.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + ISelection s = profileTableViewer.getSelection(); + if (s instanceof IStructuredSelection) { + IStructuredSelection sel = (IStructuredSelection) s; + setActivationState(sel, state); + } + refresh(); + } + + public void widgetDefaultSelected(SelectionEvent e) { + + } + }); + + return button; + } + + + @Override + protected void createButtonsForButtonBar(Composite parent) { + if (profileTableViewer != null) { + createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); + } + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + } + + @Override + protected void okPressed() { + if (profileTableViewer != null) { + offlineMode = offlineModeBtn.getSelection(); + forceUpdate = forceUpdateBtn.getSelection(); + } + super.okPressed(); + } + + private void createMenu() { + MenuManager menuMgr = new MenuManager(); + Menu contextMenu = menuMgr.createContextMenu(profileTableViewer + .getControl()); + menuMgr.addMenuListener(this); + profileTableViewer.getControl().setMenu(contextMenu); + menuMgr.setRemoveAllWhenShown(true); + + for (ProfileSelection p : sharedProfiles) { + Boolean selected = p.getSelected(); + if (selected ==null || p.getActivationState() == null) { + profileTableViewer.setGrayed(p, true); + profileTableViewer.setChecked(p, true); + } else { + profileTableViewer.setChecked(p, selected ); + } + } + } + + public void menuAboutToShow(IMenuManager manager) { + + IStructuredSelection selection = (IStructuredSelection) profileTableViewer + .getSelection(); + if (!selection.isEmpty()) { + boolean multiSelection = selection.size() > 1; + ProfileState state = null; + String selectionText; + String text; + if (multiSelection) { + selectionText = "selected profiles"; + } else { + ProfileSelection entry = (ProfileSelection) selection.getFirstElement(); + state = entry.getActivationState(); + selectionText = entry.getId(); + } + + if ( state == null || ProfileState.Disabled.equals(state)) { + text = Messages.SelectProfilesDialog_Activate_menu; + activationAction.setText(NLS.bind(text, selectionText)); + manager.add(activationAction); + } + if( !ProfileState.Disabled.equals(state)) { + text = Messages.SelectProfilesDialog_Deactivate_menu; + deActivationAction.setText(NLS.bind(text, selectionText)); + manager.add(deActivationAction); + } + } + } + + public boolean isOffline() { + return offlineMode; + } + + public boolean isForceUpdate() { + return forceUpdate; + } + + private void setActivationState(final IStructuredSelection sel, ProfileState state) { + if (sel == null) return; + Iterator<?> ite = sel.iterator(); + while (ite.hasNext()) { + Object o = ite.next(); + if (o instanceof ProfileSelection) { + ProfileSelection ps = (ProfileSelection) o; + ps.setActivationState(state); + profileTableViewer.setGrayed(ps, false); + if (ProfileState.Disabled.equals(state)) { + profileTableViewer.setChecked(ps, true); + ps.setSelected(true); + } + } + } + } + + + private void refresh() { + profileTableViewer.refresh(); + updateProfilesAsText(); + } + + + private class ChangeProfileStateAction extends Action { + + private final ProfileState state; + + public ChangeProfileStateAction(ProfileState state) { + this.state = state; + } + + @Override + public void run() { + IStructuredSelection selection = (IStructuredSelection) profileTableViewer + .getSelection(); + if (!selection.isEmpty()) { + setActivationState(selection, state); + refresh(); + } + super.run(); + } + } + + private class ProfileLabelProvider extends LabelProvider implements + ITableLabelProvider, ITableFontProvider, ITableColorProvider { + + private Font implicitActivationFont; + + private Color inactiveColor; + + public ProfileLabelProvider(Font defaultFont) { + FontData[] fds = defaultFont.getFontData(); + for (FontData fd : fds) { + fd.setStyle(SWT.ITALIC); + } + implicitActivationFont = new Font(defaultFont.getDevice(), fds); + inactiveColor = Display.getCurrent().getSystemColor(SWT.COLOR_GRAY); + } + + public Font getFont(Object element, int columnIndex) { + ProfileSelection entry = (ProfileSelection) element; + Font font = null; + if (Boolean.TRUE.equals(entry.getAutoActive()) + && PROFILE_ID_COLUMN == columnIndex) { + font = implicitActivationFont; + } + return font; + } + + public Color getForeground(Object element, int columnIndex) { + ProfileSelection entry = (ProfileSelection) element; + if (ProfileState.Disabled.equals(entry.getActivationState())) { + return inactiveColor; + } + return null; + } + + public Color getBackground(Object element, int columnIndex) { + return null; + } + + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + + public String getColumnText(Object element, int columnIndex) { + ProfileSelection entry = (ProfileSelection) element; + StringBuilder text = new StringBuilder(); + if (entry != null) { + if (columnIndex == PROFILE_ID_COLUMN) { + text.append(entry.getId()); + ProfileState state = entry.getActivationState(); + if (Boolean.TRUE.equals(entry.getSelected()) + && state == ProfileState.Disabled) { + text.append(Messages.SelectProfilesDialog_deactivated); + } else if (Boolean.TRUE.equals(entry.getAutoActive())) { + text.append(Messages.SelectProfilesDialog_autoactivated); + } + } else if (columnIndex == SOURCE_COLUMN) { + text.append(entry.getSource()); + } + } + return text.toString(); + } + } +} diff --git a/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/messages.properties b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/messages.properties new file mode 100644 index 00000000..e739a119 --- /dev/null +++ b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/messages.properties @@ -0,0 +1,28 @@ +ProfileManager_Updating_maven_profiles=Updating maven profiles +ProfileSelectionHandler_Loading_maven_profiles=Loading project profiles +ProfileSelectionHandler_Maven_Builder_still_processing=The maven builder has not finished processing the selected project(s) yet. +ProfileSelectionHandler_multiple_definitions=multiple definitions +ProfileSelectionHandler_Select_some_maven_projects=You must select at least one active Maven project +ProfileSelectionHandler_Unable_to_open_profile_dialog=Unable to open the Maven Profile selection dialog +SelectProfilesDialog_Activate_menu=Activate {0} +SelectProfilesDialog_Active_Profiles_for_Project=Active profiles for {0} : +SelectProfilesDialog_autoactivated=\ (auto activated) +SelectProfilesDialog_Available_profiles=Available profiles : +SelectProfilesDialog_Warning_Common_profiles=Only the profiles common to all selected projects are displayed. Other profiles will not be affected. +SelectProfilesDialog_Deactivate_menu=Deactivate {0} +SelectProfilesDialog_deactivated=\ (deactivated) +SelectProfilesDialog_DeselectAll=Deselect all +SelectProfilesDialog_Force_update=Force update +SelectProfilesDialog_Maven_profile_selection=Maven Profile selection +SelectProfilesDialog_Move_Down=Move Down +SelectProfilesDialog_Move_Up=Move Up +SelectProfilesDialog_No_Common_Profiles=There are no common profiles for the {0} selected projects. +SelectProfilesDialog_Offline=Offline +SelectProfilesDialog_Profile_id_header=Profile id +SelectProfilesDialog_Profile_source_header=Source +SelectProfilesDialog_Project_has_no_available_profiles=Project {0} has no available profiles +SelectProfilesDialog_Read_Only_profiles=Active profiles area is read-only +SelectProfilesDialog_Select_active_profiles_for_selected_projects=Select the active Maven profiles for the {0} selected projects. Right-click to (de)activate a profile. +SelectProfilesDialog_Select_Maven_profiles=Select Maven profiles +SelectProfilesDialog_Select_the_active_Maven_profiles=Select the active Maven profiles for project {0}. Right-click to (de)activate a profile. +SelectProfilesDialog_SelectAll=Select All diff --git a/org.eclipse.m2e.sdk.feature/feature.xml b/org.eclipse.m2e.sdk.feature/feature.xml index 2510e7d5..e058a37c 100644 --- a/org.eclipse.m2e.sdk.feature/feature.xml +++ b/org.eclipse.m2e.sdk.feature/feature.xml @@ -112,6 +112,20 @@ version="0.0.0" unpack="false"/> + <plugin + id="org.eclipse.m2e.profiles.ui.source" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.eclipse.m2e.profiles.core.source" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + <!-- source bundles of logback integration --> <plugin @@ -97,6 +97,8 @@ <module>org.eclipse.m2e.lifecyclemapping.defaults</module> <module>org.eclipse.m2e.discovery</module> <module>org.eclipse.m2e.scm</module> + <module>org.eclipse.m2e.profiles.core</module> + <module>org.eclipse.m2e.profiles.ui</module> <!-- common test helpers --> <module>org.eclipse.m2e.tests.common</module> |