Sonar +
[platform/core/security/suspicious-activity-monitor.git] / servers / commons / src / main / java / com / samsung / commons / utils / sync / Synchronous.java
1 package com.samsung.commons.utils.sync;
2
3 import org.apache.log4j.Logger;
4
5 import java.util.Optional;
6
7 import static java.util.Optional.empty;
8 import static java.util.Optional.ofNullable;
9
10 /**
11  * Makes synchronous call
12  *
13  * @param <T> return type
14  */
15 public class Synchronous<T> {
16
17     private final Logger log = Logger.getLogger(Synchronous.class);
18
19     // Default timeout (ms)
20     private static final int DEFAULT_TIMEOUT = 1000;
21
22     // Default maximum rounds
23     private static final int DEFAULT_MAX_ROUNDS = 10;
24
25     private final Object lock = new Object();
26
27     private boolean firstTime = true;
28
29     // How long to wait before the next try
30     private int timeout = DEFAULT_TIMEOUT;
31
32     // Max tries before exit
33     private int maxRounds = DEFAULT_MAX_ROUNDS;
34
35     // Result
36     private T result;
37
38     // Is call finished
39     private boolean finished = false;
40
41     /**
42      * Constructor
43      *
44      * @param maxRounds max rounds
45      * @param timeout   timeout
46      */
47     public Synchronous(int maxRounds, int timeout) {
48         this.maxRounds = maxRounds;
49         this.timeout = timeout;
50     }
51
52     /**
53      * Create with parameters
54      *
55      * @param maxRounds max rounds
56      * @param timeout   timeout
57      * @param <T>       result
58      * @return this
59      */
60     public static <T> Synchronous<T> withParams(int maxRounds, int timeout) {
61         return new Synchronous<>(maxRounds, timeout);
62     }
63
64     /**
65      * On success call
66      *
67      * @param result result
68      */
69     void success(T result) {
70         log.trace("Result getting succeeded");
71
72         this.finished = true;
73         this.result = result;
74     }
75
76     /**
77      * On fail call
78      */
79     void fail() {
80         log.trace("Result getting failed");
81
82         this.finished = true;
83     }
84
85     /**
86      * Execute async code
87      *
88      * @param asyncCode async code
89      * @return result
90      */
91     public Optional<T> execute(AsyncCode<T> asyncCode) {
92
93         if (!firstTime) {
94             log.error("Already executed. Create new Synchronous and execute again.");
95
96             return empty();
97         }
98
99         firstTime = false;
100
101         try {
102             synchronized (lock) {
103                 finished = false;
104
105                 // Execute code
106                 try {
107                     ResultCallback<T> resultCallback = new ResultCallback<>(this);
108
109                     asyncCode.async(resultCallback);
110
111                 } catch (Exception e) {
112                     log.error("Error on running asynchronous code. Return empty.", e);
113
114                     return empty();
115                 }
116
117                 // Wait for result
118                 int rounds = 0;
119                 while (!finished) {
120                     lock.wait(timeout);
121                     rounds++;
122
123                     if (this.maxRounds == rounds) {
124                         log.debug("Max rounds exceeded. " +
125                                 "Check finished() method invocation after async code has been finished.");
126                         break;
127                     }
128                 }
129
130                 return ofNullable(this.result);
131             }
132
133         } catch (InterruptedException e) {
134             log.error("Interrupted. Return empty.");
135
136             return empty();
137         }
138     }
139 }