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