1 | package org.apache.maven.continuum.web.action; |
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 com.opensymphony.xwork2.Preparable; |
23 | |
24 | import java.util.ArrayList; |
25 | import java.util.Collection; |
26 | import java.util.Collections; |
27 | import java.util.List; |
28 | |
29 | import org.apache.commons.lang.StringEscapeUtils; |
30 | import org.apache.commons.lang.StringUtils; |
31 | import org.apache.maven.continuum.ContinuumException; |
32 | import org.apache.maven.continuum.model.project.BuildQueue; |
33 | import org.apache.maven.continuum.model.project.Schedule; |
34 | import org.apache.maven.continuum.web.exception.AuthenticationRequiredException; |
35 | import org.apache.maven.continuum.web.exception.AuthorizationRequiredException; |
36 | import org.apache.continuum.web.util.AuditLog; |
37 | import org.apache.continuum.web.util.AuditLogConstants; |
38 | import org.slf4j.Logger; |
39 | import org.slf4j.LoggerFactory; |
40 | |
41 | /** |
42 | * @author Nik Gonzalez |
43 | * @version $Id: ScheduleAction.java 1101669 2011-05-10 22:46:21Z ctan $ |
44 | * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="schedule" |
45 | */ |
46 | public class ScheduleAction |
47 | extends ContinuumConfirmAction |
48 | implements Preparable |
49 | { |
50 | private static final Logger logger = LoggerFactory.getLogger( ScheduleAction.class ); |
51 | |
52 | private int id; |
53 | |
54 | private boolean active = false; |
55 | |
56 | private int delay; |
57 | |
58 | private String description; |
59 | |
60 | private String name; |
61 | |
62 | private Collection schedules; |
63 | |
64 | private Schedule schedule; |
65 | |
66 | private boolean confirmed; |
67 | |
68 | private int maxJobExecutionTime; |
69 | |
70 | private String second = "0"; |
71 | |
72 | private String minute = "0"; |
73 | |
74 | private String hour = "*"; |
75 | |
76 | private String dayOfMonth = "*"; |
77 | |
78 | private String month = "*"; |
79 | |
80 | private String dayOfWeek = "?"; |
81 | |
82 | private String year; |
83 | |
84 | private List<BuildQueue> availableBuildQueues; |
85 | |
86 | private List<BuildQueue> selectedBuildQueues = new ArrayList<BuildQueue>(); |
87 | |
88 | private List<String> selectedBuildQueuesIds = new ArrayList<String>(); |
89 | |
90 | public void prepare() |
91 | throws Exception |
92 | { |
93 | super.prepare(); |
94 | |
95 | populateBuildQueues(); |
96 | } |
97 | |
98 | private void populateBuildQueues() |
99 | throws ContinuumException |
100 | { |
101 | if ( schedule != null ) |
102 | { |
103 | selectedBuildQueues = schedule.getBuildQueues(); |
104 | for ( BuildQueue bq : selectedBuildQueues ) |
105 | { |
106 | this.selectedBuildQueuesIds.add( Integer.toString( bq.getId() ) ); |
107 | } |
108 | } |
109 | |
110 | availableBuildQueues = getContinuum().getAllBuildQueues(); |
111 | |
112 | // remove selected build queues from available build queues |
113 | for ( BuildQueue buildQueue : selectedBuildQueues ) |
114 | { |
115 | if ( availableBuildQueues.contains( buildQueue ) ) |
116 | { |
117 | availableBuildQueues.remove( buildQueue ); |
118 | } |
119 | } |
120 | } |
121 | |
122 | public String summary() |
123 | throws ContinuumException |
124 | { |
125 | try |
126 | { |
127 | checkManageSchedulesAuthorization(); |
128 | } |
129 | catch ( AuthorizationRequiredException authzE ) |
130 | { |
131 | addActionError( authzE.getMessage() ); |
132 | return REQUIRES_AUTHORIZATION; |
133 | } |
134 | catch ( AuthenticationRequiredException e ) |
135 | { |
136 | addActionError( e.getMessage() ); |
137 | return REQUIRES_AUTHENTICATION; |
138 | |
139 | } |
140 | |
141 | schedules = getContinuum().getSchedules(); |
142 | |
143 | return SUCCESS; |
144 | } |
145 | |
146 | public String input() |
147 | throws ContinuumException |
148 | { |
149 | |
150 | try |
151 | { |
152 | checkManageSchedulesAuthorization(); |
153 | } |
154 | catch ( AuthorizationRequiredException authzE ) |
155 | { |
156 | addActionError( authzE.getMessage() ); |
157 | return REQUIRES_AUTHORIZATION; |
158 | } |
159 | catch ( AuthenticationRequiredException e ) |
160 | { |
161 | addActionError( e.getMessage() ); |
162 | return REQUIRES_AUTHENTICATION; |
163 | } |
164 | |
165 | if ( id != 0 ) |
166 | { |
167 | schedule = getContinuum().getSchedule( id ); |
168 | active = schedule.isActive(); |
169 | |
170 | String[] cronEx = schedule.getCronExpression().split( " " ); |
171 | second = cronEx[0]; |
172 | minute = cronEx[1]; |
173 | hour = cronEx[2]; |
174 | dayOfMonth = cronEx[3]; |
175 | month = cronEx[4]; |
176 | dayOfWeek = cronEx[5]; |
177 | if ( cronEx.length > 6 ) |
178 | { |
179 | year = cronEx[6]; |
180 | } |
181 | |
182 | description = schedule.getDescription(); |
183 | name = schedule.getName(); |
184 | delay = schedule.getDelay(); |
185 | maxJobExecutionTime = schedule.getMaxJobExecutionTime(); |
186 | |
187 | populateBuildQueues(); |
188 | } |
189 | else |
190 | { |
191 | // all new schedules should be active |
192 | active = true; |
193 | } |
194 | |
195 | return SUCCESS; |
196 | } |
197 | |
198 | public String save() |
199 | throws ContinuumException |
200 | { |
201 | |
202 | try |
203 | { |
204 | checkManageSchedulesAuthorization(); |
205 | } |
206 | catch ( AuthorizationRequiredException authzE ) |
207 | { |
208 | addActionError( authzE.getMessage() ); |
209 | return REQUIRES_AUTHORIZATION; |
210 | } |
211 | catch ( AuthenticationRequiredException e ) |
212 | { |
213 | addActionError( e.getMessage() ); |
214 | return REQUIRES_AUTHENTICATION; |
215 | } |
216 | |
217 | if ( StringUtils.isBlank( name ) ) |
218 | { |
219 | logger.error( "Can't create schedule. No schedule name was supplied." ); |
220 | addActionError( getText( "buildDefinition.noname.save.error.message" ) ); |
221 | } |
222 | if ( !getContinuum().getConfiguration().isDistributedBuildEnabled() |
223 | && ( selectedBuildQueuesIds == null || selectedBuildQueuesIds.isEmpty() ) ) |
224 | { |
225 | addActionError( getText( "schedule.buildqueues.empty.error" ) ); |
226 | } |
227 | if ( hasErrors() ) |
228 | { |
229 | return ERROR; |
230 | } |
231 | |
232 | try |
233 | { |
234 | Schedule s = getContinuum().getScheduleByName( name ); |
235 | if ( s != null && id != s.getId() ) |
236 | { |
237 | addActionError( getText( "schedule.name.already.exists" ) ); |
238 | return ERROR; |
239 | } |
240 | } |
241 | catch ( ContinuumException e ) |
242 | { |
243 | logger.debug( "Unexpected error getting schedule" ); |
244 | } |
245 | |
246 | AuditLog event = new AuditLog( getName(), AuditLogConstants.ADD_SCHEDULE ); |
247 | event.setCategory( AuditLogConstants.SCHEDULE ); |
248 | event.setCurrentUser( getPrincipal() ); |
249 | |
250 | if ( id == 0 ) |
251 | { |
252 | try |
253 | { |
254 | getContinuum().addSchedule( setFields( new Schedule() ) ); |
255 | event.log(); |
256 | } |
257 | catch ( ContinuumException e ) |
258 | { |
259 | addActionError( getText( "schedule.buildqueues.add.error" ) ); |
260 | return ERROR; |
261 | } |
262 | return SUCCESS; |
263 | } |
264 | else |
265 | { |
266 | try |
267 | { |
268 | getContinuum().updateSchedule( setFields( getContinuum().getSchedule( id ) ) ); |
269 | event.setAction( AuditLogConstants.MODIFY_SCHEDULE ); |
270 | event.log(); |
271 | } |
272 | catch ( ContinuumException e ) |
273 | { |
274 | addActionError( getText( "schedule.buildqueues.add.error" ) ); |
275 | return ERROR; |
276 | } |
277 | return SUCCESS; |
278 | } |
279 | } |
280 | |
281 | private Schedule setFields( Schedule schedule ) |
282 | throws ContinuumException |
283 | { |
284 | schedule.setActive( active ); |
285 | schedule.setCronExpression( getCronExpression() ); |
286 | schedule.setDelay( delay ); |
287 | schedule.setDescription( StringEscapeUtils.escapeXml( StringEscapeUtils.unescapeXml( description ) ) ); |
288 | schedule.setName( name ); |
289 | schedule.setMaxJobExecutionTime(maxJobExecutionTime); |
290 | if (!getContinuum().getConfiguration().isDistributedBuildEnabled()) { |
291 | // if distributed build don't update schedules |
292 | schedule.setBuildQueues(null); |
293 | for (String id : selectedBuildQueuesIds) { |
294 | BuildQueue buildQueue = getContinuum().getBuildQueue(Integer.parseInt(id)); |
295 | schedule.addBuildQueue(buildQueue); |
296 | } |
297 | } |
298 | |
299 | return schedule; |
300 | } |
301 | |
302 | public String confirm() |
303 | throws ContinuumException |
304 | { |
305 | try |
306 | { |
307 | checkManageSchedulesAuthorization(); |
308 | } |
309 | catch ( AuthorizationRequiredException authzE ) |
310 | { |
311 | addActionError( authzE.getMessage() ); |
312 | return REQUIRES_AUTHORIZATION; |
313 | } |
314 | catch ( AuthenticationRequiredException e ) |
315 | { |
316 | addActionError( e.getMessage() ); |
317 | return REQUIRES_AUTHENTICATION; |
318 | } |
319 | |
320 | schedule = getContinuum().getSchedule( id ); |
321 | |
322 | return SUCCESS; |
323 | } |
324 | |
325 | public String remove() |
326 | throws ContinuumException |
327 | { |
328 | try |
329 | { |
330 | checkManageSchedulesAuthorization(); |
331 | } |
332 | catch ( AuthorizationRequiredException authzE ) |
333 | { |
334 | addActionError( authzE.getMessage() ); |
335 | return REQUIRES_AUTHORIZATION; |
336 | } |
337 | catch ( AuthenticationRequiredException e ) |
338 | { |
339 | addActionError( e.getMessage() ); |
340 | return REQUIRES_AUTHENTICATION; |
341 | } |
342 | |
343 | if ( confirmed ) |
344 | { |
345 | try |
346 | { |
347 | getContinuum().removeSchedule( id ); |
348 | } |
349 | catch ( ContinuumException e ) |
350 | { |
351 | addActionError( getText( "schedule.remove.error" ) ); |
352 | return ERROR; |
353 | } |
354 | } |
355 | else |
356 | { |
357 | setConfirmationInfo( "Schedule Removal", "removeSchedule", name, "id", "" + id ); |
358 | |
359 | name = getContinuum().getSchedule( id ).getName(); |
360 | |
361 | return CONFIRM; |
362 | } |
363 | |
364 | AuditLog event = new AuditLog( name, AuditLogConstants.REMOVE_SCHEDULE ); |
365 | event.setCategory( AuditLogConstants.SCHEDULE ); |
366 | event.setCurrentUser( getPrincipal() ); |
367 | event.log(); |
368 | |
369 | return SUCCESS; |
370 | } |
371 | |
372 | public Collection getSchedules() |
373 | { |
374 | return schedules; |
375 | } |
376 | |
377 | public int getId() |
378 | { |
379 | return id; |
380 | } |
381 | |
382 | public void setId( int id ) |
383 | { |
384 | this.id = id; |
385 | } |
386 | |
387 | public boolean isActive() |
388 | { |
389 | return active; |
390 | } |
391 | |
392 | public void setActive( boolean active ) |
393 | { |
394 | this.active = active; |
395 | } |
396 | |
397 | public int getDelay() |
398 | { |
399 | return delay; |
400 | } |
401 | |
402 | public void setDelay( int delay ) |
403 | { |
404 | this.delay = delay; |
405 | } |
406 | |
407 | public String getDescription() |
408 | { |
409 | return description; |
410 | } |
411 | |
412 | public void setDescription( String description ) |
413 | { |
414 | this.description = description; |
415 | } |
416 | |
417 | public String getName() |
418 | { |
419 | return name; |
420 | } |
421 | |
422 | public void setName( String name ) |
423 | { |
424 | this.name = name; |
425 | } |
426 | |
427 | public Schedule getSchedule() |
428 | { |
429 | return schedule; |
430 | } |
431 | |
432 | public void setSchedule( Schedule schedule ) |
433 | { |
434 | this.schedule = schedule; |
435 | } |
436 | |
437 | public boolean isConfirmed() |
438 | { |
439 | return confirmed; |
440 | } |
441 | |
442 | public void setConfirmed( boolean confirmed ) |
443 | { |
444 | this.confirmed = confirmed; |
445 | } |
446 | |
447 | public int getMaxJobExecutionTime() |
448 | { |
449 | return maxJobExecutionTime; |
450 | } |
451 | |
452 | public void setMaxJobExecutionTime( int maxJobExecutionTime ) |
453 | { |
454 | this.maxJobExecutionTime = maxJobExecutionTime; |
455 | } |
456 | |
457 | public String getSecond() |
458 | { |
459 | return second; |
460 | } |
461 | |
462 | public void setSecond( String second ) |
463 | { |
464 | this.second = second; |
465 | } |
466 | |
467 | public String getMinute() |
468 | { |
469 | return minute; |
470 | } |
471 | |
472 | public void setMinute( String minute ) |
473 | { |
474 | this.minute = minute; |
475 | } |
476 | |
477 | public String getHour() |
478 | { |
479 | return hour; |
480 | } |
481 | |
482 | public void setHour( String hour ) |
483 | { |
484 | this.hour = hour; |
485 | } |
486 | |
487 | public String getDayOfMonth() |
488 | { |
489 | return dayOfMonth; |
490 | } |
491 | |
492 | public void setDayOfMonth( String dayOfMonth ) |
493 | { |
494 | this.dayOfMonth = dayOfMonth; |
495 | } |
496 | |
497 | public String getYear() |
498 | { |
499 | return year; |
500 | } |
501 | |
502 | public void setYear( String year ) |
503 | { |
504 | this.year = year; |
505 | } |
506 | |
507 | public String getMonth() |
508 | { |
509 | return month; |
510 | } |
511 | |
512 | public void setMonth( String month ) |
513 | { |
514 | this.month = month; |
515 | } |
516 | |
517 | public String getDayOfWeek() |
518 | { |
519 | return dayOfWeek; |
520 | } |
521 | |
522 | public void setDayOfWeek( String dayOfWeek ) |
523 | { |
524 | this.dayOfWeek = dayOfWeek; |
525 | } |
526 | |
527 | private String getCronExpression() |
528 | { |
529 | return ( second + " " + minute + " " + hour + " " + dayOfMonth + " " + month + " " + dayOfWeek + " " + |
530 | year ).trim(); |
531 | } |
532 | |
533 | public List<BuildQueue> getAvailableBuildQueues() |
534 | { |
535 | return availableBuildQueues; |
536 | } |
537 | |
538 | public void setAvailableBuildQueues( List<BuildQueue> availableBuildQueues ) |
539 | { |
540 | this.availableBuildQueues = availableBuildQueues; |
541 | } |
542 | |
543 | public List<BuildQueue> getSelectedBuildQueues() |
544 | { |
545 | return selectedBuildQueues; |
546 | } |
547 | |
548 | public void setSelectedBuildQueues( List<BuildQueue> selectedBuildQueues ) |
549 | { |
550 | this.selectedBuildQueues = selectedBuildQueues; |
551 | } |
552 | |
553 | public List<String> getSelectedBuildQueuesIds() |
554 | { |
555 | return selectedBuildQueuesIds; |
556 | } |
557 | |
558 | public void setSelectedBuildQueuesIds( List<String> selectedBuildQueuesIds ) |
559 | { |
560 | this.selectedBuildQueuesIds = selectedBuildQueuesIds; |
561 | } |
562 | } |