/******************************************************************************
* Copyright (c) 2008-2013, Linagora
*
* 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:
* Linagora - initial API and implementation
*******************************************************************************/
package com.ebmwebsourcing.petals.common.internal.provisional.maven;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import com.ebmwebsourcing.petals.common.internal.PetalsCommonPlugin;
import com.ebmwebsourcing.petals.common.internal.provisional.preferences.PreferencesManager;
import com.ebmwebsourcing.petals.common.internal.provisional.utils.StringUtils;
/**
* A set of utility methods related to Maven and pom.xml files.
* @author Vincent Zurczak - EBM WebSourcing
*/
public class MavenUtils {
/**
* Gets the elements from the pom.xml file located at the work space root.
* @return a bean for the Maven templates (never null, even when the parent pom does not exists).
*/
public static MavenBean getPomParentElements() {
String parentPath = PreferencesManager.getMavenPomParent();
MavenBean bean = null;
try {
URL pomParent;
if( parentPath != null && parentPath.trim().length() > 0 ) {
try {
pomParent = new URL( parentPath );
} catch( Exception e ) {
File f = new File( parentPath );
if( ! f.exists() && ! f.isFile())
throw new MalformedURLException( f.toString() + " is not a valid file location." );
pomParent = f.toURI().toURL();
}
bean = getPomElements( pomParent );
}
} catch( MalformedURLException e ) {
PetalsCommonPlugin.log( e, IStatus.WARNING );
}
MavenBean returnedBean = new MavenBean ();
if( bean != null ) {
returnedBean.setParentArtifactId( bean.getArtifactId());
returnedBean.setParentGroupId( bean.getGroupId() );
returnedBean.setParentVersion( bean.getVersion());
}
return returnedBean;
}
/**
* Gets the elements from a pom.xml IFile.
* @param file the POM file
* @return a bean for the Maven templates, or null in case of invalid file.
*/
public static MavenBean getPomElements( IFile file ) {
try {
URL url = file.getLocation().toFile().toURI().toURL();
return getPomElements( url );
} catch( MalformedURLException e ) {
PetalsCommonPlugin.log( e, IStatus.WARNING );
}
return null;
}
/**
* Gets the elements from a pom.xml file.
* @param url
* @return a bean for the Maven templates, or null in case of invalid URL.
*/
public static MavenBean getPomElements( URL url ) {
SAXBuilder builder = new SAXBuilder();
try {
InputStream stream = url.openStream();
Document doc = builder.build( stream );
Namespace ns = doc.getRootElement().getNamespace();
Element artifactIdElement = ns == null ? doc.getRootElement().getChild( "artifactId" )
: doc.getRootElement().getChild( "artifactId", ns );
Element groupIdElement = ns == null ? doc.getRootElement().getChild( "groupId" )
: doc.getRootElement().getChild( "groupId", ns );
Element versionElement = ns == null ? doc.getRootElement().getChild( "version" )
: doc.getRootElement().getChild( "version", ns );
String artifactId = artifactIdElement != null ? artifactIdElement.getValue() : "";
String groupId = groupIdElement != null ? groupIdElement.getValue() : "";
String version = versionElement != null ? versionElement.getValue() : "";
MavenBean bean = new MavenBean ();
bean.setArtifactId( artifactId );
bean.setGroupId( groupId );
bean.setVersion( version );
return bean;
} catch( Exception e ) {
PetalsCommonPlugin.log( e, IStatus.WARNING );
}
return null;
}
/**
* Gets the dependency elements from a pom.xml IFile.
* @param file
* @return a list of {@link MavenBean} matching the dependencies.
*/
public static List<MavenBean> getPomDependencies( IFile file ) {
return getPomDependencies( file.getLocation().toFile());
}
/**
* Gets the dependency elements from a pom.xml file.
* <p>
* This method only gets the artifactId, the groupId and the version elements.
* </p>
* @param file
* @return a list of {@link MavenBean} matching the dependencies.
*/
public static List<MavenBean> getPomDependencies( File file ) {
List<MavenBean> beans = new ArrayList<MavenBean> ();
if( ! file.exists())
return beans;
SAXBuilder builder = new SAXBuilder();
try {
Document doc = builder.build( file );
Namespace ns = doc.getRootElement().getNamespace();
Element depsElt = ns == null ? doc.getRootElement().getChild( "dependencies" )
: doc.getRootElement().getChild( "dependencies", ns );
List<?> children = ns == null ? depsElt.getChildren( "dependency" ) : depsElt.getChildren( "dependency", ns );
for( Object o : children ) {
if( o instanceof Element ) {
Element depElt = (Element) o;
Element artifactIdElement = ns == null ? depElt.getChild( "artifactId" ) : depElt.getChild( "artifactId", ns );
Element groupIdElement = ns == null ? depElt.getChild( "groupId" ) : depElt.getChild( "groupId", ns );
Element versionElement = ns == null ? depElt.getChild( "version" ) : depElt.getChild( "version", ns );
String artifactId = artifactIdElement != null ? artifactIdElement.getValue() : "";
String groupId = groupIdElement != null ? groupIdElement.getValue() : "";
String version = versionElement != null ? versionElement.getValue() : "";
MavenBean bean = new MavenBean ();
bean.setArtifactId( artifactId );
bean.setGroupId( groupId );
bean.setVersion( version );
beans.add( bean );
}
}
} catch( Exception e ) {
PetalsCommonPlugin.log( e, IStatus.WARNING );
}
return beans;
}
/**
* Extracts the dependencies from a POm whose scope is 'provided'.
* <p>
* This method only gets the artifact ID.
* </p>
* @param file
* @return a non-null set of artifact IDs
*/
public static Set<String> extractDependenciesWithProvidedScope( File file ) {
Set<String> result = new HashSet<String> ();
if( ! file.exists())
return result;
SAXBuilder builder = new SAXBuilder();
try {
Document doc = builder.build( file );
Namespace ns = doc.getRootElement().getNamespace();
Element depsElt = ns == null ? doc.getRootElement().getChild( "dependencies" )
: doc.getRootElement().getChild( "dependencies", ns );
List<?> children = ns == null ? depsElt.getChildren( "dependency" ) : depsElt.getChildren( "dependency", ns );
for( Object o : children ) {
if( o instanceof Element ) {
Element depElt = (Element) o;
Element scopeElement = ns == null ? depElt.getChild( "scope" ) : depElt.getChild( "scope", ns );
String scope = scopeElement != null ? scopeElement.getValue() : "";
if( ! "provided".equalsIgnoreCase( scope ))
continue;
Element artifactIdElement = ns == null ? depElt.getChild( "artifactId" ) : depElt.getChild( "artifactId", ns );
String artifactId = artifactIdElement != null ? artifactIdElement.getValue() : "";
result.add( artifactId );
}
}
} catch( Exception e ) {
PetalsCommonPlugin.log( e, IStatus.WARNING );
}
return result;
}
/**
* @param targetPom
* @param dependencyPoms
*/
public static void setPomDependencies( File targetPom, Collection<File> dependencyPoms ) {
// Get the properties of the referenced POM
Collection<MavenBean> dependenciesMavenBeans = new ArrayList<MavenBean>( dependencyPoms.size());
for( File f : dependencyPoms ) {
try {
MavenBean bean = getPomElements( f.toURI().toURL());
dependenciesMavenBeans.add( bean );
} catch( MalformedURLException e ) {
PetalsCommonPlugin.log( e, IStatus.WARNING, "Could not read the Maven dependencies for " + targetPom.getAbsolutePath());
}
}
// Set the dependencies in the target POM
SAXBuilder builder = new SAXBuilder();
Document doc = null;
try {
doc = builder.build( targetPom );
Namespace ns = doc.getRootElement().getNamespace();
Element depsElt = ns == null ? doc.getRootElement().getChild( "dependencies" )
: doc.getRootElement().getChild( "dependencies", ns );
depsElt.removeContent();
for( MavenBean bean : dependenciesMavenBeans ) {
Element dependencyElement = ns == null ? new Element( "dependency" ) : new Element( "dependency", ns );
depsElt.addContent( dependencyElement );
Element artifactIdElement = ns == null ? new Element( "artifactId" ) : new Element( "artifactId", ns );
artifactIdElement.setText( bean.getArtifactId());
dependencyElement.addContent( artifactIdElement );
Element groupIdElement = ns == null ? new Element( "groupId" ) : new Element( "groupId", ns );
groupIdElement.setText( bean.getGroupId());
dependencyElement.addContent( groupIdElement );
Element versionElement = ns == null ? new Element( "version" ) : new Element( "version", ns );
versionElement.setText( bean.getVersion());
dependencyElement.addContent( versionElement );
Element typeElement = ns == null ? new Element( "type" ) : new Element( "type", ns );
typeElement.setText( "jbi-service-unit" );
dependencyElement.addContent( typeElement );
}
} catch( Exception e ) {
PetalsCommonPlugin.log( e, IStatus.WARNING, "Could not set the Maven dependencies for " + targetPom.getAbsolutePath());
}
// Write the new POM
FileOutputStream fos = null;
try {
if( doc != null ) {
fos = new FileOutputStream( targetPom );
new XMLOutputter( Format.getPrettyFormat()).output( doc, fos );
}
} catch( Exception e ) {
PetalsCommonPlugin.log( e, IStatus.WARNING, "Could not write the Maven dependencies for " + targetPom.getAbsolutePath());
} finally {
if( fos != null ) {
try {
fos.close();
} catch( IOException e ) {
// nothing
}
}
}
}
/**
* Finds the location of the local Maven repository.
* <p>
* This method first searches in the <code>~/.m2/settings.xml</code> file.
* If the local repository was not moved, then the default one
* (<code>~/.m2/repository</code>) is used.
* </p>
*
* @return the location of the local Maven repository
*/
public static IPath findLocalMavenRepository() {
IPath result = null;
// Look at the settings.xml file
File settingsFile = new File( System.getProperty( "user.home" ), ".m2/settings.xml" );
SAXBuilder builder = new SAXBuilder();
try {
Document doc = builder.build( settingsFile );
Namespace ns = Namespace.getNamespace( "http://maven.apache.org/SETTINGS/1.0.0" );
Element elt = doc.getRootElement().getChild( "localRepository", ns );
if( elt != null ) {
String text = elt.getTextTrim();
if( StringUtils.isEmpty( text )) {
PetalsCommonPlugin.log( "The M2 repository is overwritten in ~/.m2/settings.xml but the location is empty.", IStatus.WARNING );
} else {
result = new Path( elt.getTextTrim());
}
}
} catch( Exception e ) {
PetalsCommonPlugin.log( e, IStatus.WARNING );
}
// By default, assume it is ~/.m2/repository
if( result == null )
result = new Path( System.getProperty( "user.home" )).append( ".m2/repository" );
// Make some check
if( ! result.toFile().exists())
PetalsCommonPlugin.log( "The found M2 repository does not exist.", IStatus.WARNING );
return result;
}
}