blob: b7d518124d4d566e313ff87090509dedeacd8bb2 [file] [log] [blame]
package org.apache.maven.report.projectinfo;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
import java.io.IOException;
import java.io.InputStream;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Properties;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.validator.routines.RegexValidator;
import org.apache.commons.validator.routines.UrlValidator;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuilder;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.ProjectBuildingRequest;
// CHECKSTYLE_OFF: UnusedImports
import org.apache.maven.reporting.AbstractMavenReportRenderer;
import org.apache.maven.repository.RepositorySystem;
// CHECKSTYLE_ON: UnusedImports
import org.apache.maven.settings.Proxy;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.codehaus.plexus.util.Base64;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.StringUtils;
/**
* Utilities methods.
*
* @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
* @version $Id$
* @since 2.1
*/
public class ProjectInfoReportUtils
{
private static final UrlValidator URL_VALIDATOR = new UrlValidator( new String[] { "http", "https" },
new RegexValidator( "^([" + "\\p{Alnum}\\-\\."
+ "]*)(:\\d*)?(.*)?" ), 0 );
/** The timeout when getting the url input stream */
private static final int TIMEOUT = 1000 * 5;
/** The default encoding used to transform bytes to characters */
private static final String DEFAULT_ENCODING = "UTF-8";
/**
* Get the input stream using UTF-8 as character encoding from a URL.
*
* @param url not null
* @param settings not null to handle proxy settings
* @return the UTF-8 decoded input stream as string
* @throws IOException if any
* @see #getContent(URL, Settings, String)
*/
public static String getContent( URL url, Settings settings )
throws IOException
{
return getContent( url, settings, DEFAULT_ENCODING );
}
/**
* Get the input stream from a URL.
*
* @param url not null
* @param settings not null to handle proxy settings
* @param encoding the wanted encoding for the URL input stream. If null, UTF-8 will be used.
* @return the input stream decoded with the wanted encoding as string
* @throws IOException if any
*/
public static String getContent( URL url, Settings settings, String encoding )
throws IOException
{
return getContent( url, null, settings, encoding );
}
/**
* Get the input stream from a URL.
*
* @param url not null
* @param project could be null
* @param settings not null to handle proxy settings
* @param encoding the wanted encoding for the URL input stream. If null, UTF-8 will be used.
* @return the input stream decoded with the wanted encoding as string
* @throws IOException if any
* @since 2.3
*/
public static String getContent( URL url, MavenProject project, Settings settings, String encoding )
throws IOException
{
String scheme = url.getProtocol();
if ( StringUtils.isEmpty( encoding ) )
{
encoding = DEFAULT_ENCODING;
}
if ( "file".equals( scheme ) )
{
InputStream in = null;
try
{
URLConnection conn = url.openConnection();
in = conn.getInputStream();
final String content = IOUtil.toString( in, encoding );
in.close();
in = null;
return content;
}
finally
{
IOUtil.close( in );
}
}
Proxy proxy = settings.getActiveProxy();
if ( proxy != null )
{
if ( "http".equals( scheme ) || "https".equals( scheme ) || "ftp".equals( scheme ) )
{
scheme += ".";
}
else
{
scheme = "";
}
String host = proxy.getHost();
if ( !StringUtils.isEmpty( host ) )
{
Properties p = System.getProperties();
p.setProperty( scheme + "proxySet", "true" );
p.setProperty( scheme + "proxyHost", host );
p.setProperty( scheme + "proxyPort", String.valueOf( proxy.getPort() ) );
if ( !StringUtils.isEmpty( proxy.getNonProxyHosts() ) )
{
p.setProperty( scheme + "nonProxyHosts", proxy.getNonProxyHosts() );
}
final String userName = proxy.getUsername();
if ( !StringUtils.isEmpty( userName ) )
{
final String pwd = StringUtils.isEmpty( proxy.getPassword() ) ? "" : proxy.getPassword();
Authenticator.setDefault( new Authenticator()
{
/** {@inheritDoc} */
@Override
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication( userName, pwd.toCharArray() );
}
} );
}
}
}
InputStream in = null;
try
{
URLConnection conn = getURLConnection( url, project, settings );
in = conn.getInputStream();
final String string = IOUtil.toString( in, encoding );
in.close();
in = null;
return string;
}
finally
{
IOUtil.close( in );
}
}
/**
* @param repositorySystem not null
* @param artifact not null
* @param projectBuilder not null
* @param buildingRequest not null
* @return the artifact url or null if an error occurred.
*/
public static String getArtifactUrl( RepositorySystem repositorySystem, Artifact artifact,
ProjectBuilder projectBuilder, ProjectBuildingRequest buildingRequest )
{
if ( Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) )
{
return null;
}
Artifact copyArtifact = ArtifactUtils.copyArtifact( artifact );
if ( !"pom".equals( copyArtifact.getType() ) )
{
copyArtifact =
repositorySystem.createProjectArtifact( copyArtifact.getGroupId(), copyArtifact.getArtifactId(),
copyArtifact.getVersion() );
}
try
{
MavenProject pluginProject = projectBuilder.build( copyArtifact, buildingRequest ).getProject();
if ( isArtifactUrlValid( pluginProject.getUrl() ) )
{
return pluginProject.getUrl();
}
return null;
}
catch ( ProjectBuildingException e )
{
return null;
}
}
/**
* @param artifactId not null
* @param link could be null
* @return the artifactId cell with or without a link pattern
* @see AbstractMavenReportRenderer#linkPatternedText(String)
*/
public static String getArtifactIdCell( String artifactId, String link )
{
if ( StringUtils.isEmpty( link ) )
{
return artifactId;
}
return "{" + artifactId + "," + link + "}";
}
/**
* @param url not null
* @return <code>true</code> if the url is valid, <code>false</code> otherwise.
*/
public static boolean isArtifactUrlValid( String url )
{
if ( StringUtils.isEmpty( url ) )
{
return false;
}
return URL_VALIDATOR.isValid( url );
}
/**
* @param url not null
* @param project not null
* @param settings not null
* @return the url connection with auth if required. Don't check the certificate if SSL scheme.
* @throws IOException if any
*/
private static URLConnection getURLConnection( URL url, MavenProject project, Settings settings )
throws IOException
{
URLConnection conn = url.openConnection();
conn.setConnectTimeout( TIMEOUT );
conn.setReadTimeout( TIMEOUT );
// conn authorization
//@formatter:off
if ( settings.getServers() != null
&& !settings.getServers().isEmpty()
&& project != null
&& project.getDistributionManagement() != null
&& (
project.getDistributionManagement().getRepository() != null
|| project.getDistributionManagement().getSnapshotRepository() != null
)
&& ( StringUtils.isNotEmpty( project.getDistributionManagement().getRepository().getUrl() )
|| StringUtils.isNotEmpty( project.getDistributionManagement().getSnapshotRepository().getUrl() ) )
)
//@formatter:on
{
Server server = null;
if ( url.toString().contains( project.getDistributionManagement().getRepository().getUrl() ) )
{
server = settings.getServer( project.getDistributionManagement().getRepository().getId() );
}
if ( server == null
&& url.toString().contains( project.getDistributionManagement().getSnapshotRepository().getUrl() ) )
{
server = settings.getServer( project.getDistributionManagement().getSnapshotRepository().getId() );
}
if ( server != null && StringUtils.isNotEmpty( server.getUsername() )
&& StringUtils.isNotEmpty( server.getPassword() ) )
{
String up = server.getUsername().trim() + ":" + server.getPassword().trim();
String upEncoded = new String( Base64.encodeBase64Chunked( up.getBytes() ) ).trim();
conn.setRequestProperty( "Authorization", "Basic " + upEncoded );
}
}
if ( conn instanceof HttpsURLConnection )
{
HostnameVerifier hostnameverifier = new HostnameVerifier()
{
/** {@inheritDoc} */
public boolean verify( String urlHostName, SSLSession session )
{
return true;
}
};
( (HttpsURLConnection) conn ).setHostnameVerifier( hostnameverifier );
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager()
{
/** {@inheritDoc} */
public void checkClientTrusted( final X509Certificate[] chain, final String authType )
{
}
/** {@inheritDoc} */
public void checkServerTrusted( final X509Certificate[] chain, final String authType )
{
}
/** {@inheritDoc} */
public X509Certificate[] getAcceptedIssuers()
{
return null;
}
} };
try
{
SSLContext sslContext = SSLContext.getInstance( "SSL" );
sslContext.init( null, trustAllCerts, new SecureRandom() );
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
( (HttpsURLConnection) conn ).setSSLSocketFactory( sslSocketFactory );
}
catch ( NoSuchAlgorithmException | KeyManagementException e1 )
{
// ignore
}
}
return conn;
}
}