Merge "consolidated security configuration"
[so.git] / bpmn / MSOCommonBPMN / src / main / java / org / onap / so / client / cds / AbstractCDSProcessingBBUtils.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2019 TechMahindra
6  * ================================================================================
7  * Modifications Copyright (c) 2019 Samsung
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  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.so.client.cds;
24
25 import java.util.concurrent.CountDownLatch;
26 import java.util.concurrent.TimeUnit;
27 import org.camunda.bpm.engine.delegate.DelegateExecution;
28 import org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers;
29 import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader;
30 import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType;
31 import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput;
32 import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput;
33 import org.onap.so.client.PreconditionFailedException;
34 import org.onap.so.client.RestPropertiesLoader;
35 import org.onap.so.client.cds.beans.AbstractCDSPropertiesBean;
36 import org.onap.so.client.exception.BadResponseException;
37 import org.onap.so.client.exception.ExceptionBuilder;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40 import org.springframework.beans.factory.annotation.Autowired;
41 import org.springframework.stereotype.Component;
42 import com.google.protobuf.InvalidProtocolBufferException;
43 import com.google.protobuf.Struct;
44 import com.google.protobuf.Struct.Builder;
45 import com.google.protobuf.util.JsonFormat;
46 import io.grpc.Status;
47
48 /**
49  * Util class to support Call to CDS client
50  *
51  */
52 @Component
53 public class AbstractCDSProcessingBBUtils {
54
55     private static final Logger logger = LoggerFactory.getLogger(AbstractCDSProcessingBBUtils.class);
56
57     private static final String SUCCESS = "Success";
58     private static final String FAILED = "Failed";
59     private static final String PROCESSING = "Processing";
60     private static final String RESPONSE_PAYLOAD = "CDSResponsePayload";
61     private static final String CDS_STATUS = "CDSStatus";
62     private static final String EXEC_INPUT = "executionServiceInput";
63
64
65     /**
66      * indicate exception thrown.
67      */
68     private static final String EXCEPTION = "Exception";
69
70     @Autowired
71     private ExceptionBuilder exceptionUtil;
72
73     /**
74      * Extracting data from execution object and building the ExecutionServiceInput Object
75      *
76      * @param execution DelegateExecution object
77      */
78     public void constructExecutionServiceInputObject(DelegateExecution execution) {
79         logger.trace("Start AbstractCDSProcessingBBUtils.preProcessRequest ");
80
81         try {
82             AbstractCDSPropertiesBean executionObject =
83                     (AbstractCDSPropertiesBean) execution.getVariable("executionObject");
84
85             String payload = executionObject.getRequestObject();
86
87             CommonHeader commonHeader = CommonHeader.newBuilder().setOriginatorId(executionObject.getOriginatorId())
88                     .setRequestId(executionObject.getRequestId()).setSubRequestId(executionObject.getSubRequestId())
89                     .build();
90             ActionIdentifiers actionIdentifiers =
91                     ActionIdentifiers.newBuilder().setBlueprintName(executionObject.getBlueprintName())
92                             .setBlueprintVersion(executionObject.getBlueprintVersion())
93                             .setActionName(executionObject.getActionName()).setMode(executionObject.getMode()).build();
94
95             Builder struct = Struct.newBuilder();
96             try {
97                 JsonFormat.parser().merge(payload, struct);
98             } catch (InvalidProtocolBufferException e) {
99                 logger.error("Failed to parse received message. blueprint({}:{}) for action({}). {}",
100                         executionObject.getBlueprintVersion(), executionObject.getBlueprintName(),
101                         executionObject.getActionName(), e);
102             }
103
104             ExecutionServiceInput executionServiceInput =
105                     ExecutionServiceInput.newBuilder().setCommonHeader(commonHeader)
106                             .setActionIdentifiers(actionIdentifiers).setPayload(struct.build()).build();
107
108             execution.setVariable(EXEC_INPUT, executionServiceInput);
109
110         } catch (Exception ex) {
111             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
112         }
113     }
114
115     /**
116      * get the executionServiceInput object from execution and send a request to CDS Client and wait for TIMEOUT period
117      *
118      * @param execution DelegateExecution object
119      */
120     public void sendRequestToCDSClient(DelegateExecution execution) {
121
122         logger.trace("Start AbstractCDSProcessingBBUtils.sendRequestToCDSClient ");
123         try {
124             CDSProperties props = RestPropertiesLoader.getInstance().getNewImpl(CDSProperties.class);
125             if (props == null) {
126                 throw new PreconditionFailedException(
127                         "No RestProperty.CDSProperties implementation found on classpath, can't create client.");
128             }
129
130             ExecutionServiceInput executionServiceInput = (ExecutionServiceInput) execution.getVariable(EXEC_INPUT);
131
132             CDSResponse cdsResponse = new CDSResponse();
133
134             try (CDSProcessingClient cdsClient = new CDSProcessingClient(new ResponseHandler(cdsResponse))) {
135                 CountDownLatch countDownLatch = cdsClient.sendRequest(executionServiceInput);
136                 countDownLatch.await(props.getTimeout(), TimeUnit.SECONDS);
137             } catch (InterruptedException ex) {
138                 logger.error("Caught exception in sendRequestToCDSClient in AbstractCDSProcessingBBUtils : ", ex);
139                 Thread.currentThread().interrupt();
140             }
141
142             String cdsResponseStatus = cdsResponse.status;
143
144             /**
145              * throw CDS failed exception.
146              */
147             if (!cdsResponseStatus.equals(SUCCESS)) {
148                 throw new BadResponseException("CDS call failed with status: " + cdsResponse.status
149                         + " and errorMessage: " + cdsResponse.errorMessage);
150             }
151
152             execution.setVariable(CDS_STATUS, cdsResponseStatus);
153
154             if (cdsResponse.payload != null) {
155                 String payload = JsonFormat.printer().print(cdsResponse.payload);
156                 execution.setVariable(RESPONSE_PAYLOAD, payload);
157             }
158
159
160
161         } catch (Exception ex) {
162             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
163         }
164     }
165
166     private class ResponseHandler implements CDSProcessingListener {
167
168         private CDSResponse cdsResponse;
169
170         ResponseHandler(CDSResponse cdsResponse) {
171             this.cdsResponse = cdsResponse;
172         }
173
174         /**
175          * Get Response from CDS Client
176          */
177         @Override
178         public void onMessage(ExecutionServiceOutput message) {
179             logger.info("Received notification from CDS: {}", message);
180             EventType eventType = message.getStatus().getEventType();
181
182             switch (eventType) {
183                 case EVENT_COMPONENT_PROCESSING:
184                     cdsResponse.status = PROCESSING;
185                     break;
186                 case EVENT_COMPONENT_EXECUTED:
187                     cdsResponse.status = SUCCESS;
188                     break;
189                 default:
190                     cdsResponse.status = FAILED;
191                     cdsResponse.errorMessage = message.getStatus().getErrorMessage();
192                     break;
193             }
194             cdsResponse.payload = message.getPayload();
195         }
196
197         /**
198          * On error at CDS, log the error
199          */
200         @Override
201         public void onError(Throwable t) {
202             Status status = Status.fromThrowable(t);
203             logger.error("Failed processing blueprint {}", status, t);
204             cdsResponse.status = EXCEPTION;
205         }
206     }
207
208     private class CDSResponse {
209
210         String status;
211         String errorMessage;
212         Struct payload;
213
214         @Override
215         public String toString() {
216             return "CDSResponse{" + "status='" + status + '\'' + ", errorMessage='" + errorMessage + '\'' + ", payload="
217                     + payload + '}';
218         }
219     }
220 }