4747import hudson .util .ListBoxModel ;
4848import hudson .util .Secret ;
4949import jakarta .servlet .ServletException ;
50+
5051import java .io .File ;
5152import java .io .IOException ;
5253import java .io .PrintStream ;
7778import java .util .logging .Logger ;
7879import java .util .regex .Pattern ;
7980import javax .annotation .PreDestroy ;
81+
8082import jenkins .model .Jenkins ;
8183import org .kohsuke .stapler .AncestorInPath ;
8284import org .kohsuke .stapler .DataBoundConstructor ;
9294 * needed to access this Jira.
9395 * </p>
9496 * <b>When adding new fields do not miss to look at readResolve method!!</b>
97+ *
9598 * @author Kohsuke Kawaguchi
9699 */
97100public class JiraSite extends AbstractDescribableImpl <JiraSite > {
@@ -117,7 +120,7 @@ public class JiraSite extends AbstractDescribableImpl<JiraSite> {
117120
118121 public static final int DEFAULT_THREAD_EXECUTOR_NUMBER = 10 ;
119122
120- public static final int DEFAULT_MAX_ISSUES = 100 ;
123+ public static final int MAX_ALLOWED_ISSUES_FROM_JQL = 5000 ;
121124
122125 /**
123126 * URL of Jira for Jenkins access, like {@code http://jira.codehaus.org/}.
@@ -152,13 +155,15 @@ public class JiraSite extends AbstractDescribableImpl<JiraSite> {
152155
153156 /**
154157 * User name needed to login. Optional.
158+ *
155159 * @deprecated use credentialsId
156160 */
157161 @ Deprecated
158162 private transient String userName ;
159163
160164 /**
161165 * Password needed to login. Optional.
166+ *
162167 * @deprecated use credentialsId
163168 */
164169 @ Deprecated
@@ -223,12 +228,14 @@ public class JiraSite extends AbstractDescribableImpl<JiraSite> {
223228
224229 /**
225230 * response timeout for jira rest call
231+ *
226232 * @since 3.0.3
227233 */
228234 private int readTimeout = DEFAULT_READ_TIMEOUT ;
229235
230236 /**
231237 * thread pool number
238+ *
232239 * @since 3.0.3
233240 */
234241 private int threadExecutorNumber = DEFAULT_THREAD_EXECUTOR_NUMBER ;
@@ -240,14 +247,13 @@ public class JiraSite extends AbstractDescribableImpl<JiraSite> {
240247
241248 /**
242249 * To add scm entry change date and time in jira comments.
243- *
244250 */
245251 private boolean appendChangeTimestamp ;
246252
247253 /**
248254 * To allow configurable value of max issues from jql search via jira site global configuration.
249255 */
250- private int maxIssuesFromJqlSearch = DEFAULT_MAX_ISSUES ;
256+ private int maxIssuesFromJqlSearch ;
251257
252258 private int ioThreadCount = Integer .getInteger (JiraSite .class .getName () + ".httpclient.options.ioThreadCount" , 2 );
253259
@@ -282,8 +288,7 @@ public JiraSite(
282288 boolean updateJiraIssueForAllStatus ,
283289 @ CheckForNull String groupVisibility ,
284290 @ CheckForNull String roleVisibility ,
285- boolean useHTTPAuth ,
286- int maxIssuesFromJqlSearch ) {
291+ boolean useHTTPAuth ) {
287292 this (
288293 url ,
289294 alternativeUrl ,
@@ -297,8 +302,7 @@ public JiraSite(
297302 useHTTPAuth ,
298303 DEFAULT_TIMEOUT ,
299304 DEFAULT_READ_TIMEOUT ,
300- DEFAULT_THREAD_EXECUTOR_NUMBER ,
301- DEFAULT_MAX_ISSUES );
305+ DEFAULT_THREAD_EXECUTOR_NUMBER );
302306 }
303307
304308 // Deprecate the previous constructor but leave it in place for Java-level compatibility.
@@ -356,8 +360,7 @@ public JiraSite(
356360 useHTTPAuth ,
357361 DEFAULT_TIMEOUT ,
358362 DEFAULT_READ_TIMEOUT ,
359- DEFAULT_THREAD_EXECUTOR_NUMBER ,
360- DEFAULT_MAX_ISSUES );
363+ DEFAULT_THREAD_EXECUTOR_NUMBER );
361364 if (credentials != null ) {
362365 // we verify the credential really exists otherwise we migrate it
363366 StandardUsernamePasswordCredentials standardUsernamePasswordCredentials =
@@ -385,8 +388,7 @@ public JiraSite(
385388 boolean useHTTPAuth ,
386389 int timeout ,
387390 int readTimeout ,
388- int threadExecutorNumber ,
389- int maxIssuesFromJqlSearch ) {
391+ int threadExecutorNumber ) {
390392 if (url != null ) {
391393 url = toURL (url .toExternalForm ());
392394 }
@@ -409,7 +411,6 @@ public JiraSite(
409411 setRoleVisibility (roleVisibility );
410412 this .useHTTPAuth = useHTTPAuth ;
411413 this .jiraSession = null ;
412- this .maxIssuesFromJqlSearch = maxIssuesFromJqlSearch ;
413414 }
414415
415416 @ DataBoundConstructor
@@ -436,8 +437,7 @@ public JiraSite(
436437 boolean useHTTPAuth ,
437438 int timeout ,
438439 int readTimeout ,
439- int threadExecutorNumber ,
440- int maxIssuesFromJqlSearch ) {
440+ int threadExecutorNumber ) {
441441 this (
442442 url ,
443443 alternativeUrl ,
@@ -451,8 +451,7 @@ public JiraSite(
451451 useHTTPAuth ,
452452 timeout ,
453453 readTimeout ,
454- threadExecutorNumber ,
455- maxIssuesFromJqlSearch );
454+ threadExecutorNumber );
456455 }
457456
458457 // Deprecate the previous constructor but leave it in place for Java-level compatibility.
@@ -471,8 +470,7 @@ public JiraSite(
471470 int timeout ,
472471 int readTimeout ,
473472 int threadExecutorNumber ,
474- boolean useBearerAuth ,
475- int maxIssuesFromJqlSearch ) {
473+ boolean useBearerAuth ) {
476474 this (
477475 url ,
478476 alternativeUrl ,
@@ -486,8 +484,7 @@ public JiraSite(
486484 useHTTPAuth ,
487485 timeout ,
488486 readTimeout ,
489- threadExecutorNumber ,
490- maxIssuesFromJqlSearch );
487+ threadExecutorNumber );
491488 this .useBearerAuth = useBearerAuth ;
492489 }
493490
@@ -518,6 +515,7 @@ public boolean getDisableChangelogAnnotations() {
518515 /**
519516 * Sets connect timeout (in seconds).
520517 * If not specified, a default timeout will be used.
518+ *
521519 * @param timeoutSec Timeout in seconds
522520 */
523521 @ DataBoundSetter
@@ -532,6 +530,7 @@ public int getTimeout() {
532530 /**
533531 * Sets read timeout (in seconds).
534532 * If not specified, a default timeout will be used.
533+ *
535534 * @param readTimeout Timeout in seconds
536535 */
537536 @ DataBoundSetter
@@ -702,14 +701,13 @@ protected Object readResolve() throws FormException {
702701 useHTTPAuth ,
703702 timeout ,
704703 readTimeout ,
705- threadExecutorNumber ,
706- maxIssuesFromJqlSearch );
704+ threadExecutorNumber );
707705 }
708706 jiraSite .setAppendChangeTimestamp (appendChangeTimestamp );
709707 jiraSite .setDisableChangelogAnnotations (disableChangelogAnnotations );
710708 jiraSite .setDateTimePattern (dateTimePattern );
711709 jiraSite .setUseBearerAuth (useBearerAuth );
712-
710+ jiraSite . setMaxIssuesFromJqlSearch ( maxIssuesFromJqlSearch );
713711 return jiraSite ;
714712 }
715713
@@ -786,7 +784,8 @@ Lock getProjectUpdateLock() {
786784 /**
787785 * This method only supports credential matching by credentialsId.
788786 * Older methods are not and will not be supported as the credentials should have been migrated already.
789- * @param item can be <code>null</code> if top level
787+ *
788+ * @param item can be <code>null</code> if top level
790789 * @param uiValidation if <code>true</code> and credentials not found at item level will not go up
791790 */
792791 private StandardUsernamePasswordCredentials resolveCredentials (Item item , boolean uiValidation ) {
@@ -917,10 +916,12 @@ public Object getThreadLocalContext() {
917916 }
918917
919918 @ Override
920- public void setThreadLocalContext (Object context ) {}
919+ public void setThreadLocalContext (Object context ) {
920+ }
921921
922922 @ Override
923- public void clearThreadLocalContext () {}
923+ public void clearThreadLocalContext () {
924+ }
924925 });
925926
926927 final HttpClient httpClient = defaultHttpClientFactory .create (options );
@@ -948,16 +949,20 @@ public void destroy() throws Exception {
948949
949950 private static class NoOpEventPublisher implements EventPublisher {
950951 @ Override
951- public void publish (Object o ) {}
952+ public void publish (Object o ) {
953+ }
952954
953955 @ Override
954- public void register (Object o ) {}
956+ public void register (Object o ) {
957+ }
955958
956959 @ Override
957- public void unregister (Object o ) {}
960+ public void unregister (Object o ) {
961+ }
958962
959963 @ Override
960- public void unregisterAll () {}
964+ public void unregisterAll () {
965+ }
961966 }
962967
963968 @ SuppressWarnings ("deprecation" )
@@ -1158,9 +1163,10 @@ public boolean existsIssue(String id) {
11581163
11591164 /**
11601165 * Returns all versions for the given project key.
1161- * @deprecated use {@link JiraSession#getVersions(String)}
1166+ *
11621167 * @param projectKey Project Key
11631168 * @return A set of JiraVersions
1169+ * @deprecated use {@link JiraSession#getVersions(String)}
11641170 */
11651171 @ Deprecated
11661172 public Set <ExtendedVersion > getVersions (String projectKey ) {
@@ -1174,7 +1180,7 @@ public Set<ExtendedVersion> getVersions(String projectKey) {
11741180 /**
11751181 * Generates release notes for a given version.
11761182 *
1177- * @param projectKey the project key
1183+ * @param projectKey the project key
11781184 * @param versionName the version
11791185 * @param filter Additional JQL Filter. Example: status in (Resolved,Closed)
11801186 * @return release notes
@@ -1260,9 +1266,9 @@ public void migrateIssuesToFixVersion(String projectKey, String versionName, Str
12601266 /**
12611267 * Adds new fix version to issues matching the jql.
12621268 *
1263- * @param projectKey the project key
1269+ * @param projectKey the project key
12641270 * @param versionName the version
1265- * @param query the query
1271+ * @param query the query
12661272 * @throws TimeoutException if too long
12671273 */
12681274 public void addFixVersionToIssue (String projectKey , String versionName , String query ) throws TimeoutException {
@@ -1277,10 +1283,10 @@ public void addFixVersionToIssue(String projectKey, String versionName, String q
12771283 * Progresses all issues matching the JQL search, using the given workflow action. Optionally
12781284 * adds a comment to the issue(s) at the same time.
12791285 *
1280- * @param jqlSearch the query
1286+ * @param jqlSearch the query
12811287 * @param workflowActionName the workflowActionName
1282- * @param comment the comment
1283- * @param console the console
1288+ * @param comment the comment
1289+ * @param console the console
12841290 * @throws TimeoutException TimeoutException if too long
12851291 */
12861292 public boolean progressMatchingIssues (
@@ -1406,6 +1412,11 @@ public FormValidation doValidate(
14061412 return FormValidation .error (String .format ("Malformed alternative URL (%s)" , alternativeUrl ), e );
14071413 }
14081414
1415+ if (maxIssuesFromJqlSearch > 5000 ) {
1416+ return FormValidation .error (String .format ("Maximum number of allowed issues from jql search are %s" ,
1417+ MAX_ALLOWED_ISSUES_FROM_JQL ));
1418+ }
1419+
14091420 credentialsId = Util .fixEmpty (credentialsId );
14101421 JiraSite site = getBuilder ()
14111422 .withMainURL (mainURL )
@@ -1463,6 +1474,16 @@ public FormValidation doCheckCredentialsId(
14631474 return CredentialsHelper .doCheckFillCredentialsId (item , value , url );
14641475 }
14651476
1477+ @ SuppressWarnings ("unused" ) // used by stapler
1478+ public FormValidation doCheckMaxIssuesFromJqlSearch (@ QueryParameter int maxIssuesFromJqlSearch ) {
1479+ if (maxIssuesFromJqlSearch > MAX_ALLOWED_ISSUES_FROM_JQL ) {
1480+ return FormValidation .error (String .format ("Maximum number of allowed issues from jql search are %s" ,
1481+ MAX_ALLOWED_ISSUES_FROM_JQL ));
1482+ } else {
1483+ return FormValidation .ok ();
1484+ }
1485+ }
1486+
14661487 Builder getBuilder () {
14671488 return new Builder ();
14681489 }
@@ -1479,7 +1500,6 @@ static class Builder {
14791500 private String groupVisibility ;
14801501 private String roleVisibility ;
14811502 private boolean useHTTPAuth ;
1482- private int maxIssuesFromJqlSearch ;
14831503
14841504 public Builder withMainURL (URL mainURL ) {
14851505 this .mainURL = mainURL ;
@@ -1542,16 +1562,14 @@ public JiraSite build() {
15421562 updateJiraIssueForAllStatus ,
15431563 groupVisibility ,
15441564 roleVisibility ,
1545- useHTTPAuth ,
1546- maxIssuesFromJqlSearch );
1565+ useHTTPAuth );
15471566 }
15481567 }
15491568
15501569 // helper methods
15511570 // yes this class hierarchy can be a real big mess...
15521571
15531572 /**
1554- *
15551573 * @param item the Jenkins {@link Item} can be a {@link Job} or {@link Folder}
15561574 * @return the parent as {@link ItemGroup} which can be {@link Jenkins} or {@link Folder}
15571575 */
@@ -1597,6 +1615,7 @@ public static List<JiraSite> getSitesFromFolders(ItemGroup itemGroup) {
15971615 /**
15981616 * Gets the effective {@link JiraSite} associated with the given project
15991617 * and creates automatically jiraSession for each jiraSite found
1618+ *
16001619 * @return <code>null</code> if no such was found.
16011620 */
16021621 @ Nullable
0 commit comments