MavenRepoComponentInfoProvider.java
package fr.paris.lutece.plugins.releaser.service;
import java.io.IOException;
import java.io.Serializable;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.math.NumberUtils;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import fr.paris.lutece.plugins.releaser.business.Component;
import fr.paris.lutece.plugins.releaser.util.ConstanteUtils;
import fr.paris.lutece.plugins.releaser.util.pom.SaxPomHandler;
import fr.paris.lutece.plugins.releaser.util.version.Version;
import fr.paris.lutece.plugins.releaser.util.version.VersionParsingException;
import fr.paris.lutece.portal.service.datastore.DatastoreService;
import fr.paris.lutece.portal.service.spring.SpringContextService;
import fr.paris.lutece.portal.service.util.AppLogService;
import fr.paris.lutece.portal.service.util.AppPropertiesService;
import fr.paris.lutece.util.httpaccess.HttpAccess;
import fr.paris.lutece.util.httpaccess.HttpAccessException;
/**
* Version Service
*/
public final class MavenRepoComponentInfoProvider
{
// Maven repos URLs
private static final String PROPERTY_MAVEN_URL_PREFIX = "lutecetools.maven.repository.url";
private static final List<String> PROPERTIES_MAVEN_URL = AppPropertiesService.getKeys( PROPERTY_MAVEN_URL_PREFIX );
// Maven Releases Paths
private static final String PROPERTY_RELEASES_PATH_PREFIX = "lutecetools.maven.repository.releases";
private static final List<String> PROPERTIES_RELEASES_PATH = AppPropertiesService.getKeys( PROPERTY_RELEASES_PATH_PREFIX );
// Maven Sanapshots Paths
private static final String PROPERTY_SNAPSHOTS_PATH_PREFIX = "lutecetools.maven.repository.snapshots";
private static final List<String> PROPERTIES_SNAPSHOTS_PATH = AppPropertiesService.getKeys( PROPERTY_SNAPSHOTS_PATH_PREFIX );
// Maven path - to see the tree structure
private static final String PROPERTY_MAVEN_REPO_PATH_TREE = "lutecetools.maven.repository.treestructure.path";
private static final String PATH_MAVEN_REPO_TREE = AppPropertiesService.getProperty( PROPERTY_MAVEN_REPO_PATH_TREE );
// Maven path - To get file
private static final String PROPERTY_MAVEN_REPO_PATH_FILE = "lutecetools.maven.repository.getfile.path";
private static final String PATH_MAVEN_REPO_FILE = AppPropertiesService.getProperty( PROPERTY_MAVEN_REPO_PATH_FILE );
// Path Plugins
private static final String PROPERTY_MAVEN_PATH_PLUGINS = "lutecetools.maven.repository.path.plugins";
private static final String URL_MAVEN_PATH_PLUGINS = AppPropertiesService.getProperty( PROPERTY_MAVEN_PATH_PLUGINS );
// Path Pom site
private static final String PROPERTY_MAVEN_PATH_SITE_POM = "lutecetools.maven.repository.path.site-pom";
private static final String URL_MAVEN_PATH_SITE_POM = AppPropertiesService.getProperty( PROPERTY_MAVEN_PATH_SITE_POM );
// Path Lutece core
private static final String PROPERTY_MAVEN_PATH_CORE = "lutecetools.maven.repository.path.core";
private static final String URL_MAVEN_PATH_CORE = AppPropertiesService.getProperty( PROPERTY_MAVEN_PATH_CORE );
// Path Themes
private static final String PROPERTY_MAVEN_PATH_THEMES = "lutecetools.maven.repository.path.themes";
private static final String URL_MAVEN_PATH_THEMES = AppPropertiesService.getProperty( PROPERTY_MAVEN_PATH_THEMES );
private static final String RELEASE_NOT_FOUND = "Release not found";
private static final String EXCEPTION_MESSAGE = "LuteceTools - MavenRepoService : Error retrieving pom infos : ";
private static MavenRepoComponentInfoProvider _instance;
/**
* Private constructor
*/
private MavenRepoComponentInfoProvider( )
{
}
/**
* Returns the unique instance
*
* @return the unique instance
*/
public static synchronized MavenRepoComponentInfoProvider getInstance( )
{
if ( _instance == null )
{
_instance = new MavenRepoComponentInfoProvider( );
}
return _instance;
}
public void setComponentRemoteInformations( Component component )
{
String strArtifactId = component.getArtifactId( );
try
{
String strComponentPath = getComponentPath( strArtifactId, component.getType( ) );
// Get release versions
String strReleaseUrl = getAvailableUrl( PROPERTIES_RELEASES_PATH, strComponentPath );
if ( strReleaseUrl != null )
{
List<String> listReleaseVersions = getVersionList( strReleaseUrl );
component.setReleaseVersions( listReleaseVersions );
component.setLastAvailableVersion( getLastVersion( listReleaseVersions ) );
}
else
{
AppLogService.info( "Error getting component url. No coponent found in Maven Release Repository : " );
}
// Get snapshot versions
String strSnapshotUrl = getAvailableUrl( PROPERTIES_SNAPSHOTS_PATH, strComponentPath );
if ( strSnapshotUrl != null )
{
List<String> listSnapshotVersions = getVersionList( strSnapshotUrl );
component.setSnapshotVersions( listSnapshotVersions );
component.setLastAvailableSnapshotVersion( getLastVersion( listSnapshotVersions ) );
// Get scmDeveloperConnection from Snapshot pom
if ( !listSnapshotVersions.isEmpty() )
getPomInfos( component, getSnapshotPomUrl( strSnapshotUrl, strArtifactId, component.getLastAvailableSnapshotVersion( ) ) );
}
else
{
AppLogService.info( "Error getting component url. No coponent found in Maven Snapshot Repository : " );
}
}
catch( Exception ex )
{
AppLogService.error( "MavenRepoComponentInfoProvider - Error getting remote informations for "
+ strArtifactId + " : " + ex.getMessage( ), ex );
}
}
private String getAvailableUrl( List<String> listRepoPathTypeProperties, String strComponentPath )
{
HttpAccess httpAccess = new HttpAccess( );
String strHtml = null;
for (String strUrlProperty : PROPERTIES_MAVEN_URL)
{
String[] tabUrl = strUrlProperty.split("\\.");
for (String strTypeProperty : listRepoPathTypeProperties)
{
String[] tabRepoType = strTypeProperty.split("\\.");
if ( tabRepoType[tabRepoType.length - 1].equals( tabUrl[tabUrl.length - 1] ) )
{
String url = AppPropertiesService.getProperty(strUrlProperty) + PATH_MAVEN_REPO_TREE
+ AppPropertiesService.getProperty(strTypeProperty) + strComponentPath;
try
{
strHtml = httpAccess.doGet( url );
}
catch ( HttpAccessException e )
{
AppLogService.info( "LuteceTools - MavenRepoService : Not available url : " + url );
}
if ( strHtml != null && !strHtml.isEmpty())
{
return url;
}
}
}
}
return null;
}
private List<String> getVersionList( String strUrl )
{
List<String> listVersions = new ArrayList<>( );
if (strUrl != null && !strUrl.isEmpty())
{
try
{
HttpAccess httpAccess = new HttpAccess( );
String strHtml = httpAccess.doGet( strUrl );
List<String> listAnchors = getAnchorsList( strHtml );
for ( String strAnchor : listAnchors )
{
if ( strAnchor.matches( "^[\\d].*" ) )
{
listVersions.add( strAnchor );
}
}
}
catch( HttpAccessException e )
{
AppLogService.error( "MavenRepoComponentInfoProvider - Error retrieving versions from "
+ strUrl + " : " + e.getMessage( ), e );
}
}
return listVersions;
}
private String getLastVersion( List<String> listVersions )
{
Version strLastVersion = new Version(0, 0, 0, null);
try
{
if (listVersions != null && !listVersions.isEmpty() )
{
for (String strVersion : listVersions)
{
Version version = Version.parse(strVersion);
int diff = strLastVersion.compareTo(version);
if (diff < 0)
{
strLastVersion = version;
}
}
}
else
{
return RELEASE_NOT_FOUND;
}
}
catch (VersionParsingException e)
{
AppLogService.info( "Error parsing version : '" + e.getMessage( ) );
}
return strLastVersion.toString();
}
private String getComponentPath( String strArtifactId, String strType )
{
if ( ConstanteUtils.MAVEN_REPO_LUTECE_CORE.equals(strType ) )
{
return URL_MAVEN_PATH_CORE;
}
else if ( ConstanteUtils.MAVEN_REPO_LUTECE_SITE.equals( strType ) )
{
return URL_MAVEN_PATH_THEMES + strArtifactId;
}
else
{
return URL_MAVEN_PATH_PLUGINS + strArtifactId;
}
}
private String getPomUrl( String strDirUrl, String strArtifactId, String strVersion )
{
String strPomUrl = strDirUrl;
if ( strDirUrl.substring( strDirUrl.length() - 1) != "/" )
{
strPomUrl = strPomUrl + "/";
}
strPomUrl = strPomUrl + strVersion + "/";
strPomUrl = strPomUrl + strArtifactId + "-" + strVersion + ".pom";
return strPomUrl;
}
private String getSnapshotPomUrl( String strDirUrl, String strArtifactId, String strVersion )
{
String strSnapshotPomUrl = strDirUrl;
if ( strSnapshotPomUrl.substring( strSnapshotPomUrl.length() - 1) != "/" )
{
strSnapshotPomUrl = strSnapshotPomUrl + "/";
}
strSnapshotPomUrl = strSnapshotPomUrl + strVersion + "/";
try
{
HttpAccess httpAccess = new HttpAccess( );
List<String> listVersions = new ArrayList<>( );
String strHtml = httpAccess.doGet( strSnapshotPomUrl.toString() );
List<String> listElement = getAnchorsList( strHtml );
String strPomFileName = getPomFileName(listElement);
if ( strPomFileName == null || strPomFileName.isEmpty() )
{
String strLastDirname = null;
int nIteration = 0;
for ( String strDirname : listElement )
{
String [ ] tabDir = strDirname.split("-");
String [ ] tabVer = strVersion.split("-");
if ( tabDir[0].equals(tabVer[0]) && Integer.parseInt( tabDir[tabDir.length -1] ) >= nIteration )
{
strLastDirname = strDirname;
nIteration = Integer.parseInt( tabDir[tabDir.length -1] );
}
}
strSnapshotPomUrl = strSnapshotPomUrl + strLastDirname;
strHtml = httpAccess.doGet( strSnapshotPomUrl );
listElement = getAnchorsList( strHtml );
strPomFileName = getPomFileName(listElement);
}
strSnapshotPomUrl = strSnapshotPomUrl.replace(PATH_MAVEN_REPO_TREE, PATH_MAVEN_REPO_FILE) + "/" + strPomFileName;
}
catch ( HttpAccessException e )
{
AppLogService.error( "\n*** ERROR *** Error retrieving snapshot pom URL : " + e.getMessage( ) );
}
return strSnapshotPomUrl;
}
private void getPomInfos( Component component, String strPomUrl )
{
try
{
HttpAccess httpAccess = new HttpAccess( );
Map<String, String> headersResponse = null;
String strPom = null;
strPom = httpAccess.doGet( strPomUrl );
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance( );
SAXParser saxParser = saxParserFactory.newSAXParser( );
SaxPomHandler handler = new SaxPomHandler( );
saxParser.parse( new InputSource( new StringReader( strPom ) ), handler );
component.setScmDeveloperConnection( handler.getScmDeveloperConnection( ) );
//component.setParentPomVersion( handler.getParentPomVersion( ) );
//component.setCoreVersion( handler.getCoreVersion( ) );
}
catch ( HttpAccessException e )
{
AppLogService.error(
"\n*** ERROR *** Error reading pom for component " + component.getArtifactId( )
+ EXCEPTION_MESSAGE + e.getMessage( ) );
}
catch ( IOException | SAXException | ParserConfigurationException e )
{
AppLogService.error( EXCEPTION_MESSAGE + e.getMessage( ), e );
}
}
private String getPomFileName(List<String> listElement)
{
String strPomFileName = null;
for ( String strFilename : listElement )
{
if ( strFilename.endsWith( ".pom" ) )
{
strPomFileName = strFilename;
}
}
return strPomFileName;
}
/**
* Gets anchor list using more optimized method
*
* @param strHtml The HTML code
* @return The list
*/
private List<String> getAnchorsList( String strHtml )
{
List<String> list = new ArrayList<>( );
String strCurrent = strHtml;
int nPos = strCurrent.indexOf( "<a " );
while ( nPos > 0 )
{
strCurrent = strCurrent.substring( nPos );
int nEndTag = strCurrent.indexOf( ">" );
int nTagEnd = strCurrent.indexOf( "</a>" );
list.add( strCurrent.substring( nEndTag + 1, nTagEnd ).replaceAll( "\\/", "" ) );
strCurrent = strCurrent.substring( nTagEnd + 4 );
nPos = strCurrent.indexOf( "<a " );
}
return list;
}
}