View Javadoc

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