/* * Copyright (C) 2012 Red Hat, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.commonjava.maven.ext.core.impl; import org.apache.maven.model.Build; import org.apache.maven.model.Dependency; import org.apache.maven.model.DependencyManagement; import org.apache.maven.model.Model; import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginExecution; import org.codehaus.plexus.util.xml.Xpp3Dom; import org.commonjava.maven.ext.common.ManipulationException; import org.commonjava.maven.ext.common.model.Project; import org.commonjava.maven.ext.core.ManipulationSession; import org.commonjava.maven.ext.core.state.BOMInjectingState; import org.commonjava.maven.ext.io.PomIO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import static org.commonjava.maven.ext.core.util.IdUtils.ga; /** * Simple manipulator that will look for all module artifacts and construct a BOM that is deployed with the root artifact. It has a predictable naming * scheme making it useful in automated scenarios. Configuration is documented in {@link BOMInjectingState}. */ @Named("bom-builder") @Singleton public class BOMBuilderManipulator implements Manipulator { private static final String POM_DEPLOYER_GID = "org.goots.maven.plugins"; private static final String POM_DEPLOYER_AID = "pom-deployer-maven-plugin"; private static final String POM_DEPLOYER_VID = "1.2"; private static final String POM_DEPLOYER_COORD = ga( POM_DEPLOYER_GID, POM_DEPLOYER_AID ); private static final String IDBOM = "pme-bom"; private final Logger logger = LoggerFactory.getLogger( getClass() ); private PomIO pomIO; private ManipulationSession session; @Inject public BOMBuilderManipulator(PomIO pomIO) { this.pomIO = pomIO; } @Override public void init( final ManipulationSession session ) { this.session = session; session.setState( new BOMInjectingState( session.getUserProperties() ) ); } /** * If enabled, grab the execution root pom (which will be the topmost POM in terms of directory structure). Within that * handle the manipulation of the bom injection. */ @Override public Set<Project> applyChanges( final List<Project> projects ) throws ManipulationException { final BOMInjectingState state = session.getState( BOMInjectingState.class ); if ( !session.isEnabled() || !state.isEnabled() ) { logger.debug("{}: Nothing to do!", getClass().getSimpleName() ); return Collections.emptySet(); } List<Dependency> projectArtifacts = getArtifacts( projects ); for ( final Project project : projects ) { if ( project.isExecutionRoot() ) { logger.info( "Examining {} to add BOM generation.", project ); final Model model = project.getModel(); Build build = model.getBuild(); if ( build == null ) { build = new Build(); model.setBuild( build ); } Model bomModel = createModel( project, IDBOM ); bomModel.setDescription( "PME Generated BOM for other projects to use to align to." ); DependencyManagement dm = new DependencyManagement(); dm.setDependencies( projectArtifacts ); bomModel.setDependencyManagement( dm ); // Write new bom back out. File pmebom = new File( session.getTargetDir(), IDBOM + ".xml" ); session.getTargetDir().mkdir(); pomIO.writeModel( bomModel, pmebom ); final Map<String, Plugin> pluginMap = build.getPluginsAsMap(); if ( !pluginMap.containsKey( POM_DEPLOYER_COORD ) ) { final PluginExecution execution = new PluginExecution(); execution.setId( IDBOM ); execution.setPhase( "install" ); execution.setGoals( Collections.singletonList( "add-pom" ) ); final Plugin plugin = new Plugin(); plugin.setGroupId( POM_DEPLOYER_GID ); plugin.setArtifactId( POM_DEPLOYER_AID ); plugin.setVersion( POM_DEPLOYER_VID ); plugin.addExecution( execution ); plugin.setInherited( false ); build.addPlugin( plugin ); final Xpp3Dom xml = new Xpp3Dom( "configuration" ); final Map<String, Object> config = new HashMap<>(); config.put( "pomName", "target" + File.separatorChar + pmebom.getName() ); config.put( "errorOnMissing", false ); config.put( "artifactId", bomModel.getArtifactId() ); config.put( "groupId", bomModel.getGroupId() ); for ( final Map.Entry<String, Object> entry : config.entrySet() ) { final Xpp3Dom child = new Xpp3Dom( entry.getKey() ); if ( entry.getValue() != null ) { child.setValue( entry.getValue().toString() ); } xml.addChild( child ); } execution.setConfiguration( xml ); } return Collections.singleton( project ); } } return Collections.emptySet(); } private Model createModel( Project project, String s ) { final Model newModel = new Model(); newModel.setModelVersion( project.getModel().getModelVersion() ); newModel.setGroupId( project.getGroupId() + '.' + project.getArtifactId() ); newModel.setArtifactId( s ); newModel.setVersion( project.getVersion() ); newModel.setPackaging( "pom" ); return newModel; } // TODO: This will grab every module ; so those modules activated under profiles will also get included private List<Dependency> getArtifacts( List<Project> projects ) { List<Dependency> results = new ArrayList<>( ); for ( Project p : projects ) { Dependency d = new Dependency(); d.setGroupId( p.getGroupId() ); d.setArtifactId( p.getArtifactId() ); d.setVersion( p.getVersion() ); d.setType( p.getModel().getPackaging() ); results.add( d ); } return results; } @Override public int getExecutionIndex() { return 80; } }