/******************************************************************************* * 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 *******************************************************************************/ package org.maven.ide.eclipse.internal.project; import java.util.Enumeration; import java.util.List; import java.util.Properties; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.resolver.ArtifactNotFoundException; import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.artifact.resolver.DefaultArtifactResolver; import org.apache.maven.embedder.MavenEmbedder; import org.apache.maven.settings.Profile; import org.apache.maven.settings.Settings; import org.maven.ide.eclipse.MavenPlugin; import org.maven.ide.eclipse.embedder.ArtifactKey; /** * The MyEclipseArtifactResolver is basically a copy of * EclipseArtifactResolver with the addition of handling * reading properties from the active profiles available and substituting * those variables, if there is a match. *

The other class affected by the scheme implemented here is: * MavenProjectManagerImpl, whose line 1137 is altered * to instantiate this class instead of the copied resolver.

* * @author original author unascribed * @author rova */ public class MyEclipseArtifactResolver extends DefaultArtifactResolver { public void resolve(Artifact artifact, List remoteRepositories, ArtifactRepository localRepository) throws ArtifactResolutionException, ArtifactNotFoundException { artifact = this.checkArtifact4Variables(artifact); if(!resolveAsEclipseProject(artifact)) { super.resolve(artifact, remoteRepositories, localRepository); } } public void resolveAlways(Artifact artifact, List remoteRepositories, ArtifactRepository localRepository) throws ArtifactResolutionException, ArtifactNotFoundException { artifact = this.checkArtifact4Variables(artifact); if(!resolveAsEclipseProject( artifact ) ) { super.resolveAlways(artifact, remoteRepositories, localRepository); } } protected static boolean resolveAsEclipseProject(Artifact artifact) { MavenProjectManagerImpl.Context context = MavenProjectManagerImpl.getContext(); if(context == null) { // XXX this is actually a bug return false; } if(artifact == null) { // according to the DefaultArtifactResolver source code, it looks like artifact can be null return false; } // check in the workspace, note that workspace artifacts never have classifiers ArtifactKey key = new ArtifactKey(artifact.getGroupId(), artifact.getArtifactId(), artifact.getBaseVersion(), null); IPath pomPath = context.state.getWorkspaceArtifact(key); if( pomPath == null ) { return false; } IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IFile pom = root.getFile(pomPath); if( pom == null || !pom.isAccessible() ) { // XXX this is really a bug, need to throw something meaningful return false; } if( context.resolverConfiguration.shouldResolveWorkspaceProjects() || ( context.resolverConfiguration.shouldIncludeModules() && WorkspaceState.isSameProject( context.pom, pom ) ) ){ IPath file = pom.getLocation(); if( !"pom".equals( artifact.getType() ) ) { MavenProjectFacade facade = context.state.getProjectFacade( pom ); IFolder outputLocation = root.getFolder( facade.getOutputLocation() ); if(outputLocation.exists()) { file = outputLocation.getLocation(); } } artifact.setFile( file.toFile() ); artifact.setResolved( true ); return true; } return false; } /** * Check whether an artifact holds potential variables for replacement * from an active profile. if there no such variables, the artifact is * left intact. * * @param artifact artifact to check * @return checked artifact, possible variables substituted */ @SuppressWarnings("unchecked") private Artifact checkArtifact4Variables( Artifact artifact ){ ArtifactKey key = new ArtifactKey(artifact.getGroupId(), artifact.getArtifactId(), artifact.getBaseVersion(), null); if( key.toString().indexOf('$') >= 0 ) { // Unresolved property, for example ${parentversion} // Find out which property of the artifact key which // is to be substituted with a variable value... String groupId = key.getGroupId(); String artifactId = key.getArtifactId(); String version = key.getVersion(); MavenPlugin plugin = MavenPlugin.getDefault(); try{ MavenEmbedder embedder = plugin.getMavenEmbedderManager().getWorkspaceEmbedder(); Settings s = embedder.getSettings(); List actProfiles = s.getActiveProfiles(); // TODO: If there are no active profiles, we can skip the rest ... List profiles = s.getProfiles(); for(Object profile : profiles) { Profile p = ( Profile ) profile; for(Object actProfile : actProfiles) { String id = ( String ) actProfile; if( p.getId().equals( id ) ){ // This profile is active ... Properties props = p.getProperties(); for( Enumeration e = props.keys(); e.hasMoreElements() ;){ String propKey = ( String ) e.nextElement(); if( groupId.indexOf('$') >= 0 ){ // groupId potential variable if( strip( groupId ).equals( propKey ) ){ groupId = props.getProperty( propKey ); artifact.setGroupId( groupId ); } }else if( artifactId.indexOf('$') >= 0 ){ // artifactId potential variable if( strip( artifactId ).equals( propKey ) ){ artifactId = props.getProperty( propKey ); artifact.setArtifactId( artifactId ); } }else if( version.indexOf('$') >= 0 ) { // version potential variable if( strip( version ).equals( propKey ) ){ version = props.getProperty( propKey ); artifact.setVersion( version ); } } } } } } }catch (Exception ex) { // TODO: handle exception } } return artifact; } /** * If a string is a potential variable for substitution, strip away * the variable admin. stuff. *

Please keep in mind that there is no check whether this is a * potential variable or not. It assumed that this check is done * prior to calling this method.

* * @param entity potential variable * @return stripped from variable enclosing brackets etc. */ private String strip( String entity ){ String s = entity.substring( 2 ); // Skip the '${ return s.substring( 0, ( s.length() - 1 ) ); // Strip away the trailing '}' } }