Coverage Report - org.apache.maven.announcement.JiraAnnouncementDownloader
 
Classes in this File Line Coverage Branch Coverage Complexity
JiraAnnouncementDownloader
0% 
0% 
2,818
 
 1  
 package org.apache.maven.announcement;
 2  
 
 3  
 /*
 4  
  * Copyright 2001-2006 The Apache Software Foundation.
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License");
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *      http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 18  
 
 19  
 import org.apache.commons.httpclient.Credentials;
 20  
 import org.apache.commons.httpclient.Header;
 21  
 import org.apache.commons.httpclient.HostConfiguration;
 22  
 import org.apache.commons.httpclient.HttpClient;
 23  
 import org.apache.commons.httpclient.HttpException;
 24  
 import org.apache.commons.httpclient.HttpState;
 25  
 import org.apache.commons.httpclient.HttpStatus;
 26  
 import org.apache.commons.httpclient.StatusLine;
 27  
 import org.apache.commons.httpclient.UsernamePasswordCredentials;
 28  
 import org.apache.commons.httpclient.methods.GetMethod;
 29  
 import org.apache.maven.jira.JiraHelper;
 30  
 import org.apache.maven.plugin.logging.Log;
 31  
 import org.apache.maven.project.MavenProject;
 32  
 import org.apache.maven.settings.Proxy;
 33  
 import org.apache.maven.settings.Settings;
 34  
 
 35  
 import java.io.File;
 36  
 import java.io.FileWriter;
 37  
 import java.io.IOException;
 38  
 import java.io.PrintWriter;
 39  
 import java.util.HashMap;
 40  
 import java.util.Map;
 41  
 
 42  
 /**
 43  
  * Gets relevant issues in RSS from a given JIRA installation.
 44  
  *
 45  
  * Based on version 1.1.2 and patch by Dr. Spock (MPJIRA-8).
 46  
  *
 47  
  * @author mfranken@xebia.com
 48  
  * @author jruiz@exist.com
 49  0
  * @version $Id: org.apache.maven.announcement.JiraAnnouncementDownloader.html 816584 2012-05-08 12:33:35Z hboutemy $
 50  0
  */
 51  0
 public final class JiraAnnouncementDownloader
 52  
 {
 53  
 
 54  
     /** Log for debug output. */
 55  
     private org.apache.maven.plugin.logging.Log log;
 56  
 
 57  
     /** Output file for xml document. */
 58  
     private File output;
 59  
 
 60  
     /** The maximum number of entries to show. */
 61  
     private int nbEntriesMax;
 62  
 
 63  
     /** The filter to apply to query to JIRA. */
 64  
     private String filter;
 65  
 
 66  
     /** Ids of status to show, as comma separated string. */
 67  
     private String statusIds;
 68  
 
 69  
     /** Ids of resolution to show, as comma separated string. */
 70  
     private String resolutionIds;
 71  
 
 72  
     /** Ids of priority to show, as comma separated string. */
 73  
     private String priorityIds;
 74  
 
 75  
     /** The component to show. */
 76  
     private String component;
 77  
 
 78  
     /** The username to log into JIRA. */
 79  
     private String jiraUser;
 80  
 
 81  
     /** The password to log into JIRA. */
 82  
     private String jiraPassword;
 83  
 
 84  
     /** The username to log into webserver. */
 85  
     private String webUser;
 86  
 
 87  
     /** The password to log into webserver. */
 88  
     private String webPassword;
 89  
 
 90  
     /** The maven project. */
 91  
     private MavenProject project;
 92  
 
 93  
     /** The maven settings. */
 94  
     private Settings settings;
 95  0
 
 96  0
     /** Mapping containing all JIRA status values. */
 97  0
     private static Map statusMap = new HashMap();
 98  0
 
 99  0
     /** Mapping containing all JIRA resolution values. */
 100  0
     private static Map resolutionMap = new HashMap();
 101  0
 
 102  0
     /** Mapping containing all JIRA priority values. */
 103  0
     private static Map priorityMap = new HashMap();
 104  
 
 105  0
     static
 106  0
     {
 107  0
         statusMap.put( "Closed", "6" );
 108  0
 
 109  0
         resolutionMap.put( "Fixed", "1" );
 110  0
 
 111  0
         priorityMap.put( "Blocker", "1" );
 112  0
         priorityMap.put( "Critical", "2" );
 113  0
         priorityMap.put( "Major", "3" );
 114  0
         priorityMap.put( "Minor", "4" );
 115  0
         priorityMap.put( "Trivial", "5" );
 116  0
     }
 117  
 
 118  
     /**
 119  
      * Creates a filter given the parameters and some defaults.
 120  
      *
 121  
      * @return request parameters to be added to URL used for downloading the JIRA issues
 122  
      */
 123  0
     private String createFilter()
 124  0
     {
 125  0
         if ( ( this.filter != null ) && ( this.filter.length() > 0 ) )
 126  0
         {
 127  0
             if ( this.filter.charAt( 0 ) == '&' )
 128  0
             {
 129  0
                 return this.filter.substring( 1 );
 130  0
             }
 131  0
 
 132  0
             return this.filter;
 133  0
         }
 134  0
 
 135  0
         StringBuffer localFilter = new StringBuffer();
 136  0
 
 137  0
         // get the Status Ids
 138  0
         if ( statusIds != null )
 139  0
         {
 140  0
             String[] stats = statusIds.split( "," );
 141  0
 
 142  0
             for ( int i = 0; i < stats.length; i++ )
 143  0
             {
 144  0
                 String statusParam = (String) statusMap.get( stats[i] );
 145  0
 
 146  0
                 if ( statusParam != null )
 147  0
                 {
 148  0
                     localFilter.append( "&statusIds=" + statusParam );
 149  
                 }
 150  
             }
 151  
         }
 152  
 
 153  0
         // get the Priority Ids
 154  0
         if ( priorityIds != null )
 155  0
         {
 156  0
             String[] prios = priorityIds.split( "," );
 157  0
 
 158  0
             for ( int i = 0; i < prios.length; i++ )
 159  0
             {
 160  0
                 String priorityParam = (String) priorityMap.get( prios[i] );
 161  0
 
 162  0
                 if ( priorityParam != null )
 163  0
                 {
 164  0
                     localFilter.append( "&priorityIds=" + priorityParam );
 165  
                 }
 166  
             }
 167  
         }
 168  0
 
 169  0
         if ( resolutionIds != null )
 170  
         {
 171  0
             // get the Resolution Ids
 172  0
             String[] resos = resolutionIds.split( "," );
 173  0
 
 174  0
             for ( int i = 0; i < resos.length; i++ )
 175  0
             {
 176  0
                 String resoParam = (String) resolutionMap.get( resos[i] );
 177  0
 
 178  0
                 if ( resoParam != null )
 179  0
                 {
 180  0
                     localFilter.append( "&resolutionIds=" + resoParam );
 181  
                 }
 182  
             }
 183  
         }
 184  
 
 185  0
         // add all components
 186  0
         if ( component != null )
 187  0
         {
 188  0
             String[] components = component.split( "," );
 189  0
 
 190  0
             for ( int i = 0; i < components.length; i++ )
 191  0
             {
 192  0
                 if ( components[i].length() > 0 )
 193  0
                 {
 194  0
                     localFilter.append( "&component=" + components[i] );
 195  
                 }
 196  
             }
 197  
         }
 198  
 
 199  0
         // add default sorting (by priority and then creation date)
 200  0
         String sort = "&sorter/field=created&sorter/order=DESC" + "&sorter/field=priority&sorter/order=DESC";
 201  0
 
 202  0
         return localFilter + sort;
 203  
     }
 204  
 
 205  
     /**
 206  
      * Execute the query on the JIRA server.
 207  
      *
 208  
      * @throws Exception on error
 209  
      */
 210  
     public void doExecute()
 211  
         throws Exception
 212  
     {
 213  
         try
 214  0
         {
 215  0
             HttpClient cl = new HttpClient();
 216  0
 
 217  0
             HttpState state = new HttpState();
 218  0
 
 219  0
             HostConfiguration hc = new HostConfiguration();
 220  0
 
 221  0
             cl.setHostConfiguration( hc );
 222  0
 
 223  0
             cl.setState( state );
 224  0
 
 225  0
             determineProxy( cl );
 226  0
 
 227  0
             Map urlMap = getJiraUrlAndIssueId();
 228  0
 
 229  0
             String jiraUrl = (String) urlMap.get( "url" );
 230  0
 
 231  0
             String jiraId = (String) urlMap.get( "id" );
 232  0
 
 233  0
             doAuthentication( cl, jiraUrl );
 234  0
 
 235  0
             if ( jiraId == null || jiraId.length() == 0 )
 236  0
             {
 237  0
                 jiraId = JiraHelper.getPidFromJira( log, project.getIssueManagement().getUrl(), cl );
 238  
             }
 239  0
 
 240  0
             // create the URL for getting the proper issues from JIRA
 241  0
             String fullURL = jiraUrl + "/secure/IssueNavigator.jspa?view=rss&pid=" + jiraId;
 242  
 
 243  0
             // @todo: only for a temporary use case, hardcoded fix-for version
 244  0
             fullURL += "&fixfor=12730";
 245  0
 
 246  0
             fullURL += createFilter();
 247  0
 
 248  0
             fullURL += ( "&tempMax=" + nbEntriesMax + "&reset=true&decorator=none" );
 249  
 
 250  0
             // execute the GET
 251  0
             download( cl, fullURL );
 252  0
         }
 253  0
         catch ( Exception e )
 254  0
         {
 255  0
             getLog().error( "Error accessing " + project.getIssueManagement().getUrl(), e );
 256  0
         }
 257  0
     }
 258  0
 
 259  
     private Map getJiraUrlAndIssueId()
 260  0
     {
 261  0
         HashMap urlMap = new HashMap();
 262  0
 
 263  0
         String url = project.getIssueManagement().getUrl();
 264  0
 
 265  0
         // chop off the parameter part
 266  0
         int pos = url.indexOf( "?" );
 267  
 
 268  0
         // and get the id while we're at it
 269  0
         String id = "";
 270  0
 
 271  0
         if ( pos >= 0 )
 272  0
         {
 273  0
             // url
 274  0
             id = url.substring( url.lastIndexOf( "=" ) + 1 );
 275  
         }
 276  0
 
 277  0
         String jiraUrl = url.substring( 0, url.lastIndexOf( "/" ) );
 278  0
 
 279  0
         if ( jiraUrl.endsWith( "secure" ) || jiraUrl.endsWith( "browse" ) )
 280  0
         {
 281  0
             jiraUrl = jiraUrl.substring( 0, jiraUrl.lastIndexOf( "/" ) );
 282  0
         }
 283  0
         getLog().info( "JIRA lives at: " + jiraUrl );
 284  0
 
 285  0
         urlMap.put( "url", jiraUrl );
 286  0
 
 287  0
         urlMap.put( "id", id );
 288  0
 
 289  0
         return urlMap;
 290  
     }
 291  
 
 292  
     /**
 293  
      * Authenticate against webserver and into JIRA if we have to.
 294  
      *
 295  
      * @param client    the HttpClient
 296  0
      * @param jiraUrl   the JIRA installation
 297  
      */
 298  0
     private void doAuthentication( HttpClient client, final String jiraUrl )
 299  
     {
 300  0
         // check and prepare for basic authentication
 301  0
         if ( ( webUser != null ) && ( webUser.length() > 0 ) )
 302  0
         {
 303  0
             client.getState().setAuthenticationPreemptive( true );
 304  0
 
 305  0
             Credentials defaultcreds = new UsernamePasswordCredentials( webUser, webPassword );
 306  0
 
 307  0
             getLog().info( "Using username: " + webUser + " for Basic Authentication against the webserver at "
 308  0
                 + jiraUrl );
 309  0
 
 310  0
             client.getState().setCredentials( null, null, defaultcreds );
 311  
         }
 312  0
 
 313  0
         // log into JIRA if we have to
 314  0
         String loginUrl = null;
 315  0
 
 316  0
         if ( ( jiraUser != null ) && ( jiraUser.length() > 0 ) && ( jiraPassword != null ) )
 317  0
         {
 318  0
             StringBuffer loginLink = new StringBuffer( jiraUrl );
 319  0
 
 320  0
             loginLink.append( "/login.jsp?os_destination=/secure/" );
 321  0
 
 322  0
             loginLink.append( "&os_username=" ).append( jiraUser );
 323  0
 
 324  0
             getLog().info( "Login URL: " + loginLink + "&os_password=*******" );
 325  0
 
 326  0
             loginLink.append( "&os_password=" ).append( jiraPassword );
 327  0
 
 328  0
             loginUrl = loginLink.toString();
 329  
         }
 330  0
 
 331  0
         // execute the login
 332  0
         if ( loginUrl != null )
 333  0
         {
 334  0
             GetMethod loginGet = new GetMethod( loginUrl );
 335  
 
 336  0
             try
 337  0
             {
 338  0
                 client.executeMethod( loginGet );
 339  0
 
 340  0
                 getLog().info( "Succesfully logged in into JIRA." );
 341  0
             }
 342  0
             catch ( Exception e )
 343  0
             {
 344  0
                 if ( getLog().isDebugEnabled() )
 345  0
                 {
 346  0
                     getLog().error( "Error trying to login into JIRA:", e );
 347  0
                 }
 348  0
                 else
 349  0
                 {
 350  0
                     getLog().error( "Error trying to login into JIRA. Cause is: " + e.getLocalizedMessage() );
 351  0
                 }
 352  0
                 // continue any way, probably will fail later if authentication was necesaaray afterall
 353  0
             }
 354  0
         }
 355  0
     }
 356  
 
 357  
     /**
 358  
      * Setup proxy access if we have to.
 359  0
      *
 360  
      * @param client  the HttpClient
 361  0
      */
 362  
     private void determineProxy( HttpClient client )
 363  0
     {
 364  0
         // see whether there is any proxy defined in maven
 365  0
         Proxy proxy = null;
 366  0
 
 367  0
         String proxyHost = null;
 368  0
 
 369  0
         int proxyPort = 0;
 370  0
 
 371  0
         String proxyUser = null;
 372  0
 
 373  0
         String proxyPass = null;
 374  0
 
 375  0
         if ( project == null )
 376  0
         {
 377  0
             getLog().error( "No project set. No proxy info available." );
 378  0
 
 379  0
             return;
 380  0
         }
 381  0
 
 382  0
         if ( settings != null )
 383  0
         {
 384  0
             proxy = settings.getActiveProxy();
 385  0
         }
 386  0
 
 387  0
         if ( proxy != null )
 388  0
         {
 389  0
             proxyHost = settings.getActiveProxy().getHost();
 390  0
 
 391  0
             proxyPort = settings.getActiveProxy().getPort();
 392  0
 
 393  0
             proxyUser = settings.getActiveProxy().getUsername();
 394  0
 
 395  0
             proxyPass = settings.getActiveProxy().getPassword();
 396  0
 
 397  0
             getLog().info( proxyPass );
 398  0
         }
 399  0
 
 400  0
         if ( proxyHost != null )
 401  0
         {
 402  0
             client.getHostConfiguration().setProxy( proxyHost, proxyPort );
 403  0
 
 404  0
             getLog().info( "Using proxy: " + proxyHost + " at port " + proxyPort );
 405  0
 
 406  0
             if ( proxyUser != null )
 407  0
             {
 408  0
                 getLog().info( "Using proxy user: " + proxyUser );
 409  0
 
 410  0
                 client.getState().setProxyCredentials( null, null,
 411  
                                                        new UsernamePasswordCredentials( proxyUser, proxyPass ) );
 412  0
             }
 413  0
         }
 414  0
     }
 415  
 
 416  
     /**
 417  
      * Downloads the given link using the configured HttpClient, possibly following redirects.
 418  
      *
 419  
      * @param cl     the HttpClient
 420  
      * @param link   the URL to JIRA
 421  0
      */
 422  
     private void download( final HttpClient cl, final String link )
 423  0
     {
 424  
         try
 425  0
         {
 426  0
             GetMethod gm = new GetMethod( link );
 427  0
 
 428  0
             getLog().info( "Downloading " + link );
 429  0
 
 430  0
             gm.setFollowRedirects( true );
 431  0
 
 432  0
             cl.executeMethod( gm );
 433  0
 
 434  0
             final String strGetResponseBody = gm.getResponseBodyAsString();
 435  
 
 436  0
             // write the reponse to file
 437  0
             PrintWriter pw = new PrintWriter( new FileWriter( getOutput() ) );
 438  0
 
 439  0
             pw.print( strGetResponseBody );
 440  0
 
 441  0
             pw.close();
 442  0
 
 443  0
             StatusLine sl = gm.getStatusLine();
 444  0
 
 445  0
             if ( sl == null )
 446  0
             {
 447  0
                 getLog().info( "Unknown error validating link : " + link );
 448  0
 
 449  0
                 return;
 450  0
             }
 451  
 
 452  0
             // if we get a redirect, do so
 453  0
             if ( gm.getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY )
 454  0
             {
 455  0
                 Header locationHeader = gm.getResponseHeader( "Location" );
 456  0
 
 457  0
                 if ( locationHeader == null )
 458  0
                 {
 459  0
                     getLog().info( "Site sent redirect, but did not set Location header" );
 460  0
                 }
 461  
                 else
 462  0
                 {
 463  0
                     String newLink = locationHeader.getValue();
 464  0
 
 465  0
                     getLog().debug( "Following redirect to " + newLink );
 466  0
 
 467  0
                     download( cl, newLink );
 468  0
                 }
 469  
             }
 470  0
 
 471  0
             if ( gm.getStatusCode() != HttpStatus.SC_OK )
 472  0
             {
 473  0
                 getLog().warn( "Received: [" + gm.getStatusCode() + "]" );
 474  
             }
 475  0
         }
 476  0
         catch ( HttpException e )
 477  0
         {
 478  0
             if ( getLog().isDebugEnabled() )
 479  0
             {
 480  0
                 getLog().error( "Error downloading issues from JIRA:", e );
 481  
             }
 482  
             else
 483  0
             {
 484  0
                 getLog().error( "Error downloading issues from JIRA url :  " + e.getLocalizedMessage() );
 485  0
 
 486  
             }
 487  0
         }
 488  0
         catch ( IOException e )
 489  0
         {
 490  0
             if ( getLog().isDebugEnabled() )
 491  0
             {
 492  0
                 getLog().error( "Error downloading issues from JIRA :", e );
 493  0
             }
 494  0
             else
 495  0
             {
 496  0
                 getLog().error( "Error downloading issues from JIRA. Cause is " + e.getLocalizedMessage() );
 497  0
             }
 498  0
         }
 499  0
     }
 500  
 
 501  
     /**
 502  
      * Set the output file for the log.
 503  0
      *
 504  0
      * @param thisOutput the output file
 505  
      */
 506  
     public void setOutput( File thisOutput )
 507  0
     {
 508  0
         this.output = thisOutput;
 509  0
     }
 510  
 
 511  
     public File getOutput()
 512  0
     {
 513  0
         return this.output;
 514  
     }
 515  
 
 516  
     /**
 517  
      * Sets the project.
 518  0
      *
 519  0
      * @param thisProject  The project to set
 520  
      */
 521  
     public void setMavenProject( Object thisProject )
 522  0
     {
 523  0
         this.project = (MavenProject) thisProject;
 524  0
     }
 525  
 
 526  
     /**
 527  
      * Sets the maximum number of Issues to show.
 528  0
      *
 529  0
      * @param nbEntries  The maximum number of Issues
 530  
      */
 531  
     public void setNbEntries( final int nbEntries )
 532  0
     {
 533  0
         nbEntriesMax = nbEntries;
 534  0
     }
 535  
 
 536  
     /**
 537  
      * Sets the statusIds.
 538  0
      *
 539  0
      * @param thisStatusIds   The id(s) of the status to show, as comma separated string
 540  
      */
 541  
     public void setStatusIds( String thisStatusIds )
 542  0
     {
 543  0
         statusIds = thisStatusIds;
 544  0
     }
 545  
 
 546  
     /**
 547  
      * Sets the priorityIds.
 548  0
      *
 549  0
      * @param thisPriorityIds  The id(s) of the priority to show, as comma separated string
 550  
      */
 551  
     public void setPriorityIds( String thisPriorityIds )
 552  0
     {
 553  0
         priorityIds = thisPriorityIds;
 554  0
     }
 555  
 
 556  
     /**
 557  
      * Sets the resolutionIds.
 558  0
      *
 559  0
      * @param thisResolutionIds  The id(s) of the resolution to show, as comma separated string
 560  
      */
 561  
     public void setResolutionIds( String thisResolutionIds )
 562  0
     {
 563  0
         resolutionIds = thisResolutionIds;
 564  0
     }
 565  
 
 566  
     /**
 567  
      * Sets the password for authentication against the webserver.
 568  0
      *
 569  0
      * @param thisWebPassword  The password of the webserver
 570  
      */
 571  
     public void setWebPassword( String thisWebPassword )
 572  0
     {
 573  0
         this.webPassword = thisWebPassword;
 574  0
     }
 575  
 
 576  
     /**
 577  
      * Sets the username for authentication against the webserver.
 578  0
      *
 579  0
      * @param thisWebUser   The username of the webserver
 580  
      */
 581  
     public void setWebUser( String thisWebUser )
 582  0
     {
 583  0
         this.webUser = thisWebUser;
 584  0
     }
 585  
 
 586  
     /**
 587  
      * Sets the password to log into a secured JIRA.
 588  0
      *
 589  0
      * @param thisJiraPassword  The password for JIRA
 590  
      */
 591  
     public void setJiraPassword( final String thisJiraPassword )
 592  0
     {
 593  0
         this.jiraPassword = thisJiraPassword;
 594  0
     }
 595  
 
 596  
     /**
 597  
      * Sets the username to log into a secured JIRA.
 598  0
      *
 599  0
      * @param thisJiraUser  The username for JIRA
 600  
      */
 601  
     public void setJiraUser( String thisJiraUser )
 602  0
     {
 603  0
         this.jiraUser = thisJiraUser;
 604  0
     }
 605  
 
 606  
     /**
 607  
      * Sets the filter to apply to query to JIRA.
 608  0
      *
 609  0
      * @param thisFilter  The filter to query JIRA
 610  
      */
 611  
     public void setFilter( String thisFilter )
 612  0
     {
 613  0
         this.filter = thisFilter;
 614  0
     }
 615  
 
 616  
     /**
 617  
      * Sets the component(s) to apply to query JIRA.
 618  0
      *
 619  0
      * @param theseComponents   The id(s) of components to show, as comma separated string
 620  
      */
 621  
     public void setComponent( String theseComponents )
 622  0
     {
 623  0
         this.component = theseComponents;
 624  0
     }
 625  
 
 626  
     public void setLog( Log log )
 627  0
     {
 628  0
         this.log = log;
 629  0
     }
 630  
 
 631  
     private org.apache.maven.plugin.logging.Log getLog()
 632  0
     {
 633  0
         return log;
 634  0
     }
 635  
 
 636  
     public void setSettings( Settings settings )
 637  0
     {
 638  0
         this.settings = settings;
 639  0
     }
 640  
 }