Update package name to onap namespace
[appc.git] / appc-sdc-listener / appc-sdc-listener-bundle / src / main / java / org / onap / appc / sdc / listener / SdcListener.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Copyright (C) 2017 Amdocs
8  * =============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  * 
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  * 
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * 
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  * ============LICENSE_END=========================================================
23  */
24
25 package org.onap.appc.sdc.listener;
26
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29 import org.onap.appc.configuration.Configuration;
30 import org.onap.appc.configuration.ConfigurationFactory;
31 import org.openecomp.sdc.api.IDistributionClient;
32 import org.openecomp.sdc.api.results.IDistributionClientResult;
33 import org.openecomp.sdc.impl.DistributionClientFactory;
34 import org.openecomp.sdc.utils.DistributionActionResultEnum;
35
36 import java.net.URL;
37 import java.util.HashMap;
38 import java.util.Map;
39 import java.util.Properties;
40 import java.util.concurrent.CountDownLatch;
41 import java.util.concurrent.TimeUnit;
42
43 /**
44  * SDC listener handles bundle start and stop through start and stop method. <p>
45  * Register connection with SDC server based on properties file configuration when start,
46  * and disconnect with SDC server when stop.
47  */
48 public class SdcListener {
49     private final EELFLogger logger = EELFManager.getInstance().getLogger(SdcListener.class);
50
51     /**
52      * The bundle context
53      */
54     private IDistributionClient client;
55     private SdcCallback callback;
56     private SdcConfig config;
57     private CountDownLatch latch;
58
59     private Thread startThread = null;
60
61     @SuppressWarnings("unused")
62     public void start() throws Exception {
63         // Add timestamp to the log to differentiate the jmeter run testing calls.
64         final long timeStamp = System.currentTimeMillis();
65         logger.info(String.format("[%d] Starting SDC Listener", timeStamp));
66
67         Configuration configuration = ConfigurationFactory.getConfiguration();
68         Properties props = configuration.getProperties();
69         config = new SdcConfig(props);
70         logger.debug(String.format("[%d] created SDC config", timeStamp));
71
72         client = DistributionClientFactory.createDistributionClient();
73         logger.debug(String.format("[%d] created SDC client", timeStamp));
74
75         callback = new SdcCallback(config.getStoreOpURI(), client);
76         logger.debug(String.format("[%d] created SDC callback", timeStamp));
77
78         latch = new CountDownLatch(1);
79
80         startThread = new Thread(new StartRunnable(timeStamp));
81         startThread.setName(String.format("[%d] sdcListener start", timeStamp));
82         logger.debug(String.format("[%d] created SDC initialization thread", timeStamp));
83         startThread.start();
84     }
85
86     @SuppressWarnings("unused")
87     public void stop() throws InterruptedException {
88         // Add timestamp to the log to differentiate the jmeter run testing calls.
89         final long timeStamp = System.currentTimeMillis();
90         logger.info(String.format("[%d] Stopping SDC Listener", timeStamp));
91
92         stopStartThread(timeStamp);
93
94         if (latch != null) {
95             logger.debug(String.format("[%d] waiting SDC latch count to 0 for 10 seconds", timeStamp));
96             latch.await(10, TimeUnit.SECONDS);
97             latch = null;
98         }
99
100         if (callback != null) {
101             logger.debug(String.format("[%d] stopping SDC callback", timeStamp));
102             callback.stop();
103             callback = null;
104         }
105         if (client != null) {
106             logger.debug(String.format("[%d] stopping SDC client", timeStamp));
107             client.stop();
108             client = null;
109
110         }
111         logger.info(String.format("[%d] SDC Listener stopped successfully", timeStamp));
112     }
113
114     void stopStartThread(long timeStamp) throws InterruptedException {
115         if (startThread == null) {
116             return;
117         }
118
119         if (startThread.getState() == Thread.State.TERMINATED) {
120             logger.debug(String.format("[%d] SDC thread(%s) is already terminated.",
121                     timeStamp, startThread.getName()));
122         } else {
123             logger.debug(String.format("[%d] SDC thread(%s) is to be interrupted with state(%s)",
124                     timeStamp, startThread.getName(), startThread.getState().toString()));
125
126             startThread.interrupt();
127
128             logger.debug(String.format("[%d] SDC thread(%s) has been interrupted(%s) with state(%s)",
129                     timeStamp, startThread.getName(), startThread.isInterrupted(),
130                     startThread.getState().toString()));
131         }
132         startThread = null;
133     }
134
135     /**
136      * Runnable implementation for actual initialization during SDC listener start
137      */
138     class StartRunnable implements Runnable {
139         private final long timeStamp;
140
141         StartRunnable(long theTimeStamp) {
142             timeStamp = theTimeStamp;
143         }
144
145         /**
146          * This run method calls SDC client for init and start which are synchronized calls along with stop.
147          * To interrupt this thread at stop time, we added thread interrupted checking in each step
148          * for earlier interruption.
149          */
150         @Override
151         public void run() {
152             if (!initialRegistration()) {
153                 logger.warn(String.format("[%d] SDC thread initial registration failed.", timeStamp));
154             }
155
156             if (isThreadInterrupted("after initial registration")) {
157                 return;
158             }
159
160             IDistributionClientResult result = client.init(config, callback);
161
162             if (isThreadInterrupted("after client init")) {
163                 return;
164             }
165
166             if (result.getDistributionActionResult() == DistributionActionResultEnum.SUCCESS) {
167                 client.start();
168             } else {
169                 logger.error(String.format("[%d] Could not register SDC client. %s - %s",
170                         timeStamp, result.getDistributionActionResult(), result.getDistributionMessageResult()));
171             }
172
173             latch.countDown();
174         }
175
176         private boolean initialRegistration() {
177             try {
178                 final String jsonTemplate =
179                         "{\"consumerName\": \"%s\",\"consumerSalt\": \"%s\",\"consumerPassword\":\"%s\"}";
180                 String saltedPassStr = org.onap.tlv.sdc.security.Passwords.hashPassword(config.getPassword());
181                 if (saltedPassStr == null || !saltedPassStr.contains(":")) {
182                     return false;
183                 }
184
185                 String[] saltedPass = saltedPassStr.split(":");
186                 String json = String.format(jsonTemplate, config.getUser(), saltedPass[0], saltedPass[1]);
187
188                 Map<String, String> headers = new HashMap<>();
189                 // TODO - Replace the header below to sdc's requirements. What should the new value be
190                 headers.put("USER_ID", "test");
191
192                 // TODO - How to format the url. Always same endpoint or ports?
193                 String host = config.getAsdcAddress();
194                 URL url = new URL(String.format("http%s://%s/sdc2/rest/v1/consumers",
195                         host.contains("443") ? "s" : "", host));
196
197                 logger.info(String.format("Attempting to register user %s on %s with salted pass of %s",
198                         config.getUser(), url, saltedPass[1]));
199
200                 ProviderOperations providerOperations = new ProviderOperations();
201                 ProviderResponse result = providerOperations.post(url, json, headers);
202                 return result.getStatus() == 200;
203             } catch (Exception e) {
204                 logger.error(
205                         "Error performing initial registration with SDC server. User may not be able to connect",
206                         e);
207                 return false;
208             }
209         }
210
211         private boolean isThreadInterrupted(String details) {
212             if (Thread.currentThread().isInterrupted()) {
213                 logger.info(String.format("[%d] SDC thread interrupted %s.", timeStamp, details));
214                 return true;
215             }
216             return false;
217         }
218     }
219 }