AAI-1523 Batch reformat aai-core
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / logging / ErrorLogHelper.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *    http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.aai.logging;
22
23 import com.att.eelf.configuration.EELFLogger;
24 import com.att.eelf.configuration.EELFManager;
25
26 import java.io.FileInputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.StringWriter;
30 import java.util.ArrayList;
31 import java.util.HashMap;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Map.Entry;
36 import java.util.Properties;
37
38 import javax.ws.rs.core.MediaType;
39 import javax.xml.bind.JAXBContext;
40 import javax.xml.bind.Marshaller;
41
42 import org.apache.commons.lang.StringUtils;
43 import org.onap.aai.exceptions.AAIException;
44 import org.onap.aai.logging.LoggingContext.StatusCode;
45 import org.onap.aai.util.AAIConfig;
46 import org.onap.aai.util.AAIConstants;
47 import org.onap.aai.util.MapperUtil;
48 import org.slf4j.MDC;
49
50 /**
51  * 
52  * This classes loads the application error properties file
53  * and provides a method that returns an ErrorObject
54  * 
55  */
56
57 public class ErrorLogHelper {
58
59     private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(ErrorLogHelper.class);
60     private static final HashMap<String, ErrorObject> ERROR_OBJECTS = new HashMap<String, ErrorObject>();
61
62     static {
63         try {
64             loadProperties();
65         } catch (IOException e) {
66             throw new RuntimeException("Failed to load error.properties file", e);
67         } catch (ErrorObjectFormatException e) {
68             throw new RuntimeException("Failed to parse error.properties file", e);
69         }
70     }
71
72     /**
73      * Load properties.
74      * 
75      * @throws ErrorObjectFormatException
76      * @throws Exception the exception
77      */
78     public static void loadProperties() throws IOException, ErrorObjectFormatException {
79         final String filePath = AAIConstants.AAI_HOME_ETC_APP_PROPERTIES + "error.properties";
80         final InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath);
81         final Properties properties = new Properties();
82
83         if (is != null) {
84             properties.load(is);
85         } else {
86             try (final FileInputStream fis = new FileInputStream(filePath)) {
87                 properties.load(fis);
88             }
89         }
90
91         for (Entry<Object, Object> entry : properties.entrySet()) {
92             final String key = (String) entry.getKey();
93             final String value = (String) entry.getValue();
94             final String[] errorProperties = value.split(":");
95
96             if (errorProperties.length != 7)
97                 throw new ErrorObjectFormatException();
98
99             final ErrorObject errorObject = new ErrorObject();
100
101             errorObject.setDisposition(errorProperties[0].trim());
102             errorObject.setCategory(errorProperties[1].trim());
103             errorObject.setSeverity(errorProperties[2].trim());
104             errorObject.setErrorCode(errorProperties[3].trim());
105             errorObject.setHTTPResponseCode(errorProperties[4].trim());
106             errorObject.setRESTErrorCode(errorProperties[5].trim());
107             errorObject.setErrorText(errorProperties[6].trim());
108
109             ERROR_OBJECTS.put(key, errorObject);
110         }
111     }
112
113     /**
114      * Logs a known A&AI exception (i.e. one that can be found in error.properties)
115      *
116      * @param key The key for the error in the error.properties file
117      * @throws IOException
118      * @throws ErrorObjectNotFoundException
119      * @throws ErrorObjectFormatException
120      */
121     public static ErrorObject getErrorObject(String code) throws ErrorObjectNotFoundException {
122
123         if (code == null)
124             throw new IllegalArgumentException("Key cannot be null");
125
126         final ErrorObject errorObject = ERROR_OBJECTS.get(code);
127
128         if (errorObject == null) {
129             LOGGER.warn("Unknown AAIException with code=" + code + ".  Using default AAIException");
130             return ERROR_OBJECTS.get(AAIException.DEFAULT_EXCEPTION_CODE);
131         }
132
133         return errorObject;
134     }
135
136     /**
137      * Determines whether category is policy or not. If policy (1), this is a POL error, else it's a SVC error.
138      * The AAIRESTException may contain a different ErrorObject than that created with the REST error key.
139      * This allows lower level exception detail to be returned to the client to help troubleshoot the problem.
140      * If no error object is embedded in the AAIException, one will be created using the error object from the
141      * AAIException.
142      * 
143      * @param are must have a restError value whose numeric value must match what should be returned in the REST API
144      * @param variables optional list of variables to flesh out text in error string
145      * @return appropriately formatted JSON response per the REST API spec.
146      * @throws ErrorObjectFormatException
147      * @throws ErrorObjectNotFoundException
148      * @throws IOException
149      * @deprecated
150      */
151     public static String getRESTAPIErrorResponse(AAIException are, ArrayList<String> variables) {
152         List<MediaType> acceptHeaders = new ArrayList<MediaType>();
153         acceptHeaders.add(MediaType.APPLICATION_JSON_TYPE);
154
155         return getRESTAPIErrorResponse(acceptHeaders, are, variables);
156     }
157
158     /**
159      * Determines whether category is policy or not. If policy (1), this is a POL error, else it's a SVC error.
160      * The AAIRESTException may contain a different ErrorObject than that created with the REST error key.
161      * This allows lower level exception detail to be returned to the client to help troubleshoot the problem.
162      * If no error object is embedded in the AAIException, one will be created using the error object from the
163      * AAIException.
164      *
165      * @param acceptHeadersOrig the accept headers orig
166      * @param are must have a restError value whose numeric value must match what should be returned in the REST API
167      * @param variables optional list of variables to flesh out text in error string
168      * @return appropriately formatted JSON response per the REST API spec.
169      * @throws ErrorObjectFormatException
170      * @throws ErrorObjectNotFoundException
171      * @throws IOException
172      */
173     public static String getRESTAPIErrorResponse(List<MediaType> acceptHeadersOrig, AAIException are,
174             ArrayList<String> variables) {
175
176         StringBuilder text = new StringBuilder();
177         String response = null;
178
179         List<MediaType> acceptHeaders = new ArrayList<MediaType>();
180         // we might have an exception but no accept header, so we'll set default to JSON
181         boolean foundValidAcceptHeader = false;
182         for (MediaType mt : acceptHeadersOrig) {
183             if (MediaType.APPLICATION_XML_TYPE.isCompatible(mt) || MediaType.APPLICATION_JSON_TYPE.isCompatible(mt)) {
184                 acceptHeaders.add(mt);
185                 foundValidAcceptHeader = true;
186             }
187         }
188         if (foundValidAcceptHeader == false) {
189             // override the exception, client needs to set an appropriate Accept header
190             are = new AAIException("AAI_4014");
191             acceptHeaders.add(MediaType.APPLICATION_JSON_TYPE);
192         }
193
194         final ErrorObject eo = are.getErrorObject();
195
196         int restErrorCode = Integer.parseInt(eo.getRESTErrorCode());
197
198         ErrorObject restErrorObject;
199
200         try {
201             restErrorObject = ErrorLogHelper.getErrorObject("AAI_" + restErrorCode);
202         } catch (ErrorObjectNotFoundException e) {
203             LOGGER.warn("Failed to find related error object AAI_" + restErrorCode + " for error object "
204                     + eo.getErrorCode() + "; using AAI_" + restErrorCode);
205             restErrorObject = eo;
206         }
207
208         text.append(restErrorObject.getErrorText());
209
210         // We want to always append the (msg=%n) (ec=%n+1) to the text, but have to find value of n
211         // This assumes that the variables in the ArrayList, which might be more than are needed to flesh out the
212         // error, are ordered based on the error string.
213         int localDataIndex = StringUtils.countMatches(restErrorObject.getErrorText(), "%");
214         text.append(" (msg=%").append(localDataIndex + 1).append(") (ec=%").append(localDataIndex + 2).append(")");
215
216         if (variables == null) {
217             variables = new ArrayList<String>();
218         }
219
220         if (variables.size() < localDataIndex) {
221             ErrorLogHelper.logError("AAI_4011", "data missing for rest error");
222             while (variables.size() < localDataIndex) {
223                 variables.add("null");
224             }
225         }
226
227         // This will put the error code and error text into the right positions
228         if (are.getMessage() == null || are.getMessage().length() == 0) {
229             variables.add(localDataIndex++, eo.getErrorText());
230         } else {
231             variables.add(localDataIndex++, eo.getErrorText() + ":" + are.getMessage());
232         }
233         variables.add(localDataIndex, eo.getErrorCodeString());
234
235         for (MediaType mediaType : acceptHeaders) {
236             if (MediaType.APPLICATION_XML_TYPE.isCompatible(mediaType)) {
237                 JAXBContext context = null;
238                 try {
239                     if (eo.getCategory().equals("1")) {
240
241                         context = JAXBContext.newInstance(org.onap.aai.domain.restPolicyException.Fault.class);
242                         Marshaller m = context.createMarshaller();
243                         m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
244                         m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
245
246                         org.onap.aai.domain.restPolicyException.ObjectFactory factory =
247                                 new org.onap.aai.domain.restPolicyException.ObjectFactory();
248                         org.onap.aai.domain.restPolicyException.Fault fault = factory.createFault();
249                         org.onap.aai.domain.restPolicyException.Fault.RequestError requestError =
250                                 factory.createFaultRequestError();
251                         org.onap.aai.domain.restPolicyException.Fault.RequestError.PolicyException policyException =
252                                 factory.createFaultRequestErrorPolicyException();
253                         org.onap.aai.domain.restPolicyException.Fault.RequestError.PolicyException.Variables polvariables =
254                                 factory.createFaultRequestErrorPolicyExceptionVariables();
255
256                         policyException.setMessageId("POL" + eo.getRESTErrorCode());
257                         policyException.setText(text.toString());
258                         for (int i = 0; i < variables.size(); i++) {
259                             polvariables.getVariable().add(variables.get(i));
260                         }
261                         policyException.setVariables(polvariables);
262                         requestError.setPolicyException(policyException);
263                         fault.setRequestError(requestError);
264
265                         StringWriter sw = new StringWriter();
266                         m.marshal(fault, sw);
267
268                         response = sw.toString();
269
270                     } else {
271
272                         context = JAXBContext.newInstance(org.onap.aai.domain.restServiceException.Fault.class);
273                         Marshaller m = context.createMarshaller();
274                         m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
275                         m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
276
277                         org.onap.aai.domain.restServiceException.ObjectFactory factory =
278                                 new org.onap.aai.domain.restServiceException.ObjectFactory();
279                         org.onap.aai.domain.restServiceException.Fault fault = factory.createFault();
280                         org.onap.aai.domain.restServiceException.Fault.RequestError requestError =
281                                 factory.createFaultRequestError();
282                         org.onap.aai.domain.restServiceException.Fault.RequestError.ServiceException serviceException =
283                                 factory.createFaultRequestErrorServiceException();
284                         org.onap.aai.domain.restServiceException.Fault.RequestError.ServiceException.Variables svcvariables =
285                                 factory.createFaultRequestErrorServiceExceptionVariables();
286                         serviceException.setMessageId("SVC" + eo.getRESTErrorCode());
287                         serviceException.setText(text.toString());
288                         for (int i = 0; i < variables.size(); i++) {
289                             svcvariables.getVariable().add(variables.get(i));
290                         }
291                         serviceException.setVariables(svcvariables);
292                         requestError.setServiceException(serviceException);
293                         fault.setRequestError(requestError);
294
295                         StringWriter sw = new StringWriter();
296                         m.marshal(fault, sw);
297
298                         response = sw.toString();
299
300                     }
301                 } catch (Exception ex) {
302                     LOGGER.error(
303                             "We were unable to create a rest exception to return on an API because of a parsing error "
304                                     + ex.getMessage());
305                 }
306             } else {
307                 try {
308                     if (eo.getCategory().equals("1")) {
309                         org.onap.aai.domain.restPolicyException.RESTResponse restresp =
310                                 new org.onap.aai.domain.restPolicyException.RESTResponse();
311                         org.onap.aai.domain.restPolicyException.RequestError reqerr =
312                                 new org.onap.aai.domain.restPolicyException.RequestError();
313                         org.onap.aai.domain.restPolicyException.PolicyException polexc =
314                                 new org.onap.aai.domain.restPolicyException.PolicyException();
315                         polexc.setMessageId("POL" + eo.getRESTErrorCode());
316                         polexc.setText(text.toString());
317                         polexc.setVariables(variables);
318                         reqerr.setPolicyException(polexc);
319                         restresp.setRequestError(reqerr);
320                         response = (MapperUtil.writeAsJSONString((Object) restresp));
321
322                     } else {
323                         org.onap.aai.domain.restServiceException.RESTResponse restresp =
324                                 new org.onap.aai.domain.restServiceException.RESTResponse();
325                         org.onap.aai.domain.restServiceException.RequestError reqerr =
326                                 new org.onap.aai.domain.restServiceException.RequestError();
327                         org.onap.aai.domain.restServiceException.ServiceException svcexc =
328                                 new org.onap.aai.domain.restServiceException.ServiceException();
329                         svcexc.setMessageId("SVC" + eo.getRESTErrorCode());
330                         svcexc.setText(text.toString());
331                         svcexc.setVariables(variables);
332                         reqerr.setServiceException(svcexc);
333                         restresp.setRequestError(reqerr);
334                         response = (MapperUtil.writeAsJSONString((Object) restresp));
335                     }
336                 } catch (AAIException ex) {
337                     LOGGER.error(
338                             "We were unable to create a rest exception to return on an API because of a parsing error "
339                                     + ex.getMessage());
340                 }
341             }
342         }
343
344         return response;
345     }
346
347     /**
348      * Gets the RESTAPI error response with logging.
349      *
350      * @param acceptHeadersOrig the accept headers orig
351      * @param are the are
352      * @param variables the variables
353      * @param logline the logline
354      * @return the RESTAPI error response with logging
355      * @throws ErrorObjectFormatException
356      * @throws ErrorObjectNotFoundException
357      * @throws IOException
358      */
359     public static String getRESTAPIErrorResponseWithLogging(List<MediaType> acceptHeadersOrig, AAIException are,
360             ArrayList<String> variables) {
361         String response = ErrorLogHelper.getRESTAPIErrorResponse(acceptHeadersOrig, are, variables);
362
363         LOGGER.error(are.getMessage() + " " + LogFormatTools.getStackTop(are));
364
365         return response;
366     }
367
368     /**
369      * Gets the RESTAPI info response.
370      *
371      * @param acceptHeaders the accept headers
372      * @param areList the are list
373      * @return the RESTAPI info response
374      * @throws ErrorObjectFormatException
375      * @throws ErrorObjectNotFoundException
376      * @throws IOException
377      */
378     public static Object getRESTAPIInfoResponse(List<MediaType> acceptHeaders,
379             HashMap<AAIException, ArrayList<String>> areList) {
380
381         Object respObj = null;
382
383         org.onap.aai.domain.restResponseInfo.ObjectFactory factory =
384                 new org.onap.aai.domain.restResponseInfo.ObjectFactory();
385         org.onap.aai.domain.restResponseInfo.Info info = factory.createInfo();
386         org.onap.aai.domain.restResponseInfo.Info.ResponseMessages responseMessages =
387                 factory.createInfoResponseMessages();
388         Iterator<Entry<AAIException, ArrayList<String>>> it = areList.entrySet().iterator();
389
390         while (it.hasNext()) {
391             Entry<AAIException, ArrayList<String>> pair = (Entry<AAIException, ArrayList<String>>) it.next();
392             AAIException are = pair.getKey();
393             ArrayList<String> variables = pair.getValue();
394
395             StringBuilder text = new StringBuilder();
396
397             ErrorObject eo = are.getErrorObject();
398
399             int restErrorCode = Integer.parseInt(eo.getRESTErrorCode());
400             ErrorObject restErrorObject;
401             try {
402                 restErrorObject = ErrorLogHelper.getErrorObject("AAI_" + String.format("%04d", restErrorCode));
403             } catch (ErrorObjectNotFoundException e) {
404                 restErrorObject = eo;
405             }
406             text.append(restErrorObject.getErrorText());
407
408             // We want to always append the (msg=%n) (ec=%n+1) to the text, but have to find value of n
409             // This assumes that the variables in the ArrayList, which might be more than are needed to flesh out the
410             // error, are ordered based on the error string.
411             int localDataIndex = StringUtils.countMatches(restErrorObject.getErrorText(), "%");
412             text.append(" (msg=%").append(localDataIndex + 1).append(") (rc=%").append(localDataIndex + 2).append(")");
413
414             if (variables == null) {
415                 variables = new ArrayList<String>();
416             }
417
418             if (variables.size() < localDataIndex) {
419                 ErrorLogHelper.logError("AAI_4011", "data missing for rest error");
420                 while (variables.size() < localDataIndex) {
421                     variables.add("null");
422                 }
423             }
424
425             // This will put the error code and error text into the right positions
426             if (are.getMessage() == null) {
427                 variables.add(localDataIndex++, eo.getErrorText());
428             } else {
429                 variables.add(localDataIndex++, eo.getErrorText() + ":" + are.getMessage());
430             }
431             variables.add(localDataIndex, eo.getErrorCodeString());
432
433             try {
434                 org.onap.aai.domain.restResponseInfo.Info.ResponseMessages.ResponseMessage responseMessage =
435                         factory.createInfoResponseMessagesResponseMessage();
436                 org.onap.aai.domain.restResponseInfo.Info.ResponseMessages.ResponseMessage.Variables infovariables =
437                         factory.createInfoResponseMessagesResponseMessageVariables();
438
439                 responseMessage.setMessageId("INF" + eo.getRESTErrorCode());
440                 responseMessage.setText(text.toString());
441                 for (int i = 0; i < variables.size(); i++) {
442                     infovariables.getVariable().add(variables.get(i));
443                 }
444
445                 responseMessage.setVariables(infovariables);
446                 responseMessages.getResponseMessage().add(responseMessage);
447
448             } catch (Exception ex) {
449                 LOGGER.error("We were unable to create a rest exception to return on an API because of a parsing error "
450                         + ex.getMessage());
451             }
452         }
453
454         info.setResponseMessages(responseMessages);
455         respObj = (Object) info;
456
457         return respObj;
458     }
459
460     /**
461      * Determines whether category is policy or not. If policy (1), this is a POL error, else it's a SVC error.
462      * The AAIRESTException may contain a different ErrorObject than that created with the REST error key.
463      * This allows lower level exception detail to be returned to the client to help troubleshoot the problem.
464      * If no error object is embedded in the AAIException, one will be created using the error object from the
465      * AAIException.
466      * 
467      * @param are must have a restError value whose numeric value must match what should be returned in the REST API
468      * @param variables optional list of variables to flesh out text in error string
469      * @return appropriately formatted JSON response per the REST API spec.
470      * @throws ErrorObjectFormatException
471      * @throws ErrorObjectNotFoundException
472      * @throws IOException
473      */
474     public static String getRESTAPIPolicyErrorResponseXML(AAIException are, ArrayList<String> variables) {
475
476         StringBuilder text = new StringBuilder();
477         String response = null;
478         JAXBContext context = null;
479
480         ErrorObject eo = are.getErrorObject();
481
482         int restErrorCode = Integer.parseInt(eo.getRESTErrorCode());
483         ErrorObject restErrorObject;
484         try {
485             restErrorObject = ErrorLogHelper.getErrorObject("AAI_" + restErrorCode);
486         } catch (ErrorObjectNotFoundException e) {
487             restErrorObject = eo;
488         }
489
490         text.append(restErrorObject.getErrorText());
491
492         // We want to always append the (msg=%n) (ec=%n+1) to the text, but have to find value of n
493         // This assumes that the variables in the ArrayList, which might be more than are needed to flesh out the
494         // error, are ordered based on the error string.
495         int localDataIndex = StringUtils.countMatches(restErrorObject.getErrorText(), "%");
496         text.append(" (msg=%").append(localDataIndex + 1).append(") (ec=%").append(localDataIndex + 2).append(")");
497
498         if (variables == null) {
499             variables = new ArrayList<String>();
500         }
501
502         if (variables.size() < localDataIndex) {
503             ErrorLogHelper.logError("AAI_4011", "data missing for rest error");
504             while (variables.size() < localDataIndex) {
505                 variables.add("null");
506             }
507         }
508
509         // This will put the error code and error text into the right positions
510         if (are.getMessage() == null) {
511             variables.add(localDataIndex++, eo.getErrorText());
512         } else {
513             variables.add(localDataIndex++, eo.getErrorText() + ":" + are.getMessage());
514         }
515         variables.add(localDataIndex, eo.getErrorCodeString());
516
517         try {
518             if (eo.getCategory().equals("1")) {
519
520                 context = JAXBContext.newInstance(org.onap.aai.domain.restPolicyException.Fault.class);
521                 Marshaller m = context.createMarshaller();
522                 m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
523                 m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
524
525                 org.onap.aai.domain.restPolicyException.ObjectFactory factory =
526                         new org.onap.aai.domain.restPolicyException.ObjectFactory();
527                 org.onap.aai.domain.restPolicyException.Fault fault = factory.createFault();
528                 org.onap.aai.domain.restPolicyException.Fault.RequestError requestError =
529                         factory.createFaultRequestError();
530                 org.onap.aai.domain.restPolicyException.Fault.RequestError.PolicyException policyException =
531                         factory.createFaultRequestErrorPolicyException();
532                 org.onap.aai.domain.restPolicyException.Fault.RequestError.PolicyException.Variables polvariables =
533                         factory.createFaultRequestErrorPolicyExceptionVariables();
534
535                 policyException.setMessageId("POL" + eo.getRESTErrorCode());
536                 policyException.setText(text.toString());
537                 for (int i = 0; i < variables.size(); i++) {
538                     polvariables.getVariable().add(variables.get(i));
539                 }
540                 policyException.setVariables(polvariables);
541                 requestError.setPolicyException(policyException);
542                 fault.setRequestError(requestError);
543
544                 StringWriter sw = new StringWriter();
545                 m.marshal(fault, sw);
546
547                 response = sw.toString();
548
549             } else {
550
551                 context = JAXBContext.newInstance(org.onap.aai.domain.restServiceException.Fault.class);
552                 Marshaller m = context.createMarshaller();
553                 m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
554                 m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
555
556                 org.onap.aai.domain.restServiceException.ObjectFactory factory =
557                         new org.onap.aai.domain.restServiceException.ObjectFactory();
558                 org.onap.aai.domain.restServiceException.Fault fault = factory.createFault();
559                 org.onap.aai.domain.restServiceException.Fault.RequestError requestError =
560                         factory.createFaultRequestError();
561                 org.onap.aai.domain.restServiceException.Fault.RequestError.ServiceException serviceException =
562                         factory.createFaultRequestErrorServiceException();
563                 org.onap.aai.domain.restServiceException.Fault.RequestError.ServiceException.Variables svcvariables =
564                         factory.createFaultRequestErrorServiceExceptionVariables();
565                 serviceException.setMessageId("POL" + eo.getRESTErrorCode());
566                 serviceException.setText(text.toString());
567                 for (int i = 0; i < variables.size(); i++) {
568                     svcvariables.getVariable().add(variables.get(i));
569                 }
570                 serviceException.setVariables(svcvariables);
571                 requestError.setServiceException(serviceException);
572                 fault.setRequestError(requestError);
573
574                 StringWriter sw = new StringWriter();
575                 m.marshal(fault, sw);
576
577                 response = sw.toString();
578
579             }
580         } catch (Exception ex) {
581             LOGGER.error("We were unable to create a rest exception to return on an API because of a parsing error "
582                     + ex.getMessage());
583         }
584         return response;
585     }
586
587     public static void logException(AAIException e) {
588         final ErrorObject errorObject = e.getErrorObject();
589
590         // MDC.put("severity", errorObject.getSeverity()); //TODO Use LoggingContext.severity(int severity)
591         String severityCode = errorObject.getSeverityCode(errorObject.getSeverity());
592
593         if (!AAIConfig.isEmpty(severityCode)) {
594             int sevCode = Integer.parseInt(severityCode);
595             if (sevCode > 0 && sevCode <= 3) {
596                 LoggingContext.severity(sevCode);
597             }
598         }
599         String stackTrace = "";
600         try {
601             stackTrace = LogFormatTools.getStackTop(e);
602         } catch (Exception a) {
603             // ignore
604         }
605         final String errorMessage = new StringBuilder().append(errorObject.getErrorText()).append(":")
606                 .append(errorObject.getRESTErrorCode()).append(":").append(errorObject.getHTTPResponseCode())
607                 .append(":").append(e.getMessage()).toString().replaceAll("\\n", "^");
608
609         LoggingContext.responseCode(Integer.toString(errorObject.getHTTPResponseCode().getStatusCode()));
610         LoggingContext.responseDescription(errorMessage);
611         LoggingContext.statusCode(StatusCode.ERROR);
612
613         final String details =
614                 new StringBuilder().append(errorObject.getErrorCodeString()).append(" ").append(stackTrace).toString();
615
616         if (errorObject.getSeverity().equalsIgnoreCase("WARN"))
617             LOGGER.warn(details);
618         else if (errorObject.getSeverity().equalsIgnoreCase("ERROR"))
619             LOGGER.error(details);
620         else if (errorObject.getSeverity().equalsIgnoreCase("FATAL"))
621             LOGGER.error(details);
622         else if (errorObject.getSeverity().equals("INFO"))
623             LOGGER.info(details);
624     }
625
626     public static void logError(String code) {
627         logError(code, "");
628     }
629
630     public static void logError(String code, String message) {
631         logException(new AAIException(code, message));
632     }
633 }