1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.plugins.releaser.service;
35
36 import java.io.FileInputStream;
37 import java.io.FileNotFoundException;
38 import java.io.IOException;
39 import java.io.InputStream;
40 import java.util.ArrayList;
41 import java.util.HashMap;
42 import java.util.List;
43 import java.util.Locale;
44 import java.util.Map;
45 import java.util.concurrent.ExecutionException;
46 import java.util.concurrent.ExecutorService;
47 import java.util.concurrent.Executors;
48 import java.util.concurrent.Future;
49
50 import javax.servlet.http.HttpServletRequest;
51 import javax.xml.bind.JAXBException;
52
53 import fr.paris.lutece.plugins.releaser.business.Component;
54 import fr.paris.lutece.plugins.releaser.business.Dependency;
55 import fr.paris.lutece.plugins.releaser.business.ReleaserUser;
56 import fr.paris.lutece.plugins.releaser.business.ReleaserUser.Credential;
57 import fr.paris.lutece.plugins.releaser.business.jaxb.maven.Model;
58 import fr.paris.lutece.plugins.releaser.business.Site;
59 import fr.paris.lutece.plugins.releaser.business.SiteHome;
60 import fr.paris.lutece.plugins.releaser.business.WorkflowReleaseContext;
61 import fr.paris.lutece.plugins.releaser.util.CVSFactoryService;
62 import fr.paris.lutece.plugins.releaser.util.ConstanteUtils;
63 import fr.paris.lutece.plugins.releaser.util.ReleaserUtils;
64 import fr.paris.lutece.plugins.releaser.util.github.GitUtils;
65 import fr.paris.lutece.plugins.releaser.util.pom.PomParser;
66 import fr.paris.lutece.plugins.releaser.util.pom.PomUpdater;
67 import fr.paris.lutece.plugins.releaser.util.version.Version;
68 import fr.paris.lutece.plugins.releaser.util.version.VersionParsingException;
69 import fr.paris.lutece.portal.business.user.AdminUser;
70 import fr.paris.lutece.portal.service.datastore.DatastoreService;
71 import fr.paris.lutece.portal.service.i18n.I18nService;
72 import fr.paris.lutece.portal.service.plugin.Plugin;
73 import fr.paris.lutece.portal.service.rbac.RBACService;
74 import fr.paris.lutece.portal.service.util.AppException;
75 import fr.paris.lutece.portal.service.util.AppLogService;
76 import fr.paris.lutece.portal.service.util.AppPropertiesService;
77 import fr.paris.lutece.util.httpaccess.HttpAccessException;
78
79
80
81
82
83 public class SiteService
84 {
85
86
87 private static final int NB_POOL_REMOTE_INFORMATION = 60;
88
89
90 private static final String MESSAGE_AVOID_SNAPSHOT = "releaser.message.avoidSnapshot";
91
92
93 private static final String MESSAGE_UPGRADE_SELECTED = "releaser.message.upgradeSelected";
94
95
96 private static final String MESSAGE_TO_BE_RELEASED = "releaser.message.toBeReleased";
97
98
99 private static final String MESSAGE_MORE_RECENT_VERSION_AVAILABLE = "releaser.message.moreRecentVersionAvailable";
100
101
102 private static final String MESSAGE_AN_RELEASE_VERSION_ALREADY_EXIST = "releaser.message.releleaseVersionAlreadyExist";
103
104
105 private static final String MESSAGE_WRONG_POM_PARENT_SITE_VERSION = "releaser.message.wrongPomParentSiteVersion";
106
107
108 private static final String MESSAGE_NOT_DEFAULT_RELEASE_BRANCH_FROM = "releaser.message.notDefaultReleaseBranchFrom";
109
110
111
112
113
114
115
116
117
118
119
120
121 public static Site getSite( int nSiteId, HttpServletRequest request, Locale locale )
122 {
123 Site site = SiteHome.findByPrimaryKey( nSiteId );
124 String strPom = null;
125 ReleaserUser user = ReleaserUtils.getReleaserUser( request, locale );
126
127 if ( user != null )
128 {
129 Credential credential = user.getCredential( site.getRepoType( ) );
130
131 strPom = CVSFactoryService.getService( site.getRepoType( ) ).fetchPom( site, credential.getLogin( ), credential.getPassword( ) );
132
133 if ( strPom != null )
134 {
135 PomParsereleaser/util/pom/PomParser.html#PomParser">PomParser parser = new PomParser( );
136 parser.parse( site, strPom );
137 initSite( site, request, locale );
138 }
139 }
140 else
141 {
142 throw new AppException( ConstanteUtils.ERROR_TYPE_AUTHENTICATION_ERROR );
143 }
144
145 return site;
146 }
147
148
149
150
151
152
153
154
155
156
157
158 private static void initSite( Site site, HttpServletRequest request, Locale locale )
159 {
160
161 ReleaserUser user = ReleaserUtils.getReleaserUser( request, locale );
162 Credential credential = user.getCredential( site.getRepoType( ) );
163
164
165 String strLastReleaseVersion = CVSFactoryService.getService( site.getRepoType( ) ).getLastRelease( site, credential.getLogin( ),
166 credential.getPassword( ) );
167 site.setLastReleaseVersion( strLastReleaseVersion );
168
169
170
171 String strOriginVersion = getOriginVersion( strLastReleaseVersion, site.getVersion( ) );
172
173 site.setNextReleaseVersion( Version.getReleaseVersion( strOriginVersion ) );
174 site.setNextSnapshotVersion( Version.getNextSnapshotVersion( strOriginVersion ) );
175 site.setTargetVersions( Version.getNextReleaseVersions( strOriginVersion ) );
176 site.setBranchReleaseFrom( GitUtils.DEFAULT_RELEASE_BRANCH );
177
178 initComponents( site );
179 }
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194 public static String getOriginVersion( String strLastRelease, String strCurrentVersion )
195 {
196 String strOriginVersion = strCurrentVersion;
197 if ( ( strLastRelease != null ) && Version.isCandidate( strLastRelease ) )
198 {
199 strOriginVersion = strLastRelease;
200 }
201 return strOriginVersion;
202 }
203
204
205
206
207
208
209
210 private static void initComponents( Site site )
211 {
212 for ( Dependency dependency : site.getCurrentDependencies( ) )
213 {
214 Componentaser/business/Component.html#Component">Component component = new Component( );
215
216 component.setIsProject( isProjectComponent( site, dependency.getArtifactId( ) ) );
217 component.setArtifactId( dependency.getArtifactId( ) );
218 component.setGroupId( dependency.getGroupId( ) );
219 component.setType( dependency.getType( ) );
220 String currentVersion = dependency.getVersion( ).replace( "[", "" ).replace( "]", "" );
221 component.setCurrentVersion( currentVersion );
222 site.addComponent( component );
223 }
224
225 ExecutorService executor = Executors.newFixedThreadPool( NB_POOL_REMOTE_INFORMATION );
226
227 List<Future> futures = new ArrayList<Future>( site.getCurrentDependencies( ).size( ) );
228
229 for ( Component component : site.getComponents( ) )
230 {
231 futures.add( executor.submit( new GetRemoteInformationsTask( component ) ) );
232 }
233
234
235 for ( Future future : futures )
236 {
237
238 try
239 {
240 future.get( );
241 }
242 catch( InterruptedException e )
243 {
244 AppLogService.error( e );
245 }
246 catch( ExecutionException e )
247 {
248
249 AppLogService.error( e );
250 }
251
252 }
253
254 executor.shutdown( );
255
256 for ( Component component : site.getComponents( ) )
257 {
258 ComponentService.getService( ).updateRemoteInformations( component );
259 defineTargetVersion( component );
260 defineNextSnapshotVersion( component );
261 component.setName( ReleaserUtils.getComponentName( component.getScmDeveloperConnection( ), component.getArtifactId( ) ) );
262 component.setBranchReleaseFrom( GitUtils.DEFAULT_RELEASE_BRANCH );
263 }
264
265 }
266
267
268
269
270
271
272
273
274
275 private static void defineTargetVersion( Component component )
276 {
277 if ( component.isProject( ) && component.isSnapshotVersion( ) )
278 {
279 if ( component.getLastAvailableVersion( ) != null && !component.getCurrentVersion( ).equals( component.getLastAvailableSnapshotVersion( ) )
280 || component.isTheme( ) )
281 {
282 component.setTargetVersion( component.getLastAvailableVersion( ) );
283 }
284 else
285 {
286 component.setTargetVersions( Version.getNextReleaseVersions( component.getCurrentVersion( ) ) );
287 String strTargetVersion = Version.getReleaseVersion( component.getCurrentVersion( ) );
288 component.setTargetVersion( strTargetVersion );
289 }
290 }
291 else
292 {
293 component.setTargetVersion( component.getCurrentVersion( ) );
294 }
295 }
296
297
298
299
300
301
302
303 private static void defineNextSnapshotVersion( Component component )
304 {
305 String strNextSnapshotVersion = Version.NOT_AVAILABLE;
306 if ( !component.getCurrentVersion( ).equals( component.getLastAvailableSnapshotVersion( ) ) || component.isTheme( ) )
307 {
308 component.setNextSnapshotVersion( component.getLastAvailableSnapshotVersion( ) );
309 }
310 else
311 {
312 try
313 {
314 Version version = Version.parse( component.getTargetVersion( ) );
315 boolean bSnapshot = true;
316 strNextSnapshotVersion = version.nextPatch( bSnapshot ).toString( );
317 }
318 catch( VersionParsingException ex )
319 {
320 AppLogService.error( "Error parsing version for component " + component.getArtifactId( ) + " : " + ex.getMessage( ), ex );
321
322 }
323 component.setNextSnapshotVersion( strNextSnapshotVersion );
324 }
325
326 }
327
328
329
330
331
332
333
334
335
336
337 private static boolean isProjectComponent( Site site, String strArtifactId )
338 {
339 return new Boolean( DatastoreService.getDataValue( getComponetIsProjectDataKey( site, strArtifactId ), Boolean.FALSE.toString( ) ) );
340 }
341
342
343
344
345
346
347
348
349
350
351
352 public static void updateComponentAsProjectStatus( Site site, String strArtifactId, Boolean bIsProject )
353 {
354 DatastoreService.setDataValue( getComponetIsProjectDataKey( site, strArtifactId ), bIsProject.toString( ) );
355
356 }
357
358
359
360
361
362
363
364 public static void removeComponentAsProjectBySite( int nIdSite )
365 {
366 DatastoreService.removeDataByPrefix( getPrefixIsProjectDataKey( nIdSite ) );
367
368 }
369
370
371
372
373
374
375
376
377
378
379 private static String getComponetIsProjectDataKey( Site site, String strArtifactId )
380 {
381
382 return getPrefixIsProjectDataKey( site.getId( ) ) + strArtifactId;
383
384 }
385
386
387
388
389
390
391
392
393 private static String getPrefixIsProjectDataKey( int nIdSite )
394 {
395
396 return ConstanteUtils.CONSTANTE_COMPONENT_PROJECT_PREFIX + "_" + nIdSite + "_";
397
398 }
399
400
401
402
403
404
405
406
407
408 public static void buildComments( Site site, Locale locale )
409 {
410 site.resetComments( );
411 buildReleaseComments( site, locale );
412
413 for ( Component component : site.getComponents( ) )
414 {
415 component.resetComments( );
416 buildReleaseComments( component, locale );
417 }
418 }
419
420
421
422
423
424
425
426
427
428 private static void buildReleaseComments( Component component, Locale locale )
429 {
430
431 if ( !component.getBranchReleaseFrom( ).equals( GitUtils.DEFAULT_RELEASE_BRANCH ) )
432 {
433 String strComment = I18nService.getLocalizedString( MESSAGE_NOT_DEFAULT_RELEASE_BRANCH_FROM, locale );
434 component.addReleaseComment( strComment );
435
436 return;
437 }
438
439 if ( !component.isProject( ) )
440 {
441 if ( Version.isSnapshot( component.getTargetVersion( ) ) )
442 {
443 String strComment = I18nService.getLocalizedString( MESSAGE_AVOID_SNAPSHOT, locale );
444 component.addReleaseComment( strComment );
445 }
446 else
447 if ( component.getLastAvailableVersion( ) != null && component.getTargetVersion( ) != null && component.getLastAvailableVersion( ) != null
448 && ReleaserUtils.compareVersion( component.getTargetVersion( ), component.getLastAvailableVersion( ) ) < 0 )
449 {
450 String [ ] arguments = {
451 component.getLastAvailableVersion( )
452 };
453 String strComment = I18nService.getLocalizedString( MESSAGE_MORE_RECENT_VERSION_AVAILABLE, arguments, locale );
454
455 component.addReleaseComment( strComment );
456 }
457 }
458 else
459 {
460 if ( component.isSnapshotVersion( ) )
461 {
462 if ( ReleaserUtils.compareVersion( component.getCurrentVersion( ), component.getLastAvailableSnapshotVersion( ) ) < 0 )
463 {
464
465 String [ ] arguments = {
466 component.getLastAvailableVersion( )
467 };
468 String strComment = I18nService.getLocalizedString( MESSAGE_UPGRADE_SELECTED, arguments, locale );
469 component.addReleaseComment( strComment );
470 }
471 else
472 if ( !component.shouldBeReleased( ) && !component.isDowngrade( ) )
473 {
474
475 String [ ] arguments = {
476 component.getLastAvailableVersion( )
477 };
478 String strComment = I18nService.getLocalizedString( MESSAGE_AN_RELEASE_VERSION_ALREADY_EXIST, arguments, locale );
479 component.addReleaseComment( strComment );
480 }
481
482 else
483 if ( component.shouldBeReleased( ) )
484 {
485
486 String strComment = I18nService.getLocalizedString( MESSAGE_TO_BE_RELEASED, locale );
487 component.addReleaseComment( strComment );
488 }
489 }
490 else
491 if ( ReleaserUtils.compareVersion( component.getCurrentVersion( ), component.getLastAvailableVersion( ) ) < 0 )
492 {
493 String [ ] arguments = {
494 component.getLastAvailableVersion( )
495 };
496 String strComment = I18nService.getLocalizedString( MESSAGE_MORE_RECENT_VERSION_AVAILABLE, arguments, locale );
497
498 component.addReleaseComment( strComment );
499 }
500 }
501 }
502
503
504
505
506
507
508
509
510
511 public static void upgradeComponent( Site site, String strArtifactId )
512 {
513 for ( Component component : site.getComponents( ) )
514 {
515 if ( component.getArtifactId( ).equals( strArtifactId ) )
516 {
517 component.setTargetVersion( component.getLastAvailableVersion( ) );
518 component.setUpgrade( true );
519 }
520 }
521 }
522
523
524
525
526
527
528
529
530
531 public static void cancelUpgradeComponent( Site site, String strArtifactId )
532 {
533 for ( Component component : site.getComponents( ) )
534 {
535 if ( component.getArtifactId( ).equals( strArtifactId ) )
536 {
537
538 component.setTargetVersion( component.getCurrentVersion( ) );
539 component.setUpgrade( false );
540 }
541 }
542 }
543
544
545
546
547
548
549
550
551
552 public static void downgradeComponent( Site site, String strArtifactId )
553 {
554 for ( Component component : site.getComponents( ) )
555 {
556 if ( component.getArtifactId( ).equals( strArtifactId ) && component.isSnapshotVersion( ) )
557 {
558 component.setTargetVersion( component.getLastAvailableVersion( ) );
559 component.setNextSnapshotVersion( component.getLastAvailableSnapshotVersion( ) );
560 component.setDowngrade( true );
561 }
562 }
563 }
564
565
566
567
568
569
570
571
572
573 public static void cancelDowngradeComponent( Site site, String strArtifactId )
574 {
575 for ( Component component : site.getComponents( ) )
576 {
577 if ( component.getArtifactId( ).equals( strArtifactId ) && component.isSnapshotVersion( ) )
578 {
579 component.setDowngrade( false );
580 defineTargetVersion( component );
581 defineNextSnapshotVersion( component );
582 }
583 }
584 }
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601 public static int releaseComponent( Site site, String strArtifactId, Locale locale, AdminUser user, HttpServletRequest request )
602 {
603 for ( Component component : site.getComponents( ) )
604 {
605 if ( component.getArtifactId( ).equals( strArtifactId ) && component.shouldBeReleased( ) )
606 {
607
608 return ComponentService.getService( ).release( component, locale, user, request );
609
610 }
611 }
612 return ConstanteUtils.CONSTANTE_ID_NULL;
613 }
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628 public static Map<String, Integer> releaseSite( Site site, Locale locale, AdminUser user, HttpServletRequest request )
629 {
630 Map<String, Integer> mapResultContext = new HashMap<String, Integer>( );
631
632 Integer nIdWfContext;
633
634 for ( Component component : site.getComponents( ) )
635 {
636 if ( component.isProject( ) && component.shouldBeReleased( ) && !component.isTheme( ) )
637 {
638 component.setErrorLastRelease( false );
639 nIdWfContext = ComponentService.getService( ).release( component, locale, user, request );
640 mapResultContext.put( component.getArtifactId( ), nIdWfContext );
641
642 }
643 }
644
645 WorkflowReleaseContext context = new WorkflowReleaseContext( );
646 context.setSite( site );
647 context.setReleaserUser( ReleaserUtils.getReleaserUser( request, locale ) );
648
649 int nIdWorkflow = WorkflowReleaseContextService.getService( ).getIdWorkflow( context );
650 WorkflowReleaseContextService.getService( ).addWorkflowReleaseContext( context );
651
652 WorkflowReleaseContextService.getService( ).startWorkflowReleaseContext( context, nIdWorkflow, locale, request, user );
653
654 mapResultContext.put( site.getArtifactId( ), context.getId( ) );
655
656 return mapResultContext;
657
658 }
659
660
661
662
663
664
665
666
667
668 public static void toggleProjectComponent( Site site, String strArtifactId )
669 {
670 for ( Component component : site.getComponents( ) )
671 {
672 if ( component.getArtifactId( ).equals( strArtifactId ) )
673 {
674 component.setIsProject( !component.isProject( ) );
675 updateComponentAsProjectStatus( site, strArtifactId, component.isProject( ) );
676
677 if ( component.isProject( ) )
678 {
679 try
680 {
681 ComponentService.getService( ).setRemoteInformations( component, false );
682 }
683 catch( HttpAccessException | IOException e )
684 {
685 AppLogService.error( e );
686 }
687 ComponentService.getService( ).updateRemoteInformations( component );
688 defineTargetVersion( component );
689 defineNextSnapshotVersion( component );
690 component.setName( ReleaserUtils.getComponentName( component.getScmDeveloperConnection( ), component.getArtifactId( ) ) );
691 }
692
693 }
694 }
695 }
696
697
698
699
700
701
702
703
704
705 public static void changeNextReleaseVersion( Site site, String strArtifactId )
706 {
707 for ( Component component : site.getComponents( ) )
708 {
709 if ( component.getArtifactId( ).equals( strArtifactId ) )
710 {
711 ComponentService.getService( ).changeNextReleaseVersion( component );
712 }
713 }
714 }
715
716
717
718
719
720
721
722 public static void changeNextReleaseVersion( Site site )
723 {
724 List<String> listTargetVersions = site.getTargetVersions( );
725 int nNewIndex = ( site.getTargetVersionIndex( ) + 1 ) % listTargetVersions.size( );
726 String strTargetVersion = listTargetVersions.get( nNewIndex );
727 site.setNextReleaseVersion( strTargetVersion );
728 site.setTargetVersionIndex( nNewIndex );
729 site.setNextSnapshotVersion( Version.getNextSnapshotVersion( strTargetVersion ) );
730 }
731
732
733
734
735
736
737
738
739 public String generateTargetPOM( Site site )
740 {
741 throw new UnsupportedOperationException( "Not supported yet." );
742 }
743
744
745
746
747
748
749
750
751
752 private static void buildReleaseComments( Site site, Locale locale )
753 {
754
755 if ( !site.isTheme( ) )
756 {
757
758 InputStream inputStream = null;
759 String strPomPath = ReleaserUtils.getLocalSitePomPath( site );
760 String strPomParentReferenceVersion = AppPropertiesService.getProperty( ConstanteUtils.PROPERTY_POM_PARENT_SITE_VERSION );
761 try
762 {
763
764 inputStream = new FileInputStream( strPomPath );
765 Model model = PomUpdater.unmarshal( Model.class, inputStream );
766 String strParentSiteVersion = model.getParent( ).getVersion( );
767 if ( ReleaserUtils.compareVersion( strParentSiteVersion, strPomParentReferenceVersion ) < 0 )
768 {
769 String [ ] arguments = {
770 strPomParentReferenceVersion
771 };
772 String strComment = I18nService.getLocalizedString( MESSAGE_WRONG_POM_PARENT_SITE_VERSION, arguments, locale );
773 site.addReleaseComment( strComment );
774 }
775
776 }
777 catch( FileNotFoundException e )
778 {
779 AppLogService.error( e );
780 }
781 catch( JAXBException e )
782 {
783
784 AppLogService.error( e );
785 }
786 }
787
788 }
789
790 public static List<Site> getAuthorizedSites( int clusterId, AdminUser adminUser )
791 {
792
793 List<Site> listAuthorizedSites = new ArrayList<Site>( );
794
795 List<Site> listSite = SiteHome.findByCluster( clusterId );
796
797
798 for ( Site site : listSite )
799 {
800 boolean bAutoriseViewSite = false;
801
802 HashMap<String, Boolean> sitePermissions = new HashMap<String, Boolean>( );
803
804
805 if ( RBACService.isAuthorized( Site.RESOURCE_TYPE, site.getResourceId( ), SiteResourceIdService.PERMISSION_RELEASE, adminUser ) )
806 {
807 sitePermissions.put( Site.PERMISSION_RELEASE_SITE, true );
808 bAutoriseViewSite = true;
809 }
810 else
811 {
812 sitePermissions.put( Site.PERMISSION_RELEASE_SITE, false );
813 }
814
815
816 if ( RBACService.isAuthorized( Site.RESOURCE_TYPE, site.getResourceId( ), SiteResourceIdService.PERMISSION_MODIFY, adminUser ) )
817 {
818 sitePermissions.put( Site.PERMISSION_MODIFY_SITE, true );
819 bAutoriseViewSite = true;
820 }
821 else
822 {
823 sitePermissions.put( Site.PERMISSION_MODIFY_SITE, false );
824 }
825
826
827 if ( RBACService.isAuthorized( Site.RESOURCE_TYPE, site.getResourceId( ), SiteResourceIdService.PERMISSION_DELETE, adminUser ) )
828 {
829 sitePermissions.put( Site.PERMISSION_DELETE_SITE, true );
830 bAutoriseViewSite = true;
831 }
832 else
833 {
834 sitePermissions.put( Site.PERMISSION_DELETE_SITE, false );
835 }
836
837
838 if ( bAutoriseViewSite )
839 {
840
841 site.setPermissions( sitePermissions );
842
843
844 listAuthorizedSites.add( site );
845 }
846 }
847
848 return listAuthorizedSites;
849 }
850
851 public static boolean IsUserAuthorized( AdminUser adminUser, String siteId, String permission )
852 {
853
854 boolean bAuthorized = false;
855
856 if ( RBACService.isAuthorized( Site.RESOURCE_TYPE, siteId, permission, adminUser ) )
857 {
858 bAuthorized = true;
859 }
860
861 return bAuthorized;
862 }
863
864 public static boolean IsSiteAlreadyExist( String siteName, String artifactId, String scmUrl )
865 {
866 String clusterName = SiteHome.findDuplicateSite( siteName, artifactId, scmUrl );
867 if ( clusterName != null )
868 return true;
869
870 return false;
871 }
872
873 }