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 1042842 2010-12-06 23:09:03Z 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, ArtifactRepository localRepository )
207     {
208         if ( Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) )
209         {
210             return null;
211         }
212 
213         Artifact copyArtifact = ArtifactUtils.copyArtifact( artifact );
214         if ( !"pom".equals( copyArtifact.getType() ) )
215         {
216             copyArtifact =
217                 factory.createProjectArtifact( copyArtifact.getGroupId(), copyArtifact.getArtifactId(),
218                                                copyArtifact.getVersion(), copyArtifact.getScope() );
219         }
220         try
221         {
222             MavenProject pluginProject =
223                 mavenProjectBuilder.buildFromRepository( copyArtifact,
224                                                          remoteRepositories == null ? Collections.EMPTY_LIST
225                                                                          : remoteRepositories, localRepository );
226 
227             if ( isArtifactUrlValid( pluginProject.getUrl() ) )
228             {
229                 return pluginProject.getUrl();
230             }
231 
232             return null;
233         }
234         catch ( ProjectBuildingException e )
235         {
236             return null;
237         }
238     }
239 
240     /**
241      * @param artifactId not null
242      * @param link could be null
243      * @return the artifactId cell with or without a link pattern
244      * @see AbstractMavenReportRenderer#linkPatternedText(String)
245      */
246     public static String getArtifactIdCell( String artifactId, String link )
247     {
248         if ( StringUtils.isEmpty( link ) )
249         {
250             return artifactId;
251         }
252 
253         return "{" + artifactId + "," + link + "}";
254     }
255 
256     /**
257      * @param url not null
258      * @return <code>true</code> if the url is valid, <code>false</code> otherwise.
259      */
260     public static boolean isArtifactUrlValid( String url )
261     {
262         if ( StringUtils.isEmpty( url ) )
263         {
264             return false;
265         }
266 
267         return URL_VALIDATOR.isValid( url );
268     }
269 
270     /**
271      * @param url not null
272      * @param project not null
273      * @param settings not null
274      * @return the url connection with auth if required. Don't check the certificate if SSL scheme.
275      * @throws IOException if any
276      */
277     private static URLConnection getURLConnection( URL url, MavenProject project, Settings settings )
278         throws IOException
279     {
280         URLConnection conn = url.openConnection();
281         conn.setConnectTimeout( TIMEOUT );
282         conn.setReadTimeout( TIMEOUT );
283 
284         // conn authorization
285         if ( settings.getServers() != null
286             && !settings.getServers().isEmpty()
287             && project != null
288             && project.getDistributionManagement() != null
289             && ( project.getDistributionManagement().getRepository() != null || project.getDistributionManagement().getSnapshotRepository() != null )
290             && ( StringUtils.isNotEmpty( project.getDistributionManagement().getRepository().getUrl() ) || StringUtils.isNotEmpty( project.getDistributionManagement().getSnapshotRepository().getUrl() ) ) )
291         {
292             Server server = null;
293             if ( url.toString().contains( project.getDistributionManagement().getRepository().getUrl() ) )
294             {
295                 server = settings.getServer( project.getDistributionManagement().getRepository().getId() );
296             }
297             if ( server == null
298                 && url.toString().contains( project.getDistributionManagement().getSnapshotRepository().getUrl() ) )
299             {
300                 server = settings.getServer( project.getDistributionManagement().getSnapshotRepository().getId() );
301             }
302 
303             if ( server != null && StringUtils.isNotEmpty( server.getUsername() )
304                 && StringUtils.isNotEmpty( server.getPassword() ) )
305             {
306                 String up = server.getUsername().trim() + ":" + server.getPassword().trim();
307                 String upEncoded = new String( Base64.encodeBase64Chunked( up.getBytes() ) ).trim();
308 
309                 conn.setRequestProperty( "Authorization", "Basic " + upEncoded );
310             }
311         }
312 
313         if ( conn instanceof HttpsURLConnection )
314         {
315             HostnameVerifier hostnameverifier = new HostnameVerifier()
316             {
317                 /** {@inheritDoc} */
318                 public boolean verify( String urlHostName, SSLSession session )
319                 {
320                     return true;
321                 }
322             };
323             ( (HttpsURLConnection) conn ).setHostnameVerifier( hostnameverifier );
324 
325             TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager()
326             {
327                 /** {@inheritDoc} */
328                 public void checkClientTrusted( final X509Certificate[] chain, final String authType )
329                 {
330                 }
331 
332                 /** {@inheritDoc} */
333                 public void checkServerTrusted( final X509Certificate[] chain, final String authType )
334                 {
335                 }
336 
337                 /** {@inheritDoc} */
338                 public X509Certificate[] getAcceptedIssuers()
339                 {
340                     return null;
341                 }
342             } };
343 
344             try
345             {
346                 SSLContext sslContext = SSLContext.getInstance( "SSL" );
347                 sslContext.init( null, trustAllCerts, new SecureRandom() );
348 
349                 SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
350 
351                 ( (HttpsURLConnection) conn ).setSSLSocketFactory( sslSocketFactory );
352             }
353             catch ( NoSuchAlgorithmException e1 )
354             {
355                 // ignore
356             }
357             catch ( KeyManagementException e )
358             {
359                 // ignore
360             }
361         }
362 
363         return conn;
364     }
365 
366     public static boolean isNumber( String str )
367     {
368         if ( str.startsWith( "+" ) )
369         {
370             str = str.substring( 1 );
371         }
372         return NumberUtils.isNumber( str );
373     }
374 
375     public static int toInt( String str, int defaultValue )
376     {
377         if ( str.startsWith( "+" ) )
378         {
379             str = str.substring( 1 );
380         }
381         return NumberUtils.toInt( str, defaultValue );
382     }
383 }