1 package fr.ifremer.quadrige2.synchro.service.client;
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 import com.google.common.base.Preconditions;
27 import com.google.gson.reflect.TypeToken;
28 import fr.ifremer.common.synchro.service.SynchroResult;
29 import fr.ifremer.quadrige2.core.config.Quadrige2Configuration;
30 import fr.ifremer.quadrige2.core.dao.technical.gson.Gsons;
31 import fr.ifremer.quadrige2.core.dao.technical.http.HttpHelper;
32 import fr.ifremer.quadrige2.core.exception.*;
33 import fr.ifremer.quadrige2.core.security.AuthenticationInfo;
34 import fr.ifremer.quadrige2.core.service.RestServiceSupport;
35 import fr.ifremer.quadrige2.core.vo.administration.program.ProgramVO;
36 import fr.ifremer.quadrige2.core.vo.administration.user.QuserVO;
37 import fr.ifremer.quadrige2.core.vo.data.survey.CampaignVO;
38 import fr.ifremer.quadrige2.core.vo.system.rule.RuleListVO;
39 import fr.ifremer.quadrige2.synchro.vo.SynchroExportContextVO;
40 import fr.ifremer.quadrige2.synchro.vo.SynchroImportContextVO;
41 import fr.ifremer.quadrige2.synchro.vo.SynchroProgressionStatus;
42 import fr.ifremer.quadrige2.synchro.vo.SynchroProgressionVO;
43 import org.apache.commons.collections4.CollectionUtils;
44 import org.apache.commons.io.FileUtils;
45 import org.apache.commons.io.FilenameUtils;
46 import org.apache.commons.lang3.StringUtils;
47 import org.apache.commons.lang3.time.DateUtils;
48 import org.apache.commons.logging.Log;
49 import org.apache.commons.logging.LogFactory;
50 import org.apache.http.client.CredentialsProvider;
51 import org.apache.http.client.methods.HttpGet;
52 import org.apache.http.client.methods.HttpPost;
53 import org.apache.http.entity.ContentType;
54 import org.apache.http.entity.StringEntity;
55 import org.apache.http.entity.mime.MultipartEntityBuilder;
56 import org.apache.http.impl.client.CloseableHttpClient;
57 import org.apache.http.impl.client.HttpClients;
58 import org.apache.http.protocol.HTTP;
59 import org.nuiton.i18n.I18n;
60 import org.nuiton.jaxx.application.type.ApplicationProgressionModel;
61 import org.nuiton.version.Version;
62 import org.nuiton.version.Versions;
63 import org.springframework.beans.factory.annotation.Autowired;
64 import org.springframework.context.annotation.Lazy;
65 import org.springframework.stereotype.Service;
66
67 import java.io.File;
68 import java.io.IOException;
69 import java.lang.reflect.Type;
70 import java.util.ArrayList;
71 import java.util.Collection;
72 import java.util.List;
73 import java.util.Set;
74
75 import static org.nuiton.i18n.I18n.t;
76
77
78
79
80
81
82
83 @Service("synchroRestClientService")
84 @Lazy
85 public class SynchroRestClientServiceImpl extends RestServiceSupport implements SynchroRestClientService {
86
87 private static final Log log = LogFactory.getLog(SynchroRestClientServiceImpl.class);
88
89 private static final String URL_USER_CURRENT = "/service/user/current";
90 private static final String URL_USER_PROGRAMS = "/service/user/programs";
91 private static final String URL_PROGRAM_GET = "/service/program/get/%s";
92 private final static String URL_CHECK_VERSION = "/service/version/check/%s";
93 private final static String URL_GET_VERSION = "/service/version/get";
94 private final static String URL_IMPORT_CHECK_ANONYMOUSLY = "/service/import/check/anonymous";
95 private final static String URL_IMPORT_CHECK = "/service/import/check";
96 private final static String URL_IMPORT_STATUS = "/service/import/status/%s";
97 private final static String URL_IMPORT_START = "/service/import/start";
98 private final static String URL_IMPORT_START_ANONYMOUSLY = "/service/import/start/anonymous";
99 private final static String URL_IMPORT_STOP = "/service/import/stop/%s";
100 private final static String URL_IMPORT_ACKNOWLEDGE = "/service/import/acknowledge";
101 private static final String URL_EXPORT_UPLOAD = "/service/export/upload";
102 private static final String URL_EXPORT_UPLOAD_POST_PARAM_FILE = "file";
103 private final static String URL_EXPORT_STATUS = "/service/export/status/%s";
104 private final static String URL_EXPORT_START = "/service/export/start";
105 private final static String URL_EXPORT_STOP = "/service/export/stop/%s";
106 private final static String URL_EXPORT_FILES = "/service/export/files/%s";
107 private static final String URL_EXPORT_ACKNOWLEDGE = "/service/export/acknowledge";
108 private static final String URL_PROGRAM_SAVE_LIST = "/service/program/save/list/";
109 private static final String URL_CAMPAIGN_SAVE_LIST = "/service/campaign/save/list/";
110 private static final String URL_CAMPAIGN_DELETE_LIST = "/service/campaign/delete/list/";
111 private static final String URL_RULE_LIST_SAVE_LIST = "/service/ruleList/save/list/";
112 private static final String URL_RULE_LIST_DELETE_LIST = "/service/ruleList/delete/list/";
113
114
115
116
117
118
119
120
121
122 @Autowired
123 public SynchroRestClientServiceImpl(Quadrige2Configuration config) {
124 super(config);
125 }
126
127
128 @Override
129 public CloseableHttpClient getHttpClient(AuthenticationInfo authenticationInfo) {
130
131
132 CredentialsProvider credentialsProvider = getCredentialsProvider(authenticationInfo);
133
134 return HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
135 .setDefaultCredentialsProvider(credentialsProvider).build();
136 }
137
138
139 @Override
140 public QuserVO getUser(AuthenticationInfo authenticationInfo) {
141
142 QuserVO result = null;
143
144 if (log.isDebugEnabled()) {
145 log.debug(String.format("Try to retrieve authenticated user data, from the synchronization server [%s]", getRemoteUrl()));
146 }
147
148
149 CredentialsProvider credentialsProvider = getCredentialsProvider(authenticationInfo);
150
151 try {
152
153 try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
154 .setDefaultCredentialsProvider(credentialsProvider).build()) {
155
156 HttpGet request = new HttpGet(getPathUri(URL_USER_CURRENT));
157 result = HttpHelper.executeRequest(httpClient, request, getGson(), QuserVO.class);
158 }
159 } catch (Quadrige2TechnicalException e) {
160 log.error(I18n.t("quadrige2.error.remote.currentPerson.failed", e.getMessage()), e);
161 throw e;
162 } catch (IOException e) {
163 log.error(I18n.t("quadrige2.error.remote.currentPerson.failed", e.getMessage()), e);
164 throw new Quadrige2TechnicalException(e);
165 }
166
167 return result;
168 }
169
170
171 @Override
172 public List<ProgramVO> getWritableProgramsForUser(AuthenticationInfo authenticationInfo) {
173
174 List<ProgramVO> result = null;
175
176 if (log.isDebugEnabled()) {
177 log.debug(String.format("Try to retrieve programs of authenticated user, from the synchronization server [%s]", getRemoteUrl()));
178 }
179
180
181 CredentialsProvider credentialsProvider = getCredentialsProvider(authenticationInfo);
182
183 try {
184
185 try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
186 .setDefaultCredentialsProvider(credentialsProvider).build()) {
187
188 HttpGet request = new HttpGet(getPathUri(URL_USER_PROGRAMS));
189 Type listType = new TypeToken<ArrayList<ProgramVO>>() {
190 }.getType();
191 result = HttpHelper.executeRequest(httpClient, request, getGson(), listType);
192 }
193 } catch (Quadrige2TechnicalException e) {
194 log.error(I18n.t("quadrige2.error.remote.programs.get.failed", e.getMessage()), e);
195 throw e;
196 } catch (IOException e) {
197 log.error(I18n.t("quadrige2.error.remote.programs.get.failed", e.getMessage()), e);
198 throw new Quadrige2TechnicalException(e);
199 }
200
201 return result;
202 }
203
204
205 @Override
206 public ProgramVO getProgramByCode(AuthenticationInfo authenticationInfo, String progCd) {
207 Preconditions.checkNotNull(progCd);
208
209 if (log.isDebugEnabled()) {
210 log.debug(String.format("Try to retrieve program [%s], from the synchronization server [%s]", progCd, getRemoteUrl()));
211 }
212
213
214 CredentialsProvider credentialsProvider = getCredentialsProvider(authenticationInfo);
215
216 try {
217
218 try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
219 .setDefaultCredentialsProvider(credentialsProvider).build()) {
220
221 HttpGet request = new HttpGet(getPathUri(String.format(URL_PROGRAM_GET, progCd)));
222 return HttpHelper.executeRequest(httpClient, request, getGson(), ProgramVO.class);
223 }
224 } catch (Quadrige2TechnicalException e) {
225 log.error(I18n.t("quadrige2.error.remote.program.get.failed", progCd, e.getMessage()), e);
226 throw e;
227 } catch (IOException e) {
228 log.error(I18n.t("quadrige2.error.remote.program.get.failed", progCd, e.getMessage()), e);
229 throw new Quadrige2TechnicalException(e);
230 }
231 }
232
233
234 @Override
235 public SynchroImportContextVO checkImportContext(AuthenticationInfo authenticationInfo, SynchroImportContextVO importContextVO) {
236 if (log.isDebugEnabled()) {
237 log.debug(String.format("Check if exists referential updates on the synchronization server [%s]", getRemoteUrl()));
238 }
239
240
241 Set<String> programCodes = config.getSynchroProgramCodeIncludes();
242 if (CollectionUtils.isNotEmpty(programCodes)) {
243 importContextVO.setReferentialProgramCodes(programCodes);
244 }
245
246
247
248 if (!importContextVO.isWithData() && !importContextVO.isWithReferential()) {
249 importContextVO.setWithReferential(true);
250 }
251
252
253 CredentialsProvider credentialsProvider = getCredentialsProvider(authenticationInfo);
254 boolean isAnonymous = credentialsProvider == null;
255
256 try {
257
258 try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
259 .setDefaultCredentialsProvider(credentialsProvider)
260 .build()) {
261
262
263 checkVersion(httpClient);
264
265
266 HttpPost request = createHttpPostWithStringEntity(isAnonymous ? URL_IMPORT_CHECK_ANONYMOUSLY : URL_IMPORT_CHECK, importContextVO);
267
268
269 return HttpHelper.executeRequest(httpClient, request, getGson(), SynchroImportContextVO.class);
270 }
271 } catch (Quadrige2TechnicalException e) {
272 log.error(I18n.t("quadrige2.error.remote.checkImportContext.failed", e.getMessage()), e);
273 throw e;
274 } catch (IOException e) {
275 log.error(I18n.t("quadrige2.error.remote.checkImportContext.failed", e.getMessage()), e);
276 throw new Quadrige2TechnicalException(e);
277 }
278 }
279
280
281 @Override
282 public void checkVersion(AuthenticationInfo authenticationInfo) {
283
284
285 CredentialsProvider credentialsProvider = getCredentialsProvider(authenticationInfo);
286
287 try {
288
289 try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
290 .setDefaultCredentialsProvider(credentialsProvider).build()) {
291
292
293 checkVersion(httpClient);
294 }
295
296 } catch (Quadrige2TechnicalException e) {
297 log.error(t("quadrige2.error.remote.checkVersion.failed", e.getMessage()), e);
298 throw e;
299 } catch (IOException e) {
300 log.error(t("quadrige2.error.remote.checkVersion.failed", e.getMessage()), e);
301 throw new Quadrige2TechnicalException(e);
302 }
303 }
304
305
306 @Override
307 public void checkVersion(CloseableHttpClient httpClient) {
308
309
310 Version localVersionToCheck = Quadrige2Configuration.getInstance().getVersion();
311
312 if (log.isDebugEnabled()) {
313 log.debug(String.format("Checking if version [%s] is compatible with the synchronization server [%s]", localVersionToCheck.getVersion(),
314 getRemoteUrl()));
315 }
316
317
318 HttpGet request = new HttpGet(getPathUri(String.format(URL_CHECK_VERSION, localVersionToCheck.getVersion())));
319 String isVersionAllowedStr = HttpHelper.executeRequest(httpClient, request, getGson(), String.class);
320 boolean isVersionAllowed = Boolean.valueOf(isVersionAllowedStr);
321
322
323 if (!isVersionAllowed) {
324
325
326 request = new HttpGet(getPathUri(URL_GET_VERSION));
327 String serverVersionStr = HttpHelper.executeRequest(httpClient, request, getGson(), String.class);
328 Version serverVersion = null;
329 if (StringUtils.isNotBlank(serverVersionStr)) {
330 serverVersion = Versions.valueOf(serverVersionStr.replaceAll("\\\"", ""));
331 }
332
333
334 throw new Quadrige2BusinessException(I18n.t("quadrige2.error.synchro.version", localVersionToCheck, serverVersion));
335 }
336 }
337
338
339 @Override
340 public SynchroProgressionVO startImport(AuthenticationInfo authenticationInfo,
341 SynchroImportContextVO importContextVO,
342 ApplicationProgressionModel progressionModel) throws Exception {
343 Preconditions.checkNotNull(importContextVO);
344
345 int refreshTimeout = config.getSynchronizationRefreshTimeout();
346 String jobId = importContextVO.getJobId();
347 boolean previouslyLaunched = jobId != null;
348
349
350 CredentialsProvider credentialsProvider = getCredentialsProvider(authenticationInfo);
351 boolean isAnonymous = credentialsProvider == null;
352
353 try {
354
355 try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
356 .setDefaultCredentialsProvider(credentialsProvider)
357 .build()) {
358
359 progressionModel.setMessage(t("quadrige2.synchro.progress.start"));
360
361
362 checkVersion(httpClient);
363
364 if (!previouslyLaunched) {
365
366 HttpPost request = createHttpPostWithStringEntity(isAnonymous ? URL_IMPORT_START_ANONYMOUSLY : URL_IMPORT_START, importContextVO);
367
368
369 SynchroImportContextVO resultImportContextVO = HttpHelper.executeRequest(httpClient, request, getGson(),
370 SynchroImportContextVO.class);
371 jobId = resultImportContextVO.getJobId();
372
373
374 importContextVO.setJobId(jobId);
375 }
376
377
378 Thread.sleep(refreshTimeout);
379
380 return getImportLastStatus(httpClient, jobId, progressionModel);
381 }
382 } catch (Quadrige2TechnicalException e) {
383 log.error(I18n.t("quadrige2.error.remote.startImport.failed", e.getMessage()), e);
384 throw e;
385 } catch (IOException e) {
386 log.error(I18n.t("quadrige2.error.remote.startImport.failed", e.getMessage()), e);
387 throw new Quadrige2TechnicalException(e);
388 }
389 }
390
391
392 @Override
393 public void stopImport(AuthenticationInfo authenticationInfo,
394 String importJobId) throws Exception {
395 if (log.isDebugEnabled()) {
396 log.debug(String.format("try to stop synchronization job [%s] on servers", importJobId));
397 }
398
399
400 CredentialsProvider credentialsProvider = getCredentialsProvider(authenticationInfo);
401
402
403 try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
404 .setDefaultCredentialsProvider(credentialsProvider)
405 .build()) {
406
407
408 HttpGet request = new HttpGet(getPathUri(String.format(URL_IMPORT_STOP, importJobId)));
409
410
411 HttpHelper.executeRequest(httpClient, request);
412
413 }
414 }
415
416
417 @Override
418 public void acknowledgeImport(AuthenticationInfo authenticationInfo, SynchroImportContextVO importContextVO) throws Quadrige2TechnicalException {
419
420 if (log.isDebugEnabled()) {
421 log.debug(String.format("Sending import acknowledge to the synchronization server [%s]", getRemoteUrl()));
422 }
423
424
425 if (importContextVO.getReferentialUpdateDate() != null) {
426 importContextVO = (SynchroImportContextVO) importContextVO.clone();
427 importContextVO.setReferentialUpdateDate(
428 DateUtils.addSeconds(importContextVO.getReferentialUpdateDate(),
429 -1 * config.getImportReferentialUpdateDateOffsetInSecond()));
430 }
431
432
433 CredentialsProvider credentialsProvider = getCredentialsProvider(authenticationInfo);
434
435 try {
436
437 try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
438 .setDefaultCredentialsProvider(credentialsProvider).build()) {
439
440
441 HttpPost request = createHttpPostWithStringEntity(URL_IMPORT_ACKNOWLEDGE, importContextVO);
442
443
444 HttpHelper.executeRequest(httpClient, request);
445 }
446 } catch (Quadrige2TechnicalException e) {
447 log.error(I18n.t("quadrige2.error.remote.acknowledgeImport.failed", e.getMessage()), e);
448
449 } catch (IOException e) {
450 log.error(I18n.t("quadrige2.error.remote.acknowledgeImport.failed", e.getMessage()), e);
451 throw new Quadrige2TechnicalException(e);
452 }
453 }
454
455
456 @Override
457 public void uploadExportFile(AuthenticationInfo authenticationInfo, File fileToUpload, ApplicationProgressionModel progressionModel)
458 throws Quadrige2TechnicalException {
459
460 if (!fileToUpload.exists()) {
461 throw new Quadrige2BusinessException(I18n.t("quadrige2.error.file.not.exists", fileToUpload.getAbsolutePath()));
462 }
463
464 if (log.isDebugEnabled()) {
465 log.debug(String.format("file to transfert to server: %s", fileToUpload.getAbsolutePath()));
466 }
467
468
469 CredentialsProvider credentialsProvider = getCredentialsProvider(authenticationInfo);
470
471 try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
472 .setDefaultCredentialsProvider(credentialsProvider)
473 .build()) {
474
475
476 HttpPost uploadHttpPost = new HttpPost(getPathUri(URL_EXPORT_UPLOAD));
477
478
479 MultipartEntityBuilder builder = MultipartEntityBuilder.create();
480
481 builder.addPart(URL_EXPORT_UPLOAD_POST_PARAM_FILE, new ProgressFileBody(fileToUpload, progressionModel));
482
483 uploadHttpPost.setEntity(builder.build());
484
485 uploadHttpPost.addHeader(HTTP.EXPECT_DIRECTIVE, HTTP.EXPECT_CONTINUE);
486
487
488 HttpHelper.executeRequest(httpClient, uploadHttpPost);
489
490 } catch (Quadrige2TechnicalException e) {
491 log.error(I18n.t("quadrige2.error.remote.upload.failed", e.getMessage()), e);
492 throw e;
493 } catch (IOException e) {
494 log.error(I18n.t("quadrige2.error.remote.upload.failed", e.getMessage()), e);
495 throw new Quadrige2TechnicalException(e);
496 }
497 }
498
499
500 @Override
501 public SynchroProgressionVO startExport(AuthenticationInfo authenticationInfo,
502 SynchroExportContextVO exportContextVO,
503 ApplicationProgressionModel progressionModel) throws Exception {
504 Preconditions.checkNotNull(exportContextVO);
505
506
507 CredentialsProvider credentialsProvider = getCredentialsProvider(authenticationInfo);
508
509 try {
510
511 try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
512 .setDefaultCredentialsProvider(credentialsProvider)
513 .build()) {
514
515 progressionModel.setMessage(t("quadrige2.synchro.progress.start"));
516
517
518 checkVersion(httpClient);
519
520
521 HttpPost request = createHttpPostWithStringEntity(URL_EXPORT_START, exportContextVO);
522
523
524 SynchroProgressionVO result = HttpHelper.executeRequest(httpClient, request, getGson(), SynchroProgressionVO.class);
525
526 progressionModel.setMessage(result.getMessage());
527 progressionModel.setCurrent(result.getIncrement());
528
529 return result;
530 }
531 }
532 catch(Quadrige2TechnicalException e) {
533 throw e;
534 }
535 catch(Throwable e) {
536 throw new Quadrige2TechnicalException(e);
537 }
538 }
539
540
541 @Override
542 public void stopExport(AuthenticationInfo authenticationInfo,
543 String exportJobId) throws Exception {
544
545
546 CredentialsProvider credentialsProvider = getCredentialsProvider(authenticationInfo);
547
548
549 try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
550 .setDefaultCredentialsProvider(credentialsProvider)
551 .build()) {
552
553 HttpGet request = new HttpGet(getPathUri(String.format(URL_EXPORT_STOP, exportJobId)));
554
555
556 HttpHelper.executeRequest(httpClient, request);
557
558 }
559 }
560
561
562 @Override
563 public SynchroResult downloadExportResult(AuthenticationInfo authenticationInfo,
564 SynchroExportContextVO context,
565 ApplicationProgressionModel progressionModel) throws Exception {
566 File exportDir = config.getTempDirectory();
567 FileUtils.forceMkdir(exportDir);
568 String fileName = FilenameUtils.getBaseName(context.getFileName()) + ".json";
569 File downloadedFile = new File(exportDir, fileName);
570
571 CredentialsProvider credentialsProvider = getCredentialsProvider(authenticationInfo);
572
573 try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
574 .setDefaultCredentialsProvider(credentialsProvider)
575 .build()) {
576
577 progressionModel.setMessage(t("quadrige2.synchro.progress.download"));
578
579
580 HttpGet downloadHttpGet = new HttpGet(getPathUri(String.format(URL_EXPORT_FILES, fileName)));
581 HttpHelper.executeDownloadFileRequest(httpClient, downloadHttpGet, progressionModel, downloadedFile);
582 }
583
584 SynchroResult result = null;
585
586 if (downloadedFile.exists()) {
587 result = Gsons.deserializeFile(downloadedFile, SynchroResult.class);
588 FileUtils.deleteQuietly(downloadedFile);
589
590 if (result == null) {
591 throw new Quadrige2TechnicalException(t("quadrige2.error.synchro.export.resultFile.read", downloadedFile.getAbsolutePath()));
592 }
593 }
594
595 return result;
596 }
597
598
599 @Override
600 public void acknowledgeExport(AuthenticationInfo authenticationInfo, SynchroExportContextVO context) throws Exception {
601
602 try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
603 .setDefaultCredentialsProvider(getCredentialsProvider(authenticationInfo))
604 .build()) {
605
606
607 checkVersion(httpClient);
608
609
610 HttpPost startHttpPost = createHttpPostWithStringEntity(URL_EXPORT_ACKNOWLEDGE, context);
611
612 HttpHelper.executeRequest(httpClient, startHttpPost);
613
614 } catch (Quadrige2TechnicalException e) {
615 log.error(I18n.t("quadrige2.error.remote.acknowledgeExport.failed", e.getMessage()), e);
616
617 } catch (IOException e) {
618 log.error(I18n.t("quadrige2.error.remote.acknowledgeExport.failed", e.getMessage()), e);
619 throw new Quadrige2TechnicalException(e);
620 }
621 }
622
623
624 @Override
625 public List<ProgramVO> savePrograms(AuthenticationInfo authenticationInfo, List<ProgramVO> programs) {
626 return executeRemoteUpdateTyped(
627 URL_PROGRAM_SAVE_LIST,
628 I18n.t("quadrige2.error.remote.programs.save"),
629 authenticationInfo,
630 programs,
631 new TypeToken<ArrayList<ProgramVO>>() {},
632 true);
633 }
634
635
636 @Override
637 public List<CampaignVO> saveCampaigns(AuthenticationInfo authenticationInfo, Collection<CampaignVO> campaigns) {
638 return executeRemoteUpdateTyped(
639 URL_CAMPAIGN_SAVE_LIST,
640 I18n.t("quadrige2.error.remote.campaigns.save"),
641 authenticationInfo,
642 campaigns,
643 new TypeToken<ArrayList<CampaignVO>>() {},
644 true);
645 }
646
647 @Override
648 public void deleteCampaigns(AuthenticationInfo authenticationInfo, Collection<Integer> campaignIds) {
649 executeRemoteUpdate(URL_CAMPAIGN_DELETE_LIST,
650 I18n.t("quadrige2.error.remote.campaigns.delete"),
651 authenticationInfo,
652 campaignIds);
653 }
654
655 @Override
656 public List<RuleListVO> saveRuleLists(AuthenticationInfo authenticationInfo, Collection<RuleListVO> ruleLists) {
657 return executeRemoteUpdateTyped(
658 URL_RULE_LIST_SAVE_LIST,
659 I18n.t("quadrige2.error.remote.ruleLists.save"),
660 authenticationInfo,
661 ruleLists,
662 new TypeToken<ArrayList<RuleListVO>>() {},
663 true);
664 }
665
666 @Override
667 public void deleteRuleLists(AuthenticationInfo authenticationInfo, Collection<String> ruleListCds) {
668 executeRemoteUpdate(URL_RULE_LIST_DELETE_LIST,
669 I18n.t("quadrige2.error.remote.ruleLists.delete"),
670 authenticationInfo,
671 ruleListCds);
672 }
673
674 @Override
675 public SynchroProgressionVO getExportLastStatus(AuthenticationInfo authenticationInfo,
676 String exportJobId,
677 ApplicationProgressionModel progressionModel) throws Exception {
678
679 CredentialsProvider credentialsProvider = getCredentialsProvider(authenticationInfo);
680
681
682 try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
683 .setDefaultCredentialsProvider(credentialsProvider)
684 .build()) {
685 return getExportLastStatus(httpClient, exportJobId, progressionModel);
686 }
687 catch(Quadrige2TechnicalException e) {
688 throw e;
689 }
690 catch(Exception e) {
691 throw new Quadrige2TechnicalException(e);
692 }
693 }
694
695
696
697
698
699
700
701
702
703
704
705
706 protected final boolean isRunningStatus(SynchroProgressionStatus status) {
707 return status == SynchroProgressionStatus.RUNNING
708 || status == SynchroProgressionStatus.WAITING_EXECUTION;
709 }
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726 protected SynchroProgressionVO getImportLastStatus(CloseableHttpClient httpClient,
727 String importJobId,
728 ApplicationProgressionModel progressionModel) throws Exception {
729 SynchroProgressionVO result = null;
730 int refreshTimeout = config.getSynchronizationRefreshTimeout();
731
732 try {
733 HttpGet request = new HttpGet(getPathUri(String.format(URL_IMPORT_STATUS, importJobId)));
734
735 progressionModel.setTotal(100);
736
737 SynchroProgressionStatus status = null;
738 String filename = null;
739 while (status == null || isRunningStatus(status)) {
740
741
742 result = HttpHelper.executeRequest(httpClient, request, getGson(), SynchroProgressionVO.class);
743
744
745 if (filename == null && StringUtils.isNotBlank(result.getFileName())) {
746 filename = result.getFileName();
747 }
748
749 status = SynchroProgressionStatus.valueOf(result.getStatus());
750
751
752 progressionModel.setMessage(result.getMessage());
753 progressionModel.setCurrent(result.getIncrement());
754
755
756 Thread.sleep(refreshTimeout);
757 }
758
759
760 result.setFileName(filename);
761
762 return result;
763 } catch (Quadrige2TechnicalException e) {
764 log.error(I18n.t("quadrige2.error.remote.import.status.failed", e.getMessage()), e);
765 throw e;
766 }
767 }
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784 protected SynchroProgressionVO getExportLastStatus(CloseableHttpClient httpClient,
785 String exportJobId,
786 ApplicationProgressionModel progressionModel) throws Exception {
787 SynchroProgressionVO result = null;
788 int refreshTimeout = config.getSynchronizationRefreshTimeout();
789
790 try {
791 HttpGet request = new HttpGet(getPathUri(String.format(URL_EXPORT_STATUS, exportJobId)));
792
793 progressionModel.setTotal(100);
794
795 SynchroProgressionStatus status = null;
796 while (status == null || isRunningStatus(status)) {
797
798
799 result = HttpHelper.executeRequest(httpClient, request, getGson(), SynchroProgressionVO.class);
800
801 status = SynchroProgressionStatus.valueOf(result.getStatus());
802
803
804 progressionModel.setMessage(result.getMessage());
805 progressionModel.setCurrent(result.getIncrement());
806
807
808 Thread.sleep(refreshTimeout);
809 }
810
811 return result;
812 } catch (Quadrige2TechnicalException e) {
813 log.error(I18n.t("quadrige2.error.remote.export.status.failed", e.getMessage()), e);
814 throw e;
815 }
816 }
817
818 protected <R> List<R> executeRemoteUpdateTyped(
819 final String postPath,
820 final String errorMessagePrefix,
821 AuthenticationInfo authenticationInfo,
822 Object data,
823 TypeToken<? extends List<R>> typeToken,
824 boolean checkNotEmptyResult) {
825
826 List<R> result = executeRemoteUpdate(
827 postPath,
828 errorMessagePrefix,
829 authenticationInfo,
830 data,
831 typeToken.getType()
832 );
833
834 if (checkNotEmptyResult && CollectionUtils.isEmpty(result)) {
835 log.error(errorMessagePrefix + " " + I18n.t("quadrige2.error.remote.update.emptyResponse"));
836 throw new Quadrige2TechnicalException(errorMessagePrefix + " " + I18n.t("quadrige2.error.remote.update.emptyResponse"));
837 }
838
839 return result;
840
841 }
842
843 protected void executeRemoteUpdate(
844 final String postPath,
845 final String logMessagePrefix,
846 AuthenticationInfo authenticationInfo,
847 Object data) {
848
849 executeRemoteUpdate(postPath, logMessagePrefix, authenticationInfo, data, null);
850 }
851
852 protected <T> T executeRemoteUpdate(
853 final String postPath,
854 final String errorMessagePrefix,
855 AuthenticationInfo authenticationInfo,
856 Object data,
857 Type resultType
858 ) {
859
860
861 try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(getRequestConfig())
862 .setDefaultCredentialsProvider(getCredentialsProvider(authenticationInfo))
863 .build()) {
864
865
866 checkVersion(httpClient);
867
868
869 HttpPost request = createHttpPostWithStringEntity(postPath, data);
870
871
872 return HttpHelper.executeRequest(httpClient, request, getGson(), resultType);
873
874 } catch (BadUpdateDtException e) {
875 throw new Quadrige2BusinessException(errorMessagePrefix + " " + I18n.t("quadrige2.error.remote.update.badUpdateDate", e.getMessage()));
876 } catch (DataLockedException e) {
877 throw new Quadrige2BusinessException(errorMessagePrefix + " " + I18n.t("quadrige2.error.remote.update.dataLocked"));
878 } catch (DeleteForbiddenException e) {
879
880 throw e;
881 } catch (Quadrige2TechnicalException|IOException e) {
882 log.error(errorMessagePrefix + " " + I18n.t("quadrige2.error.remote.update.failed", e.getMessage()), e);
883 throw new Quadrige2TechnicalException(errorMessagePrefix + " " + I18n.t("quadrige2.error.remote.update.failed", e.getMessage()), e);
884 }
885 }
886
887 protected HttpPost createHttpPostWithStringEntity(
888 final String postPath,
889 Object data) throws DataLockedException {
890
891 HttpPost request = new HttpPost(getPathUri(postPath));
892 StringEntity entity = new StringEntity(getGson().toJson(data), ContentType.APPLICATION_JSON);
893 request.setEntity(entity);
894
895 return request;
896
897 }
898
899 }