/* * Copyright (c) 2012 Red Hat, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see * <http://www.gnu.org/licenses>. */ package com.redhat.rcm.version.mgr.mod; import org.apache.maven.mae.project.ProjectToolsException; import org.apache.maven.mae.project.key.ProjectKey; import org.apache.maven.mae.project.key.VersionlessProjectKey; import org.apache.maven.model.Dependency; import org.apache.maven.model.Model; import org.apache.maven.model.Parent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.redhat.rcm.version.mgr.session.VersionManagerSession; import com.redhat.rcm.version.model.DependencyManagementKey; import com.redhat.rcm.version.model.Project; public abstract class AbstractVersionModder implements ProjectModder { protected final Logger logger = LoggerFactory.getLogger( getClass() ); protected abstract String getActionDescription(); protected abstract boolean initialiseModder( final Project project, final VersionManagerSession session ); protected abstract boolean shouldModifyVersion( String version ); protected abstract String replaceVersion( String model ); /** * It is possible for a pom file to be a template. Don't alter the version in that case. * @param version * @return boolean */ protected boolean isTemplateVersion( final String version ) { if ( version.startsWith( "${" ) && version.endsWith( "}" ) ) { return true; } return false; } @Override public boolean inject( final Project project, final VersionManagerSession session ) { boolean changed = false; if ( initialiseModder( project, session ) ) { final Model model = project.getModel(); final Parent parent = project.getParent(); if ( model.getVersion() != null && shouldModifyVersion( model.getVersion() ) ) { logger.info( getActionDescription() + " in: " + model.getVersion() + "' for: " + model.getId() ); model.setVersion( replaceVersion( model.getVersion() ) ); changed = true; } if ( parent != null ) { final ProjectKey tk = session.getToolchainKey(); final VersionlessProjectKey vpk = new VersionlessProjectKey( parent ); Dependency managed = session.getManagedDependency( new DependencyManagementKey( parent.getGroupId(), parent.getArtifactId(), "pom", null ) ); if ( managed == null ) { // if we don't find the one with the specific "pom" type, look for the generic one // if we find that, we can list the specific one as a missing parent/dep and use the info from // the generic one for the version, etc. managed = session.getManagedDependency( new DependencyManagementKey( parent.getGroupId(), parent.getArtifactId() ) ); if ( managed != null ) { // TODO: Are BOTH of the following actions (missing parent, missing dep) REALLY appropriate?? session.addMissingParent( project ); // final Dependency d = new Dependency(); // d.setGroupId( parent.getGroupId() ); // d.setArtifactId( parent.getArtifactId() ); // d.setVersion( managed.getVersion() ); // d.setType( "pom" ); // // session.addMissingDependency( project, d ); } } final String version = managed == null ? null : managed.getVersion(); // if the parent references a project in the current vman modification session... if ( session.inCurrentSession( parent ) ) { logger.info( "Parent: '" + parent.getId() + "' is current session (for: " + model.getId() + ")" ); // and if the parent ref's version doesn't end with the suffix we're using here... if ( shouldModifyVersion( parent.getVersion() ) ) { logger.info( getActionDescription() + " in: " + model.getVersion() + "' for: " + model.getId() ); parent.setVersion( replaceVersion( parent.getVersion() ) ); changed = true; } } // otherwise, if we're not using a toolchain POM or our parent references the // toolchain POM already, don't mess with the rest of this stuff. else if ( tk == null || new VersionlessProjectKey( tk ).equals( vpk ) ) { logger.info( "Toolchain key: '" + tk + "' is null, or parent: '" + parent.getId() + "' is already set to toolchain for: " + model.getId() + ". Nothing to do.." ); // NOP. } else if ( session.getRelocation( vpk ) != null ) { logger.info( "Original parent " + vpk + " has been relocated to " + tk + " ; nothing to do." ); // NOP. } // if we do have a toolchain POM, and the parent ref for this project isn't listed in // a BOM (I know, that's weird)... else if ( version == null ) { // note it in the session that this parent POM hasn't been captured in our info. session.addMissingParent( project ); if ( !session.isStrict() && shouldModifyVersion( parent.getVersion() ) ) { // if we're not operating in strict mode, and the parent isn't in the current // VMan session, AND the parent ref version doesn't // end with the suffix we're using, append it and assume that the parent POM // will be VMan-ized and built using the same configuration. parent.setVersion( replaceVersion( parent.getVersion() ) ); changed = true; } else { logger.info( "NOT replacing snapshot for parent version: '" + parent.getVersion() + "' for: " + model.getId() + "; either we're operating in strict mode, or the parent version is correct." ); } } // if we're using a different version of a parent listed in our BOMs else if ( !parent.getVersion() .equals( version ) ) { logger.info( "Adjusting parent version to: '" + version + "' (was: '" + parent.getVersion() + "') for parent: '" + parent.getId() + "' in POM: " + model.getId() ); // adjust the parent version to match the BOM. parent.setVersion( version ); changed = true; } } } try { project.updateCoord(); } catch ( final ProjectToolsException e ) { session.addError( e ); } return changed; } }