Coverage Report - org.apache.maven.plugin.jira.AbstractJiraDownloader
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractJiraDownloader
14%
41/290
0%
0/150
3.833
 
 1  
 package org.apache.maven.plugin.jira;
 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 org.apache.commons.httpclient.cookie.CookiePolicy;
 23  
 import org.apache.commons.httpclient.Credentials;
 24  
 import org.apache.commons.httpclient.Header;
 25  
 import org.apache.commons.httpclient.HostConfiguration;
 26  
 import org.apache.commons.httpclient.HttpClient;
 27  
 import org.apache.commons.httpclient.HttpException;
 28  
 import org.apache.commons.httpclient.HttpState;
 29  
 import org.apache.commons.httpclient.HttpStatus;
 30  
 import org.apache.commons.httpclient.StatusLine;
 31  
 import org.apache.commons.httpclient.UsernamePasswordCredentials;
 32  
 import org.apache.commons.httpclient.params.HttpClientParams;
 33  
 import org.apache.commons.httpclient.auth.AuthScope;
 34  
 import org.apache.commons.httpclient.methods.GetMethod;
 35  
 import org.apache.maven.plugin.MojoExecutionException;
 36  
 import org.apache.maven.plugin.issues.Issue;
 37  
 import org.apache.maven.plugin.logging.Log;
 38  
 import org.apache.maven.project.MavenProject;
 39  
 import org.apache.maven.settings.Proxy;
 40  
 import org.apache.maven.settings.Settings;
 41  
 import org.apache.maven.wagon.proxy.ProxyInfo;
 42  
 import org.codehaus.plexus.util.IOUtil;
 43  
 import org.codehaus.plexus.util.StringUtils;
 44  
 
 45  
 import java.io.File;
 46  
 import java.io.FileOutputStream;
 47  
 import java.io.IOException;
 48  
 import java.io.InputStream;
 49  
 import java.io.OutputStream;
 50  
 import java.net.MalformedURLException;
 51  
 import java.net.URL;
 52  
 import java.net.URLEncoder;
 53  
 import java.util.Collections;
 54  
 import java.util.HashMap;
 55  
 import java.util.List;
 56  
 import java.util.Locale;
 57  
 import java.util.Map;
 58  
 
 59  
 /**
 60  
  * Gets relevant issues in RSS from a given JIRA installation.
 61  
  * <p/>
 62  
  * Based on version 1.1.2 and patch by Dr. Spock (MPJIRA-8).
 63  
  *
 64  
  * @author mfranken@xebia.com
 65  
  * @author jruiz@exist.com
 66  
  * @version $Id: AbstractJiraDownloader.java 1328930 2012-04-22 18:42:02Z bimargulies $
 67  
  */
 68  1
 public abstract class AbstractJiraDownloader
 69  
 {
 70  
     private static final String UTF_8 = "UTF-8";
 71  
 
 72  
     /** Log for debug output. */
 73  
     protected Log log;
 74  
     /** Output file for xml document. */
 75  
     private File output;
 76  
     /** The maximum number of entries to show. */
 77  
     private int nbEntriesMax;
 78  
     /** The filter to apply to query to JIRA. */
 79  
     private String filter;
 80  
     /** Ids of fix versions to show, as comma separated string. */
 81  
     private String fixVersionIds;
 82  
     /** Ids of status to show, as comma separated string. */
 83  
     private String statusIds;
 84  
     /** Ids of resolution to show, as comma separated string. */
 85  
     private String resolutionIds;
 86  
     /** Ids of priority to show, as comma separated string. */
 87  
     private String priorityIds;
 88  
     /** The component to show. */
 89  
     private String component;
 90  
     /** Ids of types to show, as comma separated string. */
 91  
     private String typeIds;
 92  
     /** Column names to sort by, as comma separated string. */
 93  
     private String sortColumnNames;
 94  
     /** The username to log into JIRA. */
 95  
     private String jiraUser;
 96  
     /** The password to log into JIRA. */
 97  
     private String jiraPassword;
 98  
     /** The username to log into webserver. */
 99  
     private String webUser;
 100  
     /** The password to log into webserver. */
 101  
     private String webPassword;
 102  
     /** The maven project. */
 103  
     private MavenProject project;
 104  
     /** The maven settings. */
 105  
     private Settings settings;
 106  
     /** Mapping containing all allowed JIRA status values. */
 107  1
     protected final Map<String,String> statusMap = new HashMap<String,String>( 8 );
 108  
     /** Mapping containing all allowed JIRA resolution values. */
 109  1
     protected final Map<String,String> resolutionMap = new HashMap<String,String>( 8 );
 110  
     /** Mapping containing all allowed JIRA priority values. */
 111  1
     protected final Map<String,String> priorityMap = new HashMap<String,String>( 8 );
 112  
     /** Mapping containing all allowed JIRA type values. */
 113  1
     protected final Map<String,String> typeMap = new HashMap<String,String>( 8 );
 114  
     /** The pattern used to parse dates from the JIRA xml file. */
 115  
     protected String jiraDatePattern;
 116  
 
 117  
     /**
 118  
      * Creates a filter given the parameters and some defaults.
 119  
      *
 120  
      * @return request parameters to be added to URL used for downloading the JIRA issues
 121  
      */
 122  
     private String createFilter()
 123  
     {
 124  
         // If the user has defined a filter - use that
 125  0
         if ( ( this.filter != null ) && ( this.filter.length() > 0 ) )
 126  
         {
 127  0
             return this.filter;
 128  
         }
 129  
 
 130  0
         StringBuffer localFilter = new StringBuffer( 16 );
 131  
 
 132  
         // add fix versions
 133  0
         if ( fixVersionIds != null )
 134  
         {
 135  0
             String[] fixVersions = fixVersionIds.split( "," );
 136  
 
 137  0
             for ( int i = 0; i < fixVersions.length; i++ )
 138  
             {
 139  0
                 if ( fixVersions[i].length() > 0 )
 140  
                 {
 141  0
                     localFilter.append( "&fixfor=" ).append( fixVersions[i].trim() );
 142  
                 }
 143  
             }
 144  
         }
 145  
 
 146  
         // get the Status Ids
 147  0
         if ( statusIds != null )
 148  
         {
 149  0
             String[] stats = statusIds.split( "," );
 150  0
             for ( String stat : stats )
 151  
             {
 152  0
                 stat = stat.trim();
 153  0
                 String statusParam = statusMap.get( stat );
 154  
 
 155  0
                 if ( statusParam != null )
 156  
                 {
 157  0
                     localFilter.append( "&statusIds=" ).append( statusParam );
 158  
                 }
 159  
                 else
 160  
                 {
 161  
                     // if it's numeric we can handle it too.
 162  
                     try
 163  
                     {
 164  0
                         Integer.parseInt( stat );
 165  0
                         localFilter.append( "&statusIds=" ).append( stat );
 166  
                     }
 167  0
                     catch ( NumberFormatException nfe )
 168  
                     {
 169  0
                         getLog().error( "maven-changes-plugin: invalid statusId " + stat );
 170  0
                     }
 171  
                 }
 172  
             }
 173  
         }
 174  
 
 175  
         // get the Priority Ids
 176  0
         if ( priorityIds != null )
 177  
         {
 178  0
             String[] prios = priorityIds.split( "," );
 179  
 
 180  0
             for ( String prio : prios ) 
 181  
             {
 182  0
                 prio = prio.trim();
 183  0
                 String priorityParam = priorityMap.get( prio );
 184  
 
 185  0
                 if ( priorityParam != null )
 186  
                 {
 187  0
                     localFilter.append( "&priorityIds=" ).append( priorityParam );
 188  
                 }
 189  
             }
 190  
         }
 191  
 
 192  
         // get the Resolution Ids
 193  0
         if ( resolutionIds != null )
 194  
         {
 195  0
             String[] resos = resolutionIds.split( "," );
 196  
 
 197  0
             for ( String reso : resos ) 
 198  
             {
 199  0
                 reso = reso.trim();
 200  0
                 String resoParam = resolutionMap.get( reso );
 201  
 
 202  0
                 if ( resoParam != null )
 203  
                 {
 204  0
                     localFilter.append( "&resolutionIds=" ).append( resoParam );
 205  
                 }
 206  
             }
 207  
         }
 208  
 
 209  
         // add components
 210  0
         if ( component != null )
 211  
         {
 212  0
             String[] components = component.split( "," );
 213  
 
 214  0
             for ( String component : components ) 
 215  
             {
 216  0
                 component = component.trim();
 217  0
                 if ( component.length() > 0 )
 218  
                 {
 219  0
                     localFilter.append( "&component=" ).append( component );
 220  
                 }
 221  
             }
 222  
         }
 223  
 
 224  
         // get the Type Ids
 225  0
         if ( typeIds != null )
 226  
         {
 227  0
             String[] types = typeIds.split( "," );
 228  
 
 229  0
             for ( String type : types )
 230  
             {
 231  0
                 String typeParam = typeMap.get( type.trim() );
 232  
 
 233  0
                 if ( typeParam != null )
 234  
                 {
 235  0
                     localFilter.append( "&type=" ).append( typeParam );
 236  
                 }
 237  
             }
 238  
         }
 239  
 
 240  
         // get the Sort order
 241  0
         int validSortColumnNames = 0;
 242  0
         if ( sortColumnNames != null )
 243  
         {
 244  0
             String[] sortColumnNamesArray = sortColumnNames.split( "," );
 245  
             // N.B. Add in reverse order (it's the way JIRA 3 likes it!!)
 246  0
             for ( int i = sortColumnNamesArray.length - 1; i >= 0; i-- )
 247  
             {
 248  0
                 String lowerColumnName = sortColumnNamesArray[i].trim().toLowerCase( Locale.ENGLISH );
 249  0
                 boolean descending = false;
 250  0
                 String fieldName = null;
 251  0
                 if ( lowerColumnName.endsWith( "desc" ) )
 252  
                 {
 253  0
                     descending = true;
 254  0
                     lowerColumnName = lowerColumnName.substring( 0, lowerColumnName.length() - 4 ).trim();
 255  
                 }
 256  0
                 else if ( lowerColumnName.endsWith( "asc" ) )
 257  
                 {
 258  0
                     descending = false;
 259  0
                     lowerColumnName = lowerColumnName.substring( 0, lowerColumnName.length() - 3 ).trim();
 260  
                 }
 261  
 
 262  0
                 if ( "key".equals( lowerColumnName ) )
 263  
                 {
 264  0
                     fieldName = "issuekey";
 265  
                 }
 266  0
                 else if ( "summary".equals( lowerColumnName ) )
 267  
                 {
 268  0
                     fieldName = lowerColumnName;
 269  
                 }
 270  0
                 else if ( "status".equals( lowerColumnName ) )
 271  
                 {
 272  0
                     fieldName = lowerColumnName;
 273  
                 }
 274  0
                 else if ( "resolution".equals( lowerColumnName ) )
 275  
                 {
 276  0
                     fieldName = lowerColumnName;
 277  
                 }
 278  0
                 else if ( "assignee".equals( lowerColumnName ) )
 279  
                 {
 280  0
                     fieldName = lowerColumnName;
 281  
                 }
 282  0
                 else if ( "reporter".equals( lowerColumnName ) )
 283  
                 {
 284  0
                     fieldName = lowerColumnName;
 285  
                 }
 286  0
                 else if ( "type".equals( lowerColumnName ) )
 287  
                 {
 288  0
                     fieldName = "issuetype";
 289  
                 }
 290  0
                 else if ( "priority".equals( lowerColumnName ) )
 291  
                 {
 292  0
                     fieldName = lowerColumnName;
 293  
                 }
 294  0
                 else if ( "version".equals( lowerColumnName ) )
 295  
                 {
 296  0
                     fieldName = "versions";
 297  
                 }
 298  0
                 else if ( "fix version".equals( lowerColumnName ) )
 299  
                 {
 300  0
                     fieldName = "fixVersions";
 301  
                 }
 302  0
                 else if ( "component".equals( lowerColumnName ) )
 303  
                 {
 304  0
                     fieldName = "components";
 305  
                 }
 306  0
                 else if ( "created".equals( lowerColumnName ) )
 307  
                 {
 308  0
                     fieldName = lowerColumnName;
 309  
                 }
 310  0
                 else if ( "updated".equals( lowerColumnName ) )
 311  
                 {
 312  0
                     fieldName = lowerColumnName;
 313  
                 }
 314  0
                 if ( fieldName != null )
 315  
                 {
 316  0
                     localFilter.append( "&sorter/field=" );
 317  0
                     localFilter.append( fieldName );
 318  0
                     localFilter.append( "&sorter/order=" );
 319  0
                     localFilter.append( descending ? "DESC" : "ASC" );
 320  0
                     validSortColumnNames++;
 321  
                 }
 322  
                 else
 323  
                 {
 324  
                     // Error in the configuration
 325  0
                     getLog().error(
 326  
                         "maven-changes-plugin: The configured value '" + lowerColumnName
 327  
                             + "' for sortColumnNames is not correct." );
 328  
                 }
 329  
             }
 330  
         }
 331  0
         if ( validSortColumnNames == 0 )
 332  
         {
 333  
             // Error in the configuration
 334  0
             getLog().error(
 335  
                 "maven-changes-plugin: None of the configured sortColumnNames '" + sortColumnNames + "' are correct." );
 336  
         }
 337  
 
 338  
 
 339  0
         return localFilter.toString();
 340  
     }
 341  
 
 342  
     /**
 343  
      * Execute the query on the JIRA server.
 344  
      *
 345  
      * @throws Exception on error
 346  
      */
 347  
     public void doExecute()
 348  
         throws Exception
 349  
     {
 350  
         try
 351  
         {
 352  0
             HttpClient client = new HttpClient();
 353  
 
 354  
             // MCHANGES-89 Allow circular redirects
 355  0
             HttpClientParams clientParams = client.getParams();
 356  0
             clientParams.setBooleanParameter( HttpClientParams.ALLOW_CIRCULAR_REDIRECTS, true );
 357  0
             clientParams.setCookiePolicy( CookiePolicy.BROWSER_COMPATIBILITY ); //MCHANGES-237
 358  
 
 359  0
             HttpState state = new HttpState();
 360  
 
 361  0
             HostConfiguration hc = new HostConfiguration();
 362  
 
 363  0
             client.setHostConfiguration( hc );
 364  
 
 365  0
             client.setState( state );
 366  
 
 367  0
             Map<String,String> urlMap = JiraHelper.getJiraUrlAndProjectId( project.getIssueManagement().getUrl() );
 368  
 
 369  0
             String jiraUrl = urlMap.get( "url" );
 370  0
             getLog().debug( "JIRA lives at: " + jiraUrl );
 371  
 
 372  0
             String jiraId = urlMap.get( "id" );
 373  
 
 374  0
             determineProxy( jiraUrl, client );
 375  
 
 376  0
             prepareBasicAuthentication( client );
 377  
 
 378  0
             boolean jiraAuthenticationSuccessful = false;
 379  0
             if ( isJiraAuthenticationConfigured() )
 380  
             {
 381  0
                 jiraAuthenticationSuccessful = doJiraAuthentication( client, jiraUrl );
 382  
             }
 383  
 
 384  0
             if ( ( isJiraAuthenticationConfigured() && jiraAuthenticationSuccessful )
 385  
                 || !isJiraAuthenticationConfigured() )
 386  
             {
 387  0
                 if ( jiraId == null || jiraId.length() == 0 )
 388  
                 {
 389  0
                     log.debug( "The JIRA URL " + project.getIssueManagement().getUrl()
 390  
                         + " doesn't include a pid, trying to extract it from JIRA." );
 391  0
                     jiraId = JiraHelper.getPidFromJira( log, project.getIssueManagement().getUrl(), client );
 392  
                 }
 393  
 
 394  0
                 if ( jiraId == null )
 395  
                 {
 396  0
                     getLog().error( "The issue management URL in the POM does not include a pid,"
 397  
                         + " and it was not possible to extract it from the page at that URL." );
 398  
                 }
 399  
                 else
 400  
                 {
 401  
                     // create the URL for getting the proper issues from JIRA
 402  0
                     String fullURL = jiraUrl + "/secure/IssueNavigator.jspa?view=rss&pid=" + jiraId;
 403  
 
 404  0
                     if ( getFixFor() != null )
 405  
                     {
 406  0
                         fullURL += "&fixfor=" + getFixFor();
 407  
                     }
 408  
 
 409  0
                     String createdFilter = createFilter();
 410  0
                     if ( createdFilter.charAt( 0 ) != '&' )
 411  
                     {
 412  0
                         fullURL += "&";
 413  
                     }
 414  0
                     fullURL += createdFilter;
 415  
 
 416  0
                     fullURL += ( "&tempMax=" + nbEntriesMax + "&reset=true&decorator=none" );
 417  
 
 418  0
                     if ( log.isDebugEnabled() )
 419  
                     {
 420  0
                         log.debug( "download jira issues from url " + fullURL );
 421  
                     }
 422  
 
 423  
                     // execute the GET
 424  0
                     download( client, fullURL );
 425  
                 }
 426  
             }
 427  
         }
 428  0
         catch ( Exception e )
 429  
         {
 430  0
             if ( project.getIssueManagement() != null )
 431  
             {
 432  0
                 getLog().error( "Error accessing " + project.getIssueManagement().getUrl(), e );
 433  
             }
 434  
             else
 435  
             {
 436  0
                 getLog().error( "Error accessing mock project issues", e );
 437  
             }
 438  0
         }
 439  0
     }
 440  
 
 441  
     /**
 442  
      * Override this method if you need to get issues for a specific Fix For.
 443  
      *
 444  
      * @return A Fix For id or <code>null</code> if you don't have that need
 445  
      */
 446  
     protected String getFixFor()
 447  
     {
 448  0
         return null;
 449  
     }
 450  
 
 451  
     /**
 452  
      * Check and prepare for basic authentication.
 453  
      *
 454  
      * @param client The client to prepare
 455  
      */
 456  
     private void prepareBasicAuthentication( HttpClient client )
 457  
     {
 458  0
         if ( ( webUser != null ) && ( webUser.length() > 0 ) )
 459  
         {
 460  0
             client.getParams().setAuthenticationPreemptive( true );
 461  
 
 462  0
             Credentials defaultcreds = new UsernamePasswordCredentials( webUser, webPassword );
 463  
 
 464  0
             getLog().debug( "Using username: " + webUser + " for Basic Authentication." );
 465  
 
 466  0
             client.getState().setCredentials( new AuthScope( null, AuthScope.ANY_PORT, null, AuthScope.ANY_SCHEME ),
 467  
                                               defaultcreds );
 468  
         }
 469  0
     }
 470  
 
 471  
     /**
 472  
      * Authenticate against JIRA. This method relies on jiraUser and
 473  
      * jiraPassword being set. You can check this by calling
 474  
      * isJiraAuthenticationConfigured().
 475  
      *
 476  
      * @param client    the HttpClient
 477  
      * @param jiraUrl   the JIRA installation
 478  
      * @return <code>true</code> if the authentication was successful, otherwise <code>false</code>
 479  
      */
 480  
     private boolean doJiraAuthentication( HttpClient client, final String jiraUrl )
 481  
     {
 482  
         // log into JIRA if we have to
 483  0
         String loginUrl = null;
 484  
 
 485  0
         StringBuffer loginLink = new StringBuffer( jiraUrl );
 486  
 
 487  0
         loginLink.append( "/login.jsp?os_destination=/secure/" );
 488  
 
 489  
         try
 490  
         {
 491  0
             loginLink.append( "&os_username=" ).append( URLEncoder.encode( jiraUser, UTF_8 ) );
 492  
 
 493  0
             String password = null;
 494  0
             if ( jiraPassword != null )
 495  
             {
 496  0
                 password = StringUtils.repeat( "*", jiraPassword.length() );
 497  
             }
 498  0
             getLog().debug( "Login URL: " + loginLink + "&os_password=" + password );
 499  
 
 500  0
             loginLink.append( "&os_password=" ).append( URLEncoder.encode( jiraPassword, UTF_8 ) );
 501  
 
 502  0
             loginUrl = loginLink.toString();
 503  
 
 504  
             // execute the login
 505  0
             GetMethod loginGet = new GetMethod( loginUrl );
 506  
 
 507  0
             client.executeMethod( loginGet );
 508  
 
 509  0
             if ( loginSucceeded( loginGet ) )
 510  
             {
 511  0
                 getLog().debug( "Successfully logged in into JIRA." );
 512  0
                 return true;
 513  
             }
 514  
             else
 515  
             {
 516  0
                 getLog().warn( "Was unable to login into JIRA: wrong username and/or password." );
 517  
             }
 518  
         }
 519  0
         catch ( Exception e )
 520  
         {
 521  0
             if ( getLog().isDebugEnabled() )
 522  
             {
 523  0
                 getLog().error( "Error trying to login into JIRA.", e );
 524  
             }
 525  
             else
 526  
             {
 527  0
                 getLog().error( "Error trying to login into JIRA. Cause is: " + e.getLocalizedMessage() );
 528  
             }
 529  0
         }
 530  0
         return false;
 531  
     }
 532  
 
 533  
     /**
 534  
      * Check to see if we think that JIRA authentication is needed.
 535  
      *
 536  
      * @return <code>true</code> if jiraUser and jiraPassword are set, otherwise <code>false</code>
 537  
      */
 538  
     private boolean isJiraAuthenticationConfigured()
 539  
     {
 540  0
         return ( jiraUser != null ) && ( jiraUser.length() > 0 ) && ( jiraPassword != null );
 541  
     }
 542  
 
 543  
     /**
 544  
      * Evaluate if the login attempt to JIRA was successful or not. We can't
 545  
      * use the status code because JIRA returns 200 even if the login fails.
 546  
      *
 547  
      * @param loginGet The method that was executed
 548  
      * @return <code>false</code> if we find an error message in the response body, otherwise <code>true</code>
 549  
      * @todo There must be a nicer way to know whether we were able to login or not
 550  
      */
 551  
     private boolean loginSucceeded( GetMethod loginGet )
 552  
         throws IOException
 553  
     {
 554  0
         final String loginFailureResponse = "your username and password are incorrect";
 555  
 
 556  0
         return loginGet.getResponseBodyAsString().indexOf( loginFailureResponse ) == -1;
 557  
     }
 558  
 
 559  
     /**
 560  
      * Setup proxy access if we have to.
 561  
      *
 562  
      * @param client  the HttpClient
 563  
      */
 564  
     private void determineProxy( String jiraUrl, HttpClient client )
 565  
     {
 566  
         // see whether there is any proxy defined in maven
 567  0
         Proxy proxy = null;
 568  
 
 569  0
         String proxyHost = null;
 570  
 
 571  0
         int proxyPort = 0;
 572  
 
 573  0
         String proxyUser = null;
 574  
 
 575  0
         String proxyPass = null;
 576  
 
 577  0
         if ( project == null )
 578  
         {
 579  0
             getLog().error( "No project set. No proxy info available." );
 580  
 
 581  0
             return;
 582  
         }
 583  
 
 584  0
         if ( settings != null )
 585  
         {
 586  0
             proxy = settings.getActiveProxy();
 587  
         }
 588  
 
 589  0
         if ( proxy != null )
 590  
         {
 591  
 
 592  0
             ProxyInfo proxyInfo = new ProxyInfo();
 593  0
             proxyInfo.setNonProxyHosts( proxy.getNonProxyHosts() );
 594  
 
 595  
             // Get the host out of the JIRA URL
 596  0
             URL url = null;
 597  
             try
 598  
             {
 599  0
                 url = new URL( jiraUrl );
 600  
             }
 601  0
             catch( MalformedURLException e )
 602  
             {
 603  0
                 getLog().error( "Invalid JIRA URL: " + jiraUrl + ". " + e.getMessage() );
 604  0
             }
 605  0
             String jiraHost = null;
 606  0
             if ( url != null )
 607  
             {
 608  0
                 jiraHost = url.getHost();
 609  
             }
 610  
 
 611  
             // Validation of proxy method copied from org.apache.maven.wagon.proxy.ProxyUtils.
 612  
             // @todo Can use original when maven-changes-plugin requires a more recent version of Maven
 613  
 
 614  
             //if ( ProxyUtils.validateNonProxyHosts( proxyInfo, jiraHost ) )
 615  0
             if ( JiraHelper.validateNonProxyHosts( proxyInfo, jiraHost ) )
 616  
             {
 617  0
                 return;
 618  
             }
 619  
 
 620  0
             proxyHost = settings.getActiveProxy().getHost();
 621  
 
 622  0
             proxyPort = settings.getActiveProxy().getPort();
 623  
 
 624  0
             proxyUser = settings.getActiveProxy().getUsername();
 625  
 
 626  0
             proxyPass = settings.getActiveProxy().getPassword();
 627  
 
 628  0
             getLog().debug( proxyPass );
 629  
         }
 630  
 
 631  0
         if ( proxyHost != null )
 632  
         {
 633  0
             client.getHostConfiguration().setProxy( proxyHost, proxyPort );
 634  
 
 635  0
             getLog().debug( "Using proxy: " + proxyHost + " at port " + proxyPort );
 636  
 
 637  0
             if ( proxyUser != null )
 638  
             {
 639  0
                 getLog().debug( "Using proxy user: " + proxyUser );
 640  
 
 641  0
                 client.getState().setProxyCredentials(
 642  
                                                        new AuthScope( null, AuthScope.ANY_PORT, null,
 643  
                                                                       AuthScope.ANY_SCHEME ),
 644  
                                                        new UsernamePasswordCredentials( proxyUser, proxyPass ) );
 645  
             }
 646  
         }
 647  0
     }
 648  
 
 649  
     /**
 650  
      * Downloads the given link using the configured HttpClient, possibly following redirects.
 651  
      *
 652  
      * @param cl     the HttpClient
 653  
      * @param link   the URL to JIRA
 654  
      */
 655  
     private void download( final HttpClient cl, final String link )
 656  
     {
 657  
         try
 658  
         {
 659  0
             GetMethod gm = new GetMethod( link );
 660  
 
 661  0
             getLog().info( "Downloading from JIRA at: " + link );
 662  
 
 663  0
             gm.setFollowRedirects( true );
 664  
 
 665  0
             cl.executeMethod( gm );
 666  
 
 667  0
             StatusLine sl = gm.getStatusLine();
 668  
 
 669  0
             if ( sl == null )
 670  
             {
 671  0
                 getLog().error( "Unknown error validating link: " + link );
 672  
 
 673  0
                 return;
 674  
             }
 675  
 
 676  
             // if we get a redirect, do so
 677  0
             if ( gm.getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY )
 678  
             {
 679  0
                 Header locationHeader = gm.getResponseHeader( "Location" );
 680  
 
 681  0
                 if ( locationHeader == null )
 682  
                 {
 683  0
                     getLog().warn( "Site sent redirect, but did not set Location header" );
 684  
                 }
 685  
                 else
 686  
                 {
 687  0
                     String newLink = locationHeader.getValue();
 688  
 
 689  0
                     getLog().debug( "Following redirect to " + newLink );
 690  
 
 691  0
                     download( cl, newLink );
 692  
                 }
 693  
             }
 694  
 
 695  0
             if ( gm.getStatusCode() == HttpStatus.SC_OK )
 696  
             {
 697  0
                 final InputStream responseBodyStream = gm.getResponseBodyAsStream();
 698  
 
 699  0
                 if ( !output.getParentFile().exists() )
 700  
                 {
 701  0
                     output.getParentFile().mkdirs();
 702  
                 }
 703  
 
 704  
                 // write the response to file
 705  0
                 OutputStream out = null;
 706  
                 try
 707  
                 {
 708  0
                     out = new FileOutputStream( output );
 709  0
                     IOUtil.copy( responseBodyStream, out );
 710  
                 }
 711  
                 finally
 712  
                 {
 713  0
                     IOUtil.close( out );
 714  0
                     IOUtil.close( responseBodyStream );
 715  0
                 }
 716  
 
 717  0
                 getLog().debug( "Downloading from JIRA was successful" );
 718  0
             }
 719  
             else
 720  
             {
 721  0
                 getLog().warn( "Downloading from JIRA failed. Received: [" + gm.getStatusCode() + "]" );
 722  
             }
 723  
         }
 724  0
         catch ( HttpException e )
 725  
         {
 726  0
             if ( getLog().isDebugEnabled() )
 727  
             {
 728  0
                 getLog().error( "Error downloading issues from JIRA:", e );
 729  
             }
 730  
             else
 731  
             {
 732  0
                 getLog().error( "Error downloading issues from JIRA url: " + e.getLocalizedMessage() );
 733  
 
 734  
             }
 735  
         }
 736  0
         catch ( IOException e )
 737  
         {
 738  0
             if ( getLog().isDebugEnabled() )
 739  
             {
 740  0
                 getLog().error( "Error downloading issues from JIRA:", e );
 741  
             }
 742  
             else
 743  
             {
 744  0
                 getLog().error( "Error downloading issues from JIRA. Cause is " + e.getLocalizedMessage() );
 745  
             }
 746  0
         }
 747  0
     }
 748  
 
 749  
     public List<Issue> getIssueList()
 750  
         throws MojoExecutionException
 751  
     {
 752  0
         if ( output.isFile() )
 753  
         {
 754  0
             JiraXML jira = new JiraXML( log, jiraDatePattern );
 755  0
             jira.parseXML( output );
 756  0
             getLog().info( "The JIRA version is '" + jira.getJiraVersion() + "'" );
 757  0
             return jira.getIssueList();
 758  
         }
 759  
         else
 760  
         {
 761  0
             getLog().warn( "JIRA file " + output.getPath() + " doesn't exist." );
 762  0
             return Collections.emptyList();
 763  
         }
 764  
     }
 765  
 
 766  
     public void setJiraDatePattern( String jiraDatePattern )
 767  
     {
 768  1
         this.jiraDatePattern = jiraDatePattern;
 769  1
     }
 770  
 
 771  
     /**
 772  
      * Set the output file for the log.
 773  
      *
 774  
      * @param thisOutput the output file
 775  
      */
 776  
     public void setOutput( File thisOutput )
 777  
     {
 778  1
         this.output = thisOutput;
 779  1
     }
 780  
 
 781  
     public File getOutput()
 782  
     {
 783  0
         return this.output;
 784  
     }
 785  
 
 786  
     /**
 787  
      * Sets the project.
 788  
      *
 789  
      * @param thisProject  The project to set
 790  
      */
 791  
     public void setMavenProject( Object thisProject )
 792  
     {
 793  1
         this.project = (MavenProject) thisProject;
 794  1
     }
 795  
 
 796  
     /**
 797  
      * Sets the maximum number of Issues to show.
 798  
      *
 799  
      * @param nbEntries  The maximum number of Issues
 800  
      */
 801  
     public void setNbEntries( final int nbEntries )
 802  
     {
 803  1
         nbEntriesMax = nbEntries;
 804  1
     }
 805  
 
 806  
     /**
 807  
      * Sets the statusIds.
 808  
      *
 809  
      * @param thisStatusIds   The id(s) of the status to show, as comma separated string
 810  
      */
 811  
     public void setStatusIds( String thisStatusIds )
 812  
     {
 813  1
         statusIds = thisStatusIds;
 814  1
     }
 815  
 
 816  
     /**
 817  
      * Sets the priorityIds.
 818  
      *
 819  
      * @param thisPriorityIds  The id(s) of the priority to show, as comma separated string
 820  
      */
 821  
     public void setPriorityIds( String thisPriorityIds )
 822  
     {
 823  1
         priorityIds = thisPriorityIds;
 824  1
     }
 825  
 
 826  
     /**
 827  
      * Sets the resolutionIds.
 828  
      *
 829  
      * @param thisResolutionIds  The id(s) of the resolution to show, as comma separated string
 830  
      */
 831  
     public void setResolutionIds( String thisResolutionIds )
 832  
     {
 833  1
         resolutionIds = thisResolutionIds;
 834  1
     }
 835  
 
 836  
     /**
 837  
      * Sets the sort column names.
 838  
      *
 839  
      * @param thisSortColumnNames The column names to sort by
 840  
      */
 841  
     public void setSortColumnNames( String thisSortColumnNames )
 842  
     {
 843  1
         sortColumnNames = thisSortColumnNames;
 844  1
     }
 845  
 
 846  
     /**
 847  
      * Sets the password for authentication against the webserver.
 848  
      *
 849  
      * @param thisWebPassword  The password of the webserver
 850  
      */
 851  
     public void setWebPassword( String thisWebPassword )
 852  
     {
 853  1
         this.webPassword = thisWebPassword;
 854  1
     }
 855  
 
 856  
     /**
 857  
      * Sets the username for authentication against the webserver.
 858  
      *
 859  
      * @param thisWebUser   The username of the webserver
 860  
      */
 861  
     public void setWebUser( String thisWebUser )
 862  
     {
 863  1
         this.webUser = thisWebUser;
 864  1
     }
 865  
 
 866  
     /**
 867  
      * Sets the password to log into a secured JIRA.
 868  
      *
 869  
      * @param thisJiraPassword  The password for JIRA
 870  
      */
 871  
     public void setJiraPassword( final String thisJiraPassword )
 872  
     {
 873  1
         this.jiraPassword = thisJiraPassword;
 874  1
     }
 875  
 
 876  
     /**
 877  
      * Sets the username to log into a secured JIRA.
 878  
      *
 879  
      * @param thisJiraUser  The username for JIRA
 880  
      */
 881  
     public void setJiraUser( String thisJiraUser )
 882  
     {
 883  1
         this.jiraUser = thisJiraUser;
 884  1
     }
 885  
 
 886  
     /**
 887  
      * Sets the filter to apply to query to JIRA.
 888  
      *
 889  
      * @param thisFilter  The filter to query JIRA
 890  
      */
 891  
     public void setFilter( String thisFilter )
 892  
     {
 893  1
         this.filter = thisFilter;
 894  1
     }
 895  
 
 896  
     /**
 897  
      * Sets the component(s) to apply to query JIRA.
 898  
      *
 899  
      * @param theseComponents   The id(s) of components to show, as comma separated string
 900  
      */
 901  
     public void setComponent( String theseComponents )
 902  
     {
 903  1
         this.component = theseComponents;
 904  1
     }
 905  
 
 906  
     /**
 907  
      * Sets the fix version id(s) to apply to query JIRA.
 908  
      *
 909  
      * @param theseFixVersionIds The id(s) of fix versions to show, as comma separated string
 910  
      */
 911  
     public void setFixVersionIds( String theseFixVersionIds )
 912  
     {
 913  1
         this.fixVersionIds = theseFixVersionIds;
 914  1
     }
 915  
 
 916  
     /**
 917  
      * Sets the typeIds.
 918  
      *
 919  
      * @param theseTypeIds  The id(s) of the types to show, as comma separated string
 920  
      */
 921  
     public void setTypeIds( String theseTypeIds )
 922  
     {
 923  1
         typeIds = theseTypeIds;
 924  1
     }
 925  
 
 926  
     public void setLog( Log log )
 927  
     {
 928  1
         this.log = log;
 929  1
     }
 930  
 
 931  
     private Log getLog()
 932  
     {
 933  0
         return log;
 934  
     }
 935  
 
 936  
     public void setSettings( Settings settings )
 937  
     {
 938  1
         this.settings = settings;
 939  1
     }
 940  
 }