/*******************************************************************************
* Copyright (c) 2008 Sonatype, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sonatype, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.m2e.core.project.configurator;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.apache.maven.plugin.MojoExecution;
import org.eclipse.m2e.core.internal.lifecyclemapping.LifecycleMappingConfigurationException;
import org.eclipse.m2e.core.internal.lifecyclemapping.LifecycleMappingFactory;
import org.eclipse.m2e.core.internal.project.registry.MavenProjectFacade;
import org.eclipse.m2e.core.internal.project.registry.ProjectRegistryManager;
import org.eclipse.m2e.core.lifecyclemapping.model.IPluginExecutionMetadata;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
/**
* Abstract base class for customizable lifecycle mappings
*
* @author igor
*/
public abstract class AbstractCustomizableLifecycleMapping extends AbstractLifecycleMapping {
private static Logger log = LoggerFactory.getLogger(AbstractCustomizableLifecycleMapping.class);
public Map<MojoExecutionKey, List<AbstractBuildParticipant>> getBuildParticipants(IMavenProjectFacade projectFacade,
IProgressMonitor monitor) throws CoreException {
log.debug("Build participants for {}", projectFacade.getMavenProject());
Map<MojoExecutionKey, List<AbstractBuildParticipant>> result = new LinkedHashMap<MojoExecutionKey, List<AbstractBuildParticipant>>();
Map<MojoExecutionKey, List<IPluginExecutionMetadata>> mapping = projectFacade.getMojoExecutionMapping();
Map<String, AbstractProjectConfigurator> configurators = getProjectConfigurators(projectFacade);
List<MojoExecution> mojoExecutions = ((MavenProjectFacade) projectFacade).getExecutionPlan(
ProjectRegistryManager.LIFECYCLE_DEFAULT, monitor);
if(mojoExecutions != null) { // null if execution plan could not be calculated
for(MojoExecution mojoExecution : mojoExecutions) {
MojoExecutionKey mojoExecutionKey = new MojoExecutionKey(mojoExecution);
log.debug("Mojo execution key: {}", mojoExecutionKey);
List<IPluginExecutionMetadata> executionMetadatas = mapping.get(mojoExecutionKey);
List<AbstractBuildParticipant> executionMappings = new ArrayList<AbstractBuildParticipant>();
if(executionMetadatas != null) {
for(IPluginExecutionMetadata executionMetadata : executionMetadatas) {
switch(executionMetadata.getAction()) {
case execute:
log.debug("\tAction: {}", executionMetadata.getAction());
executionMappings.add(LifecycleMappingFactory.createMojoExecutionBuildParicipant(projectFacade,
projectFacade.getMojoExecution(mojoExecutionKey, monitor), executionMetadata));
break;
case configurator:
String configuratorId = LifecycleMappingFactory.getProjectConfiguratorId(executionMetadata);
AbstractProjectConfigurator configurator = configurators.get(configuratorId);
if(configurator == null) {
log.debug("\t\tProject configurator with id {} was not found", configuratorId);
break;
}
AbstractBuildParticipant buildParticipant = configurator.getBuildParticipant(projectFacade,
projectFacade.getMojoExecution(mojoExecutionKey, monitor), executionMetadata);
if(buildParticipant != null) {
log.debug("\tAction: {}", executionMetadata.getAction());
log.debug("\t\tProject configurator : id={} class={}", configuratorId, configurator.getClass()
.getName());
log.debug("\t\tBuild participant: {}", buildParticipant.getClass().getName());
executionMappings.add(buildParticipant);
}
break;
case ignore:
case error:
log.debug("\tAction: {}", executionMetadata.getAction());
break;
default:
throw new IllegalArgumentException("Missing handling for action=" + executionMetadata.getAction());
}
}
}
result.put(mojoExecutionKey, executionMappings);
}
}
return result;
}
public List<AbstractProjectConfigurator> getProjectConfigurators(IMavenProjectFacade projectFacade,
IProgressMonitor monitor) {
return new ArrayList<AbstractProjectConfigurator>(getProjectConfigurators(projectFacade).values());
}
private Map<String, AbstractProjectConfigurator> getProjectConfigurators(IMavenProjectFacade projectFacade) {
return LifecycleMappingFactory.getProjectConfigurators(projectFacade);
}
@Override
public boolean hasLifecycleMappingChanged(IMavenProjectFacade newFacade,
ILifecycleMappingConfiguration oldConfiguration, IProgressMonitor monitor) {
if(!getId().equals(newFacade.getLifecycleMappingId())) {
throw new IllegalArgumentException();
}
if(oldConfiguration == null || !getId().equals(oldConfiguration.getLifecycleMappingId())) {
return true;
}
Map<MojoExecutionKey, List<IPluginExecutionMetadata>> oldMappings = oldConfiguration.getMojoExecutionMapping();
for(Map.Entry<MojoExecutionKey, List<IPluginExecutionMetadata>> entry : newFacade.getMojoExecutionMapping()
.entrySet()) {
List<IPluginExecutionMetadata> metadatas = entry.getValue();
List<IPluginExecutionMetadata> oldMetadatas = oldMappings.get(entry.getKey());
if(metadatas == null || metadatas.isEmpty()) {
if(oldMetadatas != null && !oldMetadatas.isEmpty()) {
return true; // different
}
continue; // mapping is null/empty and did not change
}
if(oldMetadatas == null || oldMetadatas.isEmpty()) {
return true;
}
if(metadatas.size() != oldMetadatas.size()) {
return true;
}
for(int i = 0; i < metadatas.size(); i++ ) {
IPluginExecutionMetadata metadata = metadatas.get(i);
IPluginExecutionMetadata oldMetadata = oldMetadatas.get(i);
if(metadata == null) {
if(oldMetadata != null) {
return true;
}
continue;
}
if(oldMetadata == null) {
return true;
}
if(metadata.getAction() != oldMetadata.getAction()) {
return true;
}
switch(metadata.getAction()) {
case ignore:
case execute:
continue;
case error:
// TODO verify error message did not change...
continue;
case configurator:
String configuratorId = LifecycleMappingFactory.getProjectConfiguratorId(metadata);
String oldConfiguratorId = LifecycleMappingFactory.getProjectConfiguratorId(oldMetadata);
if(!eq(configuratorId, oldConfiguratorId)) {
return true;
}
try {
AbstractProjectConfigurator configurator = LifecycleMappingFactory.createProjectConfigurator(metadata);
if(configurator.hasConfigurationChanged(newFacade, oldConfiguration, entry.getKey(), monitor)) {
return true;
}
} catch(LifecycleMappingConfigurationException e) {
// installation problem/misconfiguration
}
continue;
}
}
}
return false;
}
private static <T> boolean eq(T a, T b) {
return a != null ? a.equals(b) : b == null;
}
}