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