View Javadoc

1   package org.apache.maven.report.projectinfo;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.net.Authenticator;
25  import java.net.PasswordAuthentication;
26  import java.net.URL;
27  import java.net.URLConnection;
28  import java.security.KeyManagementException;
29  import java.security.NoSuchAlgorithmException;
30  import java.security.SecureRandom;
31  import java.security.cert.X509Certificate;
32  import java.util.Collections;
33  import java.util.List;
34  import java.util.Properties;
35  
36  import javax.net.ssl.HostnameVerifier;
37  import javax.net.ssl.HttpsURLConnection;
38  import javax.net.ssl.SSLContext;
39  import javax.net.ssl.SSLSession;
40  import javax.net.ssl.SSLSocketFactory;
41  import javax.net.ssl.TrustManager;
42  import javax.net.ssl.X509TrustManager;
43  
44  import org.apache.commons.lang.math.NumberUtils;
45  import org.apache.commons.validator.UrlValidator;
46  import org.apache.maven.artifact.Artifact;
47  import org.apache.maven.artifact.ArtifactUtils;
48  import org.apache.maven.artifact.factory.ArtifactFactory;
49  import org.apache.maven.artifact.repository.ArtifactRepository;
50  import org.apache.maven.project.MavenProject;
51  import org.apache.maven.project.MavenProjectBuilder;
52  import org.apache.maven.project.ProjectBuildingException;
53  import org.apache.maven.reporting.AbstractMavenReportRenderer;
54  import org.apache.maven.settings.Proxy;
55  import org.apache.maven.settings.Server;
56  import org.apache.maven.settings.Settings;
57  import org.codehaus.plexus.util.Base64;
58  import org.codehaus.plexus.util.IOUtil;
59  import org.codehaus.plexus.util.StringUtils;
60  
61  /**
62   * Utilities methods.
63   *
64   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
65   * @version $Id: ProjectInfoReportUtils.java 1367255 2012-07-30 20:01:21Z hboutemy $
66   * @since 2.1
67   */
68  public class ProjectInfoReportUtils
69  {
70      private static final UrlValidator URL_VALIDATOR = new UrlValidator( new String[] { "http", "https" } );
71  
72      /** The timeout when getting the url input stream */
73      private static final int TIMEOUT = 1000 * 5;
74  
75      /**
76       * Get the input stream using ISO-8859-1 as charset from an URL.
77       *
78       * @param url not null
79       * @param settings not null to handle proxy settings
80       * @return the ISO-8859-1 inputstream found.
81       * @throws IOException if any
82       * @see #getContent(URL, Settings, String)
83       */
84      public static String getContent( URL url, Settings settings )
85          throws IOException
86      {
87          return getContent( url, settings, "ISO-8859-1" );
88      }
89  
90      /**
91       * Get the input stream from an URL.
92       *
93       * @param url not null
94       * @param settings not null to handle proxy settings
95       * @param encoding the wanted encoding for the inputstream. If null, encoding will be "ISO-8859-1".
96       * @return the inputstream found depending the wanted encoding.
97       * @throws IOException if any
98       */
99      public static String getContent( URL url, Settings settings, String encoding )
100         throws IOException
101     {
102         return getContent( url, null, settings, encoding );
103     }
104 
105     /**
106      * Get the input stream from an URL.
107      *
108      * @param url not null
109      * @param project could be null
110      * @param settings not null to handle proxy settings
111      * @param encoding the wanted encoding for the inputstream. If empty, encoding will be "ISO-8859-1".
112      * @return the inputstream found depending the wanted encoding.
113      * @throws IOException if any
114      * @since 2.3
115      */
116     public static String getContent( URL url, MavenProject project, Settings settings, String encoding )
117         throws IOException
118     {
119         String scheme = url.getProtocol();
120 
121         if ( StringUtils.isEmpty( encoding ) )
122         {
123             encoding = "ISO-8859-1";
124         }
125 
126         if ( "file".equals( scheme ) )
127         {
128             InputStream in = null;
129             try
130             {
131                 URLConnection conn = url.openConnection();
132                 in = conn.getInputStream();
133 
134                 return IOUtil.toString( in, encoding );
135             }
136             finally
137             {
138                 IOUtil.close( in );
139             }
140         }
141 
142         Proxy proxy = settings.getActiveProxy();
143         if ( proxy != null )
144         {
145             if ( "http".equals( scheme ) || "https".equals( scheme ) || "ftp".equals( scheme ) )
146             {
147                 scheme += ".";
148             }
149             else
150             {
151                 scheme = "";
152             }
153 
154             String host = proxy.getHost();
155             if ( !StringUtils.isEmpty( host ) )
156             {
157                 Properties p = System.getProperties();
158                 p.setProperty( scheme + "proxySet", "true" );
159                 p.setProperty( scheme + "proxyHost", host );
160                 p.setProperty( scheme + "proxyPort", String.valueOf( proxy.getPort() ) );
161                 if ( !StringUtils.isEmpty( proxy.getNonProxyHosts() ) )
162                 {
163                     p.setProperty( scheme + "nonProxyHosts", proxy.getNonProxyHosts() );
164                 }
165 
166                 final String userName = proxy.getUsername();
167                 if ( !StringUtils.isEmpty( userName ) )
168                 {
169                     final String pwd = StringUtils.isEmpty( proxy.getPassword() ) ? "" : proxy.getPassword();
170                     Authenticator.setDefault( new Authenticator()
171                     {
172                         /** {@inheritDoc} */
173                         protected PasswordAuthentication getPasswordAuthentication()
174                         {
175                             return new PasswordAuthentication( userName, pwd.toCharArray() );
176                         }
177                     } );
178                 }
179             }
180         }
181 
182         InputStream in = null;
183         try
184         {
185             URLConnection conn = getURLConnection( url, project, settings );
186             in = conn.getInputStream();
187 
188             return IOUtil.toString( in, encoding );
189         }
190         finally
191         {
192             IOUtil.close( in );
193         }
194     }
195 
196     /**
197      * @param factory not null
198      * @param artifact not null
199      * @param mavenProjectBuilder not null
200      * @param remoteRepositories not null
201      * @param localRepository not null
202      * @return the artifact url or null if an error occurred.
203      */
204     public static String getArtifactUrl( ArtifactFactory factory, Artifact artifact,
205                                          MavenProjectBuilder mavenProjectBuilder,
206                                          List<ArtifactRepository> remoteRepositories,
207                                          ArtifactRepository localRepository )
208     {
209         if ( Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) )
210         {
211             return null;
212         }
213 
214         Artifact copyArtifact = ArtifactUtils.copyArtifact( artifact );
215         if ( !"pom".equals( copyArtifact.getType() ) )
216         {
217             copyArtifact =
218                 factory.createProjectArtifact( copyArtifact.getGroupId(), copyArtifact.getArtifactId(),
219                                                copyArtifact.getVersion(), copyArtifact.getScope() );
220         }
221         try
222         {
223             MavenProject pluginProject =
224                 mavenProjectBuilder.buildFromRepository( copyArtifact,
225                                                          remoteRepositories == null ? Collections.EMPTY_LIST
226                                                                          : remoteRepositories, localRepository );
227 
228             if ( isArtifactUrlValid( pluginProject.getUrl() ) )
229             {
230                 return pluginProject.getUrl();
231             }
232 
233             return null;
234         }
235         catch ( ProjectBuildingException e )
236         {
237             return null;
238         }
239     }
240 
241     /**
242      * @param artifactId not null
243      * @param link could be null
244      * @return the artifactId cell with or without a link pattern
245      * @see AbstractMavenReportRenderer#linkPatternedText(String)
246      */
247     public static String getArtifactIdCell( String artifactId, String link )
248     {
249         if ( StringUtils.isEmpty( link ) )
250         {
251             return artifactId;
252         }
253 
254         return "{" + artifactId + "," + link + "}";
255     }
256 
257     /**
258      * @param url not null
259      * @return <code>true</code> if the url is valid, <code>false</code> otherwise.
260      */
261     public static boolean isArtifactUrlValid( String url )
262     {
263         if ( StringUtils.isEmpty( url ) )
264         {
265             return false;
266         }
267 
268         return URL_VALIDATOR.isValid( url );
269     }
270 
271     /**
272      * @param url not null
273      * @param project not null
274      * @param settings not null
275      * @return the url connection with auth if required. Don't check the certificate if SSL scheme.
276      * @throws IOException if any
277      */
278     private static URLConnection getURLConnection( URL url, MavenProject project, Settings settings )
279         throws IOException
280     {
281         URLConnection conn = url.openConnection();
282         conn.setConnectTimeout( TIMEOUT );
283         conn.setReadTimeout( TIMEOUT );
284 
285         // conn authorization
286         if ( settings.getServers() != null
287             && !settings.getServers().isEmpty()
288             && project != null
289             && project.getDistributionManagement() != null
290             && ( project.getDistributionManagement().getRepository() != null || project.getDistributionManagement().getSnapshotRepository() != null )
291             && ( StringUtils.isNotEmpty( project.getDistributionManagement().getRepository().getUrl() ) || StringUtils.isNotEmpty( project.getDistributionManagement().getSnapshotRepository().getUrl() ) ) )
292         {
293             Server server = null;
294             if ( url.toString().contains( project.getDistributionManagement().getRepository().getUrl() ) )
295             {
296                 server = settings.getServer( project.getDistributionManagement().getRepository().getId() );
297             }
298             if ( server == null
299                 && url.toString().contains( project.getDistributionManagement().getSnapshotRepository().getUrl() ) )
300             {
301                 server = settings.getServer( project.getDistributionManagement().getSnapshotRepository().getId() );
302             }
303 
304             if ( server != null && StringUtils.isNotEmpty( server.getUsername() )
305                 && StringUtils.isNotEmpty( server.getPassword() ) )
306             {
307                 String up = server.getUsername().trim() + ":" + server.getPassword().trim();
308                 String upEncoded = new String( Base64.encodeBase64Chunked( up.getBytes() ) ).trim();
309 
310                 conn.setRequestProperty( "Authorization", "Basic " + upEncoded );
311             }
312         }
313 
314         if ( conn instanceof HttpsURLConnection )
315         {
316             HostnameVerifier hostnameverifier = new HostnameVerifier()
317             {
318                 /** {@inheritDoc} */
319                 public boolean verify( String urlHostName, SSLSession session )
320                 {
321                     return true;
322                 }
323             };
324             ( (HttpsURLConnection) conn ).setHostnameVerifier( hostnameverifier );
325 
326             TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager()
327             {
328                 /** {@inheritDoc} */
329                 public void checkClientTrusted( final X509Certificate[] chain, final String authType )
330                 {
331                 }
332 
333                 /** {@inheritDoc} */
334                 public void checkServerTrusted( final X509Certificate[] chain, final String authType )
335                 {
336                 }
337 
338                 /** {@inheritDoc} */
339                 public X509Certificate[] getAcceptedIssuers()
340                 {
341                     return null;
342                 }
343             } };
344 
345             try
346             {
347                 SSLContext sslContext = SSLContext.getInstance( "SSL" );
348                 sslContext.init( null, trustAllCerts, new SecureRandom() );
349 
350                 SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
351 
352                 ( (HttpsURLConnection) conn ).setSSLSocketFactory( sslSocketFactory );
353             }
354             catch ( NoSuchAlgorithmException e1 )
355             {
356                 // ignore
357             }
358             catch ( KeyManagementException e )
359             {
360                 // ignore
361             }
362         }
363 
364         return conn;
365     }
366 
367     public static boolean isNumber( String str )
368     {
369         if ( str.startsWith( "+" ) )
370         {
371             str = str.substring( 1 );
372         }
373         return NumberUtils.isNumber( str );
374     }
375 
376     public static float toFloat( String str, float defaultValue )
377     {
378         if ( str.startsWith( "+" ) )
379         {
380             str = str.substring( 1 );
381         }
382         return NumberUtils.toFloat( str, defaultValue );
383     }
384 }