Fix for APPC-1286
[appc.git] / appc-oam / appc-oam-bundle / src / main / java / org / onap / appc / oam / processor / BaseCommon.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Copyright (C) 2017 Amdocs
8  * ================================================================================
9  * Modifications (C) 2018 Ericsson
10  * =============================================================================
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  * 
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  * 
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  * 
23  * ============LICENSE_END=========================================================
24  */
25
26 package org.onap.appc.oam.processor;
27
28 import com.att.eelf.configuration.EELFLogger;
29 import com.att.eelf.i18n.EELFResourceManager;
30 import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.common.header.CommonHeader;
31 import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.status.Status;
32 import org.opendaylight.yang.gen.v1.org.onap.appc.oam.rev170303.status.StatusBuilder;
33 import org.onap.appc.exceptions.InvalidInputException;
34 import org.onap.appc.exceptions.InvalidStateException;
35 import org.onap.appc.executor.objects.Params;
36 import org.onap.appc.i18n.Msg;
37 import org.onap.appc.logging.LoggingConstants;
38 import org.onap.appc.logging.LoggingUtils;
39 import org.onap.appc.oam.AppcOam;
40 import org.onap.appc.oam.OAMCommandStatus;
41 import org.onap.appc.oam.util.ConfigurationHelper;
42 import org.onap.appc.oam.util.OperationHelper;
43 import org.onap.appc.oam.util.StateHelper;
44 import org.slf4j.MDC;
45
46 import java.net.InetAddress;
47 import java.net.UnknownHostException;
48 import java.time.Instant;
49 import java.util.Arrays;
50 import java.util.Date;
51 import java.util.HashMap;
52 import java.util.List;
53 import java.util.Map;
54 import java.util.concurrent.TimeoutException;
55
56 import static com.att.eelf.configuration.Configuration.MDC_INSTANCE_UUID;
57 import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
58 import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
59 import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS;
60 import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
61
62 /**
63  * Common handling methods of <br>
64  *     - BaseProcessor (for REST sync handling) <br>
65  *     - BaseActionRunnable (for REST async handling)
66  */
67 public abstract class BaseCommon {
68     final EELFLogger logger;
69     final ConfigurationHelper configurationHelper;
70     final StateHelper stateHelper;
71     final OperationHelper operationHelper;
72
73     Status status;
74     Date startTime;
75
76     AppcOam.RPC rpc;
77     CommonHeader commonHeader;
78
79     private final List<String> MDC_KEYS = Arrays.asList(
80         LoggingConstants.MDCKeys.PARTNER_NAME,
81         LoggingConstants.MDCKeys.SERVER_NAME,
82         MDC_INSTANCE_UUID,
83         MDC_KEY_REQUEST_ID,
84         MDC_SERVER_FQDN,
85         MDC_SERVER_IP_ADDRESS,
86         MDC_SERVICE_NAME
87     );
88     private Map<String, String> oldMdcContent = new HashMap<>();
89
90     /**
91      * Constructor
92      *
93      * @param eelfLogger            for logging
94      * @param configurationHelperIn for property reading
95      * @param stateHelperIn         for APP-C OAM state checking
96      * @param operationHelperIn for operational helper
97      */
98     BaseCommon(EELFLogger eelfLogger,
99                ConfigurationHelper configurationHelperIn,
100                StateHelper stateHelperIn,
101                OperationHelper operationHelperIn) {
102         logger = eelfLogger;
103         configurationHelper = configurationHelperIn;
104         stateHelper = stateHelperIn;
105         operationHelper = operationHelperIn;
106     }
107
108     /**
109      * Audit log the passed in message at INFO level.
110      * @param msg the Msg to be audit logged.
111      */
112     void auditInfoLog(Msg msg) {
113         LoggingUtils.auditInfo(startTime.toInstant(),
114             Instant.now(),
115             String.valueOf(status.getCode()),
116             status.getMessage(),
117             getClass().getCanonicalName(),
118             msg,
119             configurationHelper.getAppcName(),
120             stateHelper.getCurrentOamState().toString()
121         );
122     }
123
124     /**
125      * Set MDC properties.
126      */
127     public final void setInitialLogProperties() {
128         MDC.put(MDC_KEY_REQUEST_ID, commonHeader.getRequestId());
129         MDC.put(LoggingConstants.MDCKeys.PARTNER_NAME, commonHeader.getOriginatorId());
130         MDC.put(MDC_INSTANCE_UUID, ""); // value should be created in the future
131         MDC.put(MDC_SERVICE_NAME, rpc.name());
132         try {
133             //!!!Don't change the following to a .getHostName() again please. It's wrong!MDC.put(MDC_SERVER_FQDN,
134             // InetAddress.getLocalHost().getCanonicalHostName());
135             MDC.put(MDC_SERVER_FQDN, getHostInfo("canonicalHostName"));
136             MDC.put(MDC_SERVER_IP_ADDRESS, getHostInfo("hostName"));
137             MDC.put(LoggingConstants.MDCKeys.SERVER_NAME, getHostInfo("hostName"));
138         } catch (Exception e) {
139             logger.error("MDC constant error", e);
140         }
141     }
142
143     /**
144      * Clear MDC properties.
145      */
146     public final void clearRequestLogProperties() {
147         for (String key : MDC_KEYS) {
148             try {
149                 MDC.remove(key);
150             } catch (Exception e) {
151                 logger.error(
152                     String.format("Unable to clear the Log properties (%s) due to exception: %s", key, e.getMessage()));
153             }
154         }
155     }
156
157     /**
158      * Reset MDC log properties based on passed in condition. does:<br>
159      *   - persist existing MDC setting and set my MDC log properties <br>
160      *   - or re-apply persisted MDC log properties
161      * @param useMdcMap boolean to indicate whether to persist the existing MDC setting and set my MDC log properties,
162      *                  or to re-apply the persisted MDC log properties.
163      */
164     void resetLogProperties(boolean useMdcMap) {
165         if (useMdcMap) {
166             for (Map.Entry<String, String> aEntry : oldMdcContent.entrySet()) {
167                 MDC.put(aEntry.getKey(), aEntry.getValue());
168             }
169             return;
170         }
171
172         // persist existing log properties and set my log properties
173         oldMdcContent.clear();
174         for (String key : MDC_KEYS) {
175             String value = MDC.get(key);
176             if (value != null) {
177                 oldMdcContent.put(key, value);
178             }
179         }
180         setInitialLogProperties();
181     }
182
183     /**
184      * Set class <b>status</b> by calling setStatus(OAMCommandStatus, Params) with null paramter.
185      * @see #setStatus(OAMCommandStatus, String)
186      *
187      * @param oamCommandStatus of the to be set new state
188      */
189     void setStatus(OAMCommandStatus oamCommandStatus) {
190         setStatus(oamCommandStatus, null);
191     }
192
193     /**
194      * Create Status based on the passed in parameter, then set the class <b>status</b> with it.
195      *
196      * @param oamCommandStatus of the current OAM command status
197      * @param message to be set in the new status
198      */
199     void setStatus(OAMCommandStatus oamCommandStatus, String message) {
200         Params params = new Params().addParam("errorMsg", message);
201
202         StatusBuilder statusBuilder = new StatusBuilder();
203         statusBuilder.setCode(oamCommandStatus.getResponseCode());
204         if (params != null) {
205             statusBuilder.setMessage(oamCommandStatus.getFormattedMessage(params));
206         } else {
207             statusBuilder.setMessage(oamCommandStatus.getResponseMessage());
208         }
209
210         status = statusBuilder.build();
211     }
212
213     /**
214      * Set class <b>status</b> with error status calculated from the passed in paremeter
215      * and audit log the error message.
216      * @param t of the error Throwable.
217      */
218     void setErrorStatus(Throwable t) {
219         resetLogProperties(false);
220
221         final String appName = configurationHelper.getAppcName();
222         String exceptionMessage = t.getMessage() != null ? t.getMessage() : t.toString();
223
224         OAMCommandStatus oamCommandStatus;
225         String errorMessage;
226         if (t instanceof InvalidInputException) {
227             oamCommandStatus = OAMCommandStatus.INVALID_PARAMETER;
228             errorMessage = EELFResourceManager.format(Msg.OAM_OPERATION_INVALID_INPUT, t.getMessage());
229         } else if (t instanceof InvalidStateException) {
230             exceptionMessage = String.format(AppcOam.INVALID_STATE_MESSAGE_FORMAT,
231                 rpc.getAppcOperation(), appName, stateHelper.getCurrentOamState());
232             oamCommandStatus = OAMCommandStatus.REJECTED;
233             errorMessage = EELFResourceManager.format(Msg.INVALID_STATE_TRANSITION, exceptionMessage);
234         } else if (t instanceof TimeoutException) {
235             oamCommandStatus = OAMCommandStatus.TIMEOUT;
236             errorMessage = EELFResourceManager.format(Msg.OAM_OPERATION_EXCEPTION, t,
237                     appName, t.getClass().getSimpleName(), rpc.name(), exceptionMessage);
238         } else {
239             oamCommandStatus = OAMCommandStatus.UNEXPECTED_ERROR;
240             errorMessage = EELFResourceManager.format(Msg.OAM_OPERATION_EXCEPTION, t,
241                 appName, t.getClass().getSimpleName(), rpc.name(), exceptionMessage);
242         }
243
244         setStatus(oamCommandStatus, exceptionMessage);
245
246         LoggingUtils.logErrorMessage(
247             String.valueOf(status.getCode()),
248             status.getMessage(),
249             LoggingConstants.TargetNames.APPC,
250             LoggingConstants.TargetNames.APPC_OAM_PROVIDER,
251             errorMessage,
252             AppcOam.class.getCanonicalName());
253
254         resetLogProperties(true);
255     }
256
257     /**
258      * Genral debug log when debug logging level is enabled.
259      * @param message of the log message format
260      * @param args of the objects listed in the message format
261      */
262     void logDebug(String message, Object... args) {
263         if (logger.isDebugEnabled()) {
264             logger.debug(String.format(message, args));
265         }
266     }
267
268     protected String getHostInfo(String type) throws UnknownHostException {
269         InetAddress inetAddress = InetAddress.getLocalHost();
270         String returnValue = "";
271         switch(type) {
272             case "canonicalHostName": returnValue = inetAddress.getCanonicalHostName();
273                 break;
274             case "hostName": returnValue = inetAddress.getHostName();
275                 break;
276             case "hostAddress": returnValue = inetAddress.getHostAddress();
277                 break;
278             default: returnValue = "Invalid operation";
279                 break;
280         }
281         return returnValue;
282     }
283 }