1 | package org.apache.continuum.dao; |
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 java.util.HashMap; |
23 | import java.util.List; |
24 | import java.util.Map; |
25 | |
26 | import javax.jdo.Extent; |
27 | import javax.jdo.JDOHelper; |
28 | import javax.jdo.PersistenceManager; |
29 | import javax.jdo.Query; |
30 | import javax.jdo.Transaction; |
31 | |
32 | import org.apache.maven.continuum.model.project.BuildResult; |
33 | import org.apache.maven.continuum.model.project.Project; |
34 | import org.apache.maven.continuum.project.ContinuumProjectState; |
35 | import org.apache.maven.continuum.store.ContinuumStoreException; |
36 | import org.springframework.stereotype.Repository; |
37 | |
38 | /** |
39 | * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a> |
40 | * @version $Id: BuildResultDaoImpl.java 790386 2009-07-01 21:27:25Z evenisse $ |
41 | * @plexus.component role="org.apache.continuum.dao.BuildResultDao" |
42 | */ |
43 | @Repository("buildResultDao") |
44 | public class BuildResultDaoImpl |
45 | extends AbstractDao |
46 | implements BuildResultDao |
47 | { |
48 | public void updateBuildResult( BuildResult build ) |
49 | throws ContinuumStoreException |
50 | { |
51 | PersistenceManager pm = getPersistenceManager(); |
52 | |
53 | Transaction tx = pm.currentTransaction(); |
54 | |
55 | Project project = build.getProject(); |
56 | try |
57 | { |
58 | tx.begin(); |
59 | |
60 | if ( !JDOHelper.isDetached( build ) ) |
61 | { |
62 | throw new ContinuumStoreException( "Not detached: " + build ); |
63 | } |
64 | |
65 | pm.makePersistent( build ); |
66 | |
67 | if ( !JDOHelper.isDetached( project ) ) |
68 | { |
69 | throw new ContinuumStoreException( "Not detached: " + project ); |
70 | } |
71 | |
72 | project.setState( build.getState() ); |
73 | |
74 | //TODO: Use projectDao |
75 | pm.makePersistent( project ); |
76 | |
77 | tx.commit(); |
78 | } |
79 | finally |
80 | { |
81 | rollback( tx ); |
82 | } |
83 | } |
84 | |
85 | public void addBuildResult( Project project, BuildResult build ) |
86 | throws ContinuumStoreException |
87 | { |
88 | PersistenceManager pm = getPersistenceManager(); |
89 | |
90 | Transaction tx = pm.currentTransaction(); |
91 | |
92 | try |
93 | { |
94 | tx.begin(); |
95 | |
96 | pm.getFetchPlan().addGroup( PROJECT_WITH_BUILDS_FETCH_GROUP ); |
97 | |
98 | Object objectId = pm.newObjectIdInstance( Project.class, project.getId() ); |
99 | |
100 | project = (Project) pm.getObjectById( objectId ); |
101 | |
102 | build = (BuildResult) makePersistent( pm, build, false ); |
103 | |
104 | // TODO: these are in the wrong spot - set them on success (though |
105 | // currently some depend on latest build being the one in progress) |
106 | project.setLatestBuildId( build.getId() ); |
107 | |
108 | project.setState( build.getState() ); |
109 | |
110 | project.addBuildResult( build ); |
111 | |
112 | tx.commit(); |
113 | } |
114 | finally |
115 | { |
116 | rollback( tx ); |
117 | } |
118 | } |
119 | |
120 | public BuildResult getLatestBuildResultForProject( int projectId ) |
121 | { |
122 | PersistenceManager pm = getPersistenceManager(); |
123 | |
124 | Transaction tx = pm.currentTransaction(); |
125 | |
126 | try |
127 | { |
128 | tx.begin(); |
129 | |
130 | Extent extent = pm.getExtent( BuildResult.class, true ); |
131 | |
132 | Query query = pm.newQuery( extent ); |
133 | |
134 | query.declareParameters( "int projectId" ); |
135 | |
136 | query.setFilter( "this.project.id == projectId && this.project.latestBuildId == this.id" ); |
137 | |
138 | List<BuildResult> result = (List<BuildResult>) query.execute( projectId ); |
139 | |
140 | result = (List<BuildResult>) pm.detachCopyAll( result ); |
141 | |
142 | tx.commit(); |
143 | |
144 | if ( result != null && !result.isEmpty() ) |
145 | { |
146 | return result.get( 0 ); |
147 | } |
148 | } |
149 | finally |
150 | { |
151 | rollback( tx ); |
152 | } |
153 | return null; |
154 | } |
155 | |
156 | public BuildResult getLatestBuildResultForProjectWithDetails( int projectId ) |
157 | { |
158 | PersistenceManager pm = getPersistenceManager(); |
159 | |
160 | Transaction tx = pm.currentTransaction(); |
161 | |
162 | try |
163 | { |
164 | tx.begin(); |
165 | |
166 | pm.getFetchPlan().addGroup( BUILD_RESULT_WITH_DETAILS_FETCH_GROUP ); |
167 | |
168 | Extent extent = pm.getExtent( BuildResult.class, true ); |
169 | |
170 | Query query = pm.newQuery( extent ); |
171 | |
172 | query.declareParameters( "int projectId" ); |
173 | |
174 | query.setFilter( "this.project.id == projectId && this.project.latestBuildId == this.id" ); |
175 | |
176 | List<BuildResult> result = (List<BuildResult>) query.execute( projectId ); |
177 | |
178 | result = (List<BuildResult>) pm.detachCopyAll( result ); |
179 | |
180 | tx.commit(); |
181 | |
182 | if ( result != null && !result.isEmpty() ) |
183 | { |
184 | return result.get( 0 ); |
185 | } |
186 | } |
187 | finally |
188 | { |
189 | rollback( tx ); |
190 | } |
191 | return null; |
192 | } |
193 | |
194 | public BuildResult getLatestBuildResultForBuildDefinition( int projectId, int buildDefinitionId ) |
195 | { |
196 | PersistenceManager pm = getPersistenceManager(); |
197 | |
198 | Transaction tx = pm.currentTransaction(); |
199 | |
200 | try |
201 | { |
202 | tx.begin(); |
203 | |
204 | Extent extent = pm.getExtent( BuildResult.class, true ); |
205 | |
206 | Query query = pm.newQuery( extent ); |
207 | |
208 | query.declareParameters( "int projectId, int buildDefinitionId" ); |
209 | |
210 | query.setFilter( "this.project.id == projectId && this.buildDefinition.id == buildDefinitionId" ); |
211 | query.setOrdering( "id descending" ); |
212 | |
213 | Object[] params = new Object[2]; |
214 | params[0] = projectId; |
215 | params[1] = buildDefinitionId; |
216 | |
217 | List<BuildResult> result = (List<BuildResult>) query.executeWithArray( params ); |
218 | |
219 | result = (List<BuildResult>) pm.detachCopyAll( result ); |
220 | |
221 | tx.commit(); |
222 | |
223 | if ( result != null && !result.isEmpty() ) |
224 | { |
225 | return result.get( 0 ); |
226 | } |
227 | } |
228 | finally |
229 | { |
230 | rollback( tx ); |
231 | } |
232 | return null; |
233 | } |
234 | |
235 | public Map<Integer, BuildResult> getLatestBuildResultsByProjectGroupId( int projectGroupId ) |
236 | { |
237 | PersistenceManager pm = getPersistenceManager(); |
238 | |
239 | Transaction tx = pm.currentTransaction(); |
240 | |
241 | try |
242 | { |
243 | tx.begin(); |
244 | |
245 | Extent extent = pm.getExtent( BuildResult.class, true ); |
246 | |
247 | Query query = pm.newQuery( extent ); |
248 | |
249 | String filter = "this.project.latestBuildId == this.id"; |
250 | |
251 | if ( projectGroupId > 0 ) |
252 | { |
253 | query.declareParameters( "int projectGroupId" ); |
254 | filter += " && this.project.projectGroup.id == projectGroupId"; |
255 | } |
256 | |
257 | query.setFilter( filter ); |
258 | |
259 | List<BuildResult> result; |
260 | if ( projectGroupId > 0 ) |
261 | { |
262 | result = (List<BuildResult>) query.execute( projectGroupId ); |
263 | } |
264 | else |
265 | { |
266 | result = (List<BuildResult>) query.execute(); |
267 | } |
268 | |
269 | result = (List<BuildResult>) pm.detachCopyAll( result ); |
270 | |
271 | tx.commit(); |
272 | |
273 | if ( result != null && !result.isEmpty() ) |
274 | { |
275 | Map<Integer, BuildResult> builds = new HashMap<Integer, BuildResult>(); |
276 | |
277 | for ( BuildResult br : result ) |
278 | { |
279 | builds.put( br.getProject().getId(), br ); |
280 | } |
281 | |
282 | return builds; |
283 | } |
284 | } |
285 | finally |
286 | { |
287 | rollback( tx ); |
288 | } |
289 | |
290 | return null; |
291 | } |
292 | |
293 | public void removeBuildResult( BuildResult buildResult ) |
294 | { |
295 | removeObject( buildResult ); |
296 | } |
297 | |
298 | public List<BuildResult> getAllBuildsForAProjectByDate( int projectId ) |
299 | { |
300 | PersistenceManager pm = getPersistenceManager(); |
301 | |
302 | Transaction tx = pm.currentTransaction(); |
303 | |
304 | try |
305 | { |
306 | tx.begin(); |
307 | |
308 | Query query = pm.newQuery( "SELECT FROM " + BuildResult.class.getName() + |
309 | " WHERE project.id == projectId PARAMETERS int projectId ORDER BY endTime DESC" ); |
310 | |
311 | query.declareImports( "import java.lang.Integer" ); |
312 | |
313 | query.declareParameters( "Integer projectId" ); |
314 | |
315 | List<BuildResult> result = (List<BuildResult>) query.execute( projectId ); |
316 | |
317 | result = (List<BuildResult>) pm.detachCopyAll( result ); |
318 | |
319 | tx.commit(); |
320 | |
321 | return result; |
322 | } |
323 | finally |
324 | { |
325 | rollback( tx ); |
326 | } |
327 | } |
328 | |
329 | public BuildResult getBuildResult( int buildId ) |
330 | throws ContinuumStoreException |
331 | { |
332 | return (BuildResult) getObjectById( BuildResult.class, buildId, BUILD_RESULT_WITH_DETAILS_FETCH_GROUP ); |
333 | } |
334 | |
335 | public List<BuildResult> getBuildResultByBuildNumber( int projectId, int buildNumber ) |
336 | { |
337 | PersistenceManager pm = getPersistenceManager(); |
338 | |
339 | Transaction tx = pm.currentTransaction(); |
340 | |
341 | try |
342 | { |
343 | tx.begin(); |
344 | |
345 | Extent extent = pm.getExtent( BuildResult.class, true ); |
346 | |
347 | Query query = pm.newQuery( extent ); |
348 | |
349 | query.declareParameters( "int projectId, int buildNumber" ); |
350 | |
351 | query.setFilter( "this.project.id == projectId && this.buildNumber == buildNumber" ); |
352 | |
353 | List<BuildResult> result = (List<BuildResult>) query.execute( projectId, buildNumber ); |
354 | |
355 | result = (List<BuildResult>) pm.detachCopyAll( result ); |
356 | |
357 | tx.commit(); |
358 | |
359 | return result; |
360 | } |
361 | finally |
362 | { |
363 | rollback( tx ); |
364 | } |
365 | } |
366 | |
367 | public List<BuildResult> getBuildResultsByBuildDefinition( int projectId, int buildDefinitionId ) |
368 | { |
369 | return getBuildResultsByBuildDefinition( projectId, buildDefinitionId, -1, -1 ); |
370 | } |
371 | |
372 | public List<BuildResult> getBuildResultsByBuildDefinition( int projectId, int buildDefinitionId, long startIndex, |
373 | long endIndex ) |
374 | { |
375 | PersistenceManager pm = getPersistenceManager(); |
376 | |
377 | Transaction tx = pm.currentTransaction(); |
378 | |
379 | try |
380 | { |
381 | tx.begin(); |
382 | |
383 | Extent extent = pm.getExtent( BuildResult.class, true ); |
384 | |
385 | Query query = pm.newQuery( extent ); |
386 | |
387 | if ( startIndex >= 0 && endIndex >= 0 ) |
388 | { |
389 | query.setRange( startIndex, endIndex ); |
390 | } |
391 | |
392 | query.declareParameters( "int projectId, int buildDefinitionId" ); |
393 | |
394 | query.setFilter( "this.project.id == projectId && this.buildDefinition.id == buildDefinitionId" ); |
395 | |
396 | query.setOrdering( "this.id descending" ); |
397 | |
398 | List<BuildResult> result = (List<BuildResult>) query.execute( projectId, buildDefinitionId ); |
399 | |
400 | result = (List<BuildResult>) pm.detachCopyAll( result ); |
401 | |
402 | tx.commit(); |
403 | |
404 | return result; |
405 | } |
406 | finally |
407 | { |
408 | rollback( tx ); |
409 | } |
410 | } |
411 | |
412 | public long getNbBuildResultsForProject( int projectId ) |
413 | { |
414 | PersistenceManager pm = getPersistenceManager(); |
415 | |
416 | Transaction tx = pm.currentTransaction(); |
417 | |
418 | try |
419 | { |
420 | tx.begin(); |
421 | |
422 | Query query = pm.newQuery( BuildResult.class, "project.id == projectId" ); |
423 | |
424 | query.declareParameters( "int projectId" ); |
425 | |
426 | query.setResult( "count(this)" ); |
427 | |
428 | long result = (Long) query.execute( projectId ); |
429 | |
430 | tx.commit(); |
431 | |
432 | return result; |
433 | } |
434 | finally |
435 | { |
436 | rollback( tx ); |
437 | } |
438 | } |
439 | |
440 | public long getNbBuildResultsInSuccessForProject( int projectId, long fromDate ) |
441 | { |
442 | PersistenceManager pm = getPersistenceManager(); |
443 | |
444 | Transaction tx = pm.currentTransaction(); |
445 | |
446 | try |
447 | { |
448 | tx.begin(); |
449 | |
450 | Extent extent = pm.getExtent( BuildResult.class, true ); |
451 | |
452 | Query query = pm.newQuery( extent ); |
453 | |
454 | query.declareParameters( "int projectId, long fromDate, int state" ); |
455 | |
456 | query.setFilter( "this.project.id == projectId && this.startTime > fromDate && this.state == state" ); |
457 | |
458 | query.setResult( "count(this)" ); |
459 | |
460 | long result = (Long) query.execute( projectId, fromDate, ContinuumProjectState.OK ); |
461 | |
462 | tx.commit(); |
463 | |
464 | return result; |
465 | } |
466 | finally |
467 | { |
468 | rollback( tx ); |
469 | } |
470 | } |
471 | |
472 | public List<BuildResult> getBuildResultsForProjectWithDetails( int projectId, long fromDate, int tobuildResultId ) |
473 | { |
474 | PersistenceManager pm = getPersistenceManager(); |
475 | |
476 | Transaction tx = pm.currentTransaction(); |
477 | |
478 | try |
479 | { |
480 | tx.begin(); |
481 | |
482 | Extent extent = pm.getExtent( BuildResult.class, true ); |
483 | pm.getFetchPlan().addGroup( BUILD_RESULT_WITH_DETAILS_FETCH_GROUP ); |
484 | |
485 | Query query = pm.newQuery( extent ); |
486 | |
487 | String parameters = "int projectId, long fromDate"; |
488 | String filter = "this.project.id == projectId && this.startTime > fromDate"; |
489 | |
490 | if ( tobuildResultId > 0 ) |
491 | { |
492 | parameters += ", int buildResultId"; |
493 | filter += " && this.id < buildResultId"; |
494 | } |
495 | query.declareParameters( parameters ); |
496 | |
497 | query.setFilter( filter ); |
498 | |
499 | query.setOrdering( "this.id descending" ); |
500 | |
501 | List<BuildResult> result; |
502 | |
503 | if ( tobuildResultId > 0 ) |
504 | { |
505 | result = (List<BuildResult>) query.execute( projectId, fromDate, tobuildResultId ); |
506 | } |
507 | else |
508 | { |
509 | result = (List<BuildResult>) query.execute( projectId, fromDate ); |
510 | } |
511 | |
512 | result = (List<BuildResult>) pm.detachCopyAll( result ); |
513 | |
514 | tx.commit(); |
515 | |
516 | return result; |
517 | } |
518 | finally |
519 | { |
520 | rollback( tx ); |
521 | } |
522 | } |
523 | |
524 | public List<BuildResult> getBuildResultsForProject( int projectId ) |
525 | { |
526 | return getBuildResultsForProjectWithDetails( projectId, -1, -1 ); |
527 | } |
528 | |
529 | public List<BuildResult> getBuildResultsForProject( int projectId, long startIndex, long endIndex ) |
530 | { |
531 | PersistenceManager pm = getPersistenceManager(); |
532 | |
533 | Transaction tx = pm.currentTransaction(); |
534 | |
535 | try |
536 | { |
537 | tx.begin(); |
538 | |
539 | Extent extent = pm.getExtent( BuildResult.class, true ); |
540 | |
541 | Query query = pm.newQuery( extent ); |
542 | |
543 | query.declareParameters( "int projectId" ); |
544 | |
545 | query.setFilter( "this.project.id == projectId" ); |
546 | |
547 | query.setOrdering( "this.startTime descending" ); |
548 | |
549 | if ( startIndex >= 0 ) |
550 | { |
551 | query.setRange( startIndex, endIndex ); |
552 | } |
553 | |
554 | List<BuildResult> result = (List<BuildResult>) query.execute( projectId ); |
555 | |
556 | result = (List<BuildResult>) pm.detachCopyAll( result ); |
557 | |
558 | tx.commit(); |
559 | |
560 | return result; |
561 | } |
562 | finally |
563 | { |
564 | rollback( tx ); |
565 | } |
566 | } |
567 | |
568 | public List<BuildResult> getBuildResultsForProjectFromId( int projectId, long startId ) |
569 | throws ContinuumStoreException |
570 | { |
571 | PersistenceManager pm = getPersistenceManager(); |
572 | |
573 | Transaction tx = pm.currentTransaction(); |
574 | |
575 | pm.getFetchPlan().addGroup( BUILD_RESULT_WITH_DETAILS_FETCH_GROUP ); |
576 | |
577 | try |
578 | { |
579 | tx.begin(); |
580 | |
581 | Extent extent = pm.getExtent( BuildResult.class, true ); |
582 | |
583 | Query query = pm.newQuery( extent ); |
584 | |
585 | query.declareParameters( "int projectId, int buildNumber" ); |
586 | |
587 | query.setFilter( "this.project.id == projectId && this.buildNumber >= buildNumber" ); |
588 | |
589 | query.setOrdering( "this.startTime descending" ); |
590 | |
591 | List<BuildResult> result = (List<BuildResult>) query.execute( projectId, startId ); |
592 | |
593 | result = (List<BuildResult>) pm.detachCopyAll( result ); |
594 | |
595 | tx.commit(); |
596 | |
597 | return result; |
598 | } |
599 | catch ( Exception e ) |
600 | { |
601 | throw new ContinuumStoreException( e.getMessage(), e ); |
602 | } |
603 | finally |
604 | { |
605 | rollback( tx ); |
606 | } |
607 | } |
608 | |
609 | public BuildResult getLatestBuildResultInSuccess( int projectId ) |
610 | { |
611 | PersistenceManager pm = getPersistenceManager(); |
612 | |
613 | Transaction tx = pm.currentTransaction(); |
614 | |
615 | try |
616 | { |
617 | tx.begin(); |
618 | |
619 | Extent extent = pm.getExtent( BuildResult.class, true ); |
620 | |
621 | Query query = pm.newQuery( extent ); |
622 | |
623 | query.declareParameters( "int projectId" ); |
624 | |
625 | String filter = "this.project.buildNumber == this.buildNumber && this.project.id == projectId"; |
626 | |
627 | query.setFilter( filter ); |
628 | |
629 | query.setUnique( true ); |
630 | |
631 | BuildResult result = (BuildResult) query.execute( projectId ); |
632 | |
633 | result = (BuildResult) pm.detachCopy( result ); |
634 | |
635 | tx.commit(); |
636 | |
637 | return result; |
638 | } |
639 | finally |
640 | { |
641 | rollback( tx ); |
642 | } |
643 | } |
644 | |
645 | private int getPreviousBuildResultIdInSuccess( int projectId, int buildResultId ) |
646 | { |
647 | PersistenceManager pm = getPersistenceManager(); |
648 | |
649 | Transaction tx = pm.currentTransaction(); |
650 | |
651 | try |
652 | { |
653 | tx.begin(); |
654 | |
655 | Extent extent = pm.getExtent( BuildResult.class, true ); |
656 | |
657 | Query query = pm.newQuery( extent ); |
658 | |
659 | query.declareParameters( "int projectId, int buildResultId" ); |
660 | |
661 | String filter = "this.id < buildResultId && this.state == " + ContinuumProjectState.OK + |
662 | " && this.project.id == projectId"; |
663 | |
664 | query.setFilter( filter ); |
665 | |
666 | query.setResult( "max(this.id)" ); |
667 | |
668 | int result = (Integer) query.execute( projectId, buildResultId ); |
669 | |
670 | tx.commit(); |
671 | |
672 | return result; |
673 | } |
674 | finally |
675 | { |
676 | rollback( tx ); |
677 | } |
678 | } |
679 | |
680 | public BuildResult getPreviousBuildResultInSuccess( int projectId, int buildResultId ) |
681 | throws ContinuumStoreException |
682 | { |
683 | try |
684 | { |
685 | return getBuildResult( getPreviousBuildResultIdInSuccess( projectId, buildResultId ) ); |
686 | } |
687 | catch ( NullPointerException e ) |
688 | { |
689 | return null; |
690 | } |
691 | } |
692 | |
693 | public Map<Integer, BuildResult> getBuildResultsInSuccessByProjectGroupId( int projectGroupId ) |
694 | { |
695 | PersistenceManager pm = getPersistenceManager(); |
696 | |
697 | Transaction tx = pm.currentTransaction(); |
698 | |
699 | try |
700 | { |
701 | tx.begin(); |
702 | |
703 | Extent extent = pm.getExtent( BuildResult.class, true ); |
704 | |
705 | Query query = pm.newQuery( extent ); |
706 | |
707 | String filter = "this.project.buildNumber == this.buildNumber"; |
708 | |
709 | if ( projectGroupId > 0 ) |
710 | { |
711 | query.declareParameters( "int projectGroupId" ); |
712 | filter += " && this.project.projectGroup.id == projectGroupId"; |
713 | } |
714 | |
715 | query.setFilter( filter ); |
716 | |
717 | List<BuildResult> result; |
718 | |
719 | if ( projectGroupId > 0 ) |
720 | { |
721 | result = (List<BuildResult>) query.execute( projectGroupId ); |
722 | } |
723 | else |
724 | { |
725 | result = (List<BuildResult>) query.execute(); |
726 | } |
727 | |
728 | result = (List<BuildResult>) pm.detachCopyAll( result ); |
729 | |
730 | tx.commit(); |
731 | |
732 | if ( result != null && !result.isEmpty() ) |
733 | { |
734 | Map<Integer, BuildResult> builds = new HashMap<Integer, BuildResult>(); |
735 | |
736 | for ( BuildResult br : result ) |
737 | { |
738 | builds.put( br.getProject().getId(), br ); |
739 | } |
740 | |
741 | return builds; |
742 | } |
743 | } |
744 | finally |
745 | { |
746 | rollback( tx ); |
747 | } |
748 | |
749 | return null; |
750 | } |
751 | } |