f908a3f0d6783d2b93a143dbca85ac9c0520974a
[so.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 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.openecomp.mso.apihandlerinfra;
22
23 import java.io.StringReader;
24 import java.io.StringWriter;
25 import java.sql.Timestamp;
26 import java.text.SimpleDateFormat;
27 import java.util.Date;
28
29 import javax.ws.rs.core.Response;
30 import javax.xml.bind.JAXBContext;
31 import javax.xml.bind.JAXBException;
32 import javax.xml.bind.Marshaller;
33 import javax.xml.bind.Unmarshaller;
34 import javax.xml.transform.OutputKeys;
35 import javax.xml.transform.Transformer;
36 import javax.xml.transform.TransformerFactory;
37 import javax.xml.transform.dom.DOMSource;
38 import javax.xml.transform.sax.SAXSource;
39 import javax.xml.transform.stream.StreamResult;
40
41 import org.hibernate.Query;
42 import org.hibernate.Session;
43 import org.w3c.dom.Document;
44 import org.w3c.dom.Element;
45 import org.w3c.dom.Node;
46 import org.w3c.dom.NodeList;
47 import org.xml.sax.InputSource;
48
49 import org.openecomp.mso.apihandler.common.ErrorNumbers;
50 import org.openecomp.mso.apihandler.common.ValidationException;
51 import org.openecomp.mso.apihandlerinfra.volumebeans.ActionType;
52 import org.openecomp.mso.apihandlerinfra.volumebeans.VolumeInputs;
53 import org.openecomp.mso.apihandlerinfra.volumebeans.ObjectFactory;
54 import org.openecomp.mso.apihandlerinfra.volumebeans.RequestInfo;
55 import org.openecomp.mso.apihandlerinfra.volumebeans.RequestStatusType;
56 import org.openecomp.mso.apihandlerinfra.volumebeans.VolumeRequest;
57 import org.openecomp.mso.db.AbstractSessionFactoryManager;
58 import org.openecomp.mso.logger.MsoLogger;
59 import org.openecomp.mso.logger.MessageEnum;
60 import org.openecomp.mso.properties.MsoJavaProperties;
61 import org.openecomp.mso.requestsdb.RequestsDbSessionFactoryManager;
62 import org.openecomp.mso.requestsdb.InfraActiveRequests;
63 import org.openecomp.mso.requestsdb.RequestsDatabase;
64
65 public class VolumeMsoInfraRequest {
66
67     private String requestId;
68     private String requestXML;
69     private String requestUri;
70     private RequestInfo rinfo;
71     private VolumeInputs volumeInputs;
72     private String volumeParams;
73     private ActionType action;
74     private String errorMessage;
75     private String httpResponse;
76     private String responseBody;
77     private RequestStatusType status;
78     private long startTime;
79     private long progress = Constants.PROGRESS_REQUEST_RECEIVED;
80
81     protected AbstractSessionFactoryManager requestsDbSessionFactoryManager = new RequestsDbSessionFactoryManager ();
82
83     private static MsoLogger msoLogger = MsoLogger.getMsoLogger (MsoLogger.Catalog.APIH);
84     private static final String NOT_PROVIDED = "not provided";
85
86     VolumeMsoInfraRequest (String requestId) {
87         this.requestId = requestId;
88         this.startTime = System.currentTimeMillis();
89         MsoLogger.setLogContext (requestId, null);
90
91     }
92
93     // Parse request XML
94     void parse (String reqXML, String version, MsoJavaProperties props) throws ValidationException {
95
96         msoLogger.debug ("Validating the request");
97
98         this.requestXML = reqXML;
99
100         VolumeRequest volumeReq = null;
101         boolean isWrongRootElement = false;
102
103         try {
104             JAXBContext jaxbContext = JAXBContext.newInstance (VolumeRequest.class);
105             Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller ();
106
107             InputSource inputSource = new InputSource (new StringReader (reqXML));
108             SAXSource source = new SAXSource (inputSource);
109
110             if (reqXML.contains ("volume-request") && !reqXML.contains("vnf-request")) {
111                 volumeReq = jaxbUnmarshaller.unmarshal (source, VolumeRequest.class).getValue ();
112             } else {
113                 isWrongRootElement = true;
114             }
115
116         } catch (Exception e) {
117                 msoLogger.error (MessageEnum.APIH_VNFREQUEST_VALIDATION_ERROR, "", "", MsoLogger.ErrorCode.DataError, "Exception when parsing reqXML", e);
118             throw new ValidationException ("format for volume request");
119         }
120
121         if (isWrongRootElement) {
122                 msoLogger.error (MessageEnum.APIH_REQUEST_VALIDATION_ERROR_REASON, "root element is not correct", "", "", MsoLogger.ErrorCode.SchemaError, "root element <volume-request> expected");
123             throw new ValidationException ("root element <volume-request> expected");
124         }
125
126         if (volumeReq == null) {
127             throw new ValidationException ("volume-request");
128         }
129
130         this.rinfo = volumeReq.getRequestInfo ();
131
132         if (this.rinfo == null) {
133             throw new ValidationException ("request-info");
134         }
135
136         action = this.rinfo.getAction ();
137         if (action == null) {
138             throw new ValidationException ("action");
139         }
140         this.volumeInputs = volumeReq.getVolumeInputs ();
141         if (this.volumeInputs == null) {
142             throw new ValidationException ("volume-inputs");
143         }
144
145         // Verify that the elements correspond to the version
146
147         switch (version) {
148             case Constants.SCHEMA_VERSION_V1:
149                 if (this.volumeInputs.getBackoutOnFailure() != null || this.volumeInputs.getAicCloudRegion() != null ||
150                     this.volumeInputs.getVfModuleModelName() != null
151                     || this.volumeInputs.getAsdcServiceModelVersion() != null ||
152                     this.volumeInputs.getServiceInstanceId() != null || this.volumeInputs.getVnfId() != null) {
153                     throw new ValidationException("format for v1 version of volume request");
154                 }
155                 break;
156             case Constants.SCHEMA_VERSION_V2:
157                 if (this.volumeInputs.getServiceType() != null || this.volumeInputs.getAicNodeClli() != null ||
158                     this.volumeInputs.getServiceInstanceId() != null || this.volumeInputs.getVnfId() != null) {
159                     throw new ValidationException("format for v2 version of volume request");
160                 }
161                 break;
162             case Constants.SCHEMA_VERSION_V3:
163                 if (this.volumeInputs.getServiceType() != null || this.volumeInputs.getAicNodeClli() != null) {
164                     throw new ValidationException("format for v3 version of volume request");
165                 }
166                 break;
167         }
168
169
170         if (!InfraUtils.isActionAllowed (props, "volume", version, action.value ())) {
171                 throw new ValidationException ("action allowable for version " + version + " of volume request");
172         }
173
174         switch (action) {
175             case UPDATE:
176             case DELETE:
177             case UPDATE_VF_MODULE_VOL:
178             case DELETE_VF_MODULE_VOL:
179                 if (this.volumeInputs.getVolumeGroupId () == null) {
180                     throw new ValidationException ("volume-group-id");
181                 }
182                 break;
183             default:
184                 break;
185         }
186
187         if (ActionType.CREATE.equals (action) || ActionType.CREATE_VF_MODULE_VOL.equals(action)) {
188                 if (this.volumeInputs.getVolumeGroupName () == null) {
189                         throw new ValidationException ("volume-group-name");
190                 }
191                 if (!InfraUtils.isValidHeatName(this.volumeInputs.getVolumeGroupName ())) {
192                         throw new ValidationException ("volume-group-name: no value meeting heat stack name syntax requirements");
193                 }
194         }
195
196
197         if (this.volumeInputs.getVnfType () == null) {
198                throw new ValidationException ("vnf-type");
199         }
200
201
202         switch (action) {
203         case CREATE_VF_MODULE_VOL:
204         case UPDATE_VF_MODULE_VOL:
205         case DELETE_VF_MODULE_VOL:
206             if (this.volumeInputs.getVfModuleModelName () == null) {
207                 throw new ValidationException ("vf-module-model-name");
208             }
209             break;
210         default:
211             break;
212         }
213
214         if (!version.equals(Constants.SCHEMA_VERSION_V1) && this.volumeInputs.getServiceId () == null) {
215                 throw new ValidationException ("service-id ");
216         }
217
218         if (version.equals(Constants.SCHEMA_VERSION_V1) && this.volumeInputs.getServiceType () != null && this.volumeInputs.getServiceId () != null) {
219                 throw new ValidationException ("service-type or service-id ");
220         }
221
222         if (version.equals(Constants.SCHEMA_VERSION_V1) && this.volumeInputs.getAicNodeClli () == null) {
223                 throw new ValidationException ("aic-node-clli");
224         }
225
226         if ((version.equals(Constants.SCHEMA_VERSION_V2) || version.equals(Constants.SCHEMA_VERSION_V3)) && (this.volumeInputs.getAicCloudRegion () == null || this.volumeInputs.getAicCloudRegion ().isEmpty())) {
227                 throw new ValidationException ("aic-cloud-region");
228         }
229
230         if (version.equals(Constants.SCHEMA_VERSION_V3) && this.volumeInputs.getServiceInstanceId () == null) {
231                 throw new ValidationException ("service-instance-id");
232         }
233
234         if (version.equals(Constants.SCHEMA_VERSION_V3) && this.volumeInputs.getVnfId () == null && ActionType.CREATE_VF_MODULE_VOL.equals(action)) {
235                 throw new ValidationException ("vnf-id");
236         }
237
238         if (ActionType.CREATE.equals (action) || ActionType.CREATE_VF_MODULE_VOL.equals(action)) {
239             if (this.volumeInputs.getTenantId () == null) {
240                 throw new ValidationException ("tenant-id");
241             }
242         }
243
244
245                 Object vpN = volumeReq.getVolumeParams ();
246
247                 if (vpN != null) {
248                     Node node = (Node) vpN;
249                     Document doc = node.getOwnerDocument ();
250                     this.volumeParams = domToStr (doc);
251                 }
252
253                 msoLogger.debug ("VolumeParams: " + this.volumeParams);
254
255
256         msoLogger.debug ("Request valid");
257
258         // Rebuild the request string for BPEL to include request-id
259         rinfo.setRequestId (this.requestId);
260         volumeReq.setRequestInfo (rinfo);
261
262         StringWriter stringWriter = new StringWriter ();
263         try {
264             JAXBContext jaxbContext = JAXBContext.newInstance (VolumeRequest.class);
265             Marshaller jaxbMarshaller = jaxbContext.createMarshaller ();
266
267             // output pretty printed
268             jaxbMarshaller.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT, true);
269
270             jaxbMarshaller.marshal (volumeReq, stringWriter);
271
272         } catch (JAXBException e) {
273             msoLogger.debug ("Exception: ", e);
274         }
275
276         this.requestXML = stringWriter.toString ().replace("http://org.openecomp/mso/infra/volume-request",
277                         "http://org.openecomp/mso/infra/vnf-request");
278
279         msoLogger.debug("REQUEST XML to BPEL: " + this.requestXML);
280
281     }
282
283     public void createRequestRecord (Status status) {
284
285         Session session = null;
286         try {
287
288             session = requestsDbSessionFactoryManager.getSessionFactory ().openSession ();
289             session.beginTransaction ();
290
291             InfraActiveRequests aq = new InfraActiveRequests ();
292             aq.setRequestId (requestId);
293
294             Timestamp startTimeStamp = new Timestamp (System.currentTimeMillis());
295             if (rinfo != null) {
296                 if (rinfo.getAction () != null) {
297                     aq.setAction (rinfo.getAction ().value ());
298                     aq.setRequestAction (RequestActionMap.getMappedRequestAction (rinfo.getAction ().value ()));
299                 }
300                 aq.setSource (rinfo.getSource ());
301             } else {
302                 // Set up mandatory parameters
303                 aq.setAction (NOT_PROVIDED);
304                 aq.setRequestAction (NOT_PROVIDED);
305             }
306
307             aq.setRequestBody (this.requestXML);
308             aq.setRequestScope (ModelType.volumeGroup.name ());
309
310              if (volumeInputs != null) {
311                 if (volumeInputs.getVolumeGroupId () != null) {
312                     aq.setVolumeGroupId (volumeInputs.getVolumeGroupId ());
313                 }
314                 if (volumeInputs.getVolumeGroupName () != null) {
315                     aq.setVolumeGroupName (volumeInputs.getVolumeGroupName ());
316                 }
317                 if (volumeInputs.getVnfType () != null) {
318                     aq.setVnfType (volumeInputs.getVnfType ());
319                 }
320                 if (volumeInputs.getVnfId () != null) {
321                     aq.setVnfId (volumeInputs.getVnfId ());
322                 }
323                 if (volumeInputs.getServiceInstanceId () != null) {
324                     aq.setServiceInstanceId (volumeInputs.getServiceInstanceId ());
325                 }
326                 if (volumeInputs.getServiceType () != null) {
327                     aq.setServiceType (volumeInputs.getServiceType ());
328                 }
329                 if (volumeInputs.getServiceId () != null) {
330                     aq.setAaiServiceId (volumeInputs.getServiceId ());
331                 }
332                 if (volumeInputs.getAicNodeClli () != null) {
333                     aq.setAicNodeClli (volumeInputs.getAicNodeClli ());
334                 }
335                 if (volumeInputs.getAicCloudRegion () != null) {
336                     aq.setAicCloudRegion (volumeInputs.getAicCloudRegion ());
337                 }
338                 if (volumeInputs.getTenantId () != null) {
339                     aq.setTenantId (volumeInputs.getTenantId ());
340                 }
341
342             }
343             aq.setStartTime (startTimeStamp);
344             aq.setRequestStatus (status.toString ());
345             aq.setLastModifiedBy (Constants.MODIFIED_BY_APIHANDLER);
346             aq.setRequestType ("VOLUME");
347
348             if (volumeParams != null) {
349                 msoLogger.debug ("Storing volumeParams: " + volumeParams);
350                 aq.setVnfParams (this.volumeParams);
351             }
352
353             if ((status == Status.FAILED) || (status == Status.COMPLETE)) {
354                 aq.setStatusMessage (this.errorMessage);
355                 aq.setResponseBody (this.responseBody);
356
357                 Timestamp endTimeStamp = new Timestamp (System.currentTimeMillis());
358                 aq.setEndTime (endTimeStamp);
359             }
360             aq.setProgress (this.progress);
361
362
363             msoLogger.debug ("About to insert a record");
364
365             session.save (aq);
366             session.getTransaction ().commit ();
367             session.close ();
368         } catch (Exception e) {
369                 msoLogger.error (MessageEnum.APIH_DB_INSERT_EXC, "", "", MsoLogger.ErrorCode.DataError, "Exception in createRequestRecord", e);
370             if (session != null) {
371                 session.close ();
372             }
373             if (!status.equals (Status.FAILED)) {
374                 throw e;
375             }
376         }
377     }
378
379     public void updateFinalStatus (Status status) {
380         int result = 0;
381         try {
382                 result = (RequestsDatabase.getInstance()).updateInfraFinalStatus(requestId, status.toString (),
383                          this.errorMessage, this.progress, this.responseBody, Constants.MODIFIED_BY_APIHANDLER);
384         } catch (Exception e) {
385                 msoLogger.error(MessageEnum.APIH_DB_UPDATE_EXC, e.getMessage(), "", "", MsoLogger.ErrorCode.DataError, "Exception in updateFinalStatus");
386                 msoLogger.debug("Exception: ", e);
387         }
388     }
389
390     public Response buildResponse (int httpResponseCode, String errorCode, InfraActiveRequests inProgress) {
391         return buildResponseWithError (httpResponseCode, errorCode, inProgress, null);
392     }
393
394     public Response buildResponseWithError (int httpResponseCode,
395                                             String errorCode,
396                                             InfraActiveRequests inProgress,
397                                             String errorString) {
398
399         ObjectFactory beansObjectFactory = new ObjectFactory ();
400
401         VolumeRequest vr = beansObjectFactory.createVolumeRequest ();
402
403         RequestInfo ri = beansObjectFactory.createRequestInfo ();
404
405         ri.setRequestId (requestId);
406         ri.setRequestStatus (this.status);
407         ri.setAction (this.rinfo.getAction ());
408         ri.setSource (this.rinfo.getSource ());
409
410         String errorMsg = null;
411         if (errorCode != null) {
412             // If error code is actually an XML error response from BPEL, treat it specially:
413             if (!Messages.errors.containsKey (errorCode)) {
414                 if (errorCode.length () > 300) {
415                     errorMsg = errorCode.substring (0, 299);
416                 } else {
417                     errorMsg = errorCode;
418                 }
419
420             } else {
421
422                 if (inProgress == null) {
423                         if (errorCode.equals(ErrorNumbers.RECIPE_DOES_NOT_EXIST)) {
424                                 errorMsg = String.format (Messages.errors.get (errorCode), "volume", errorString);
425                         }
426                         else {
427                                 errorMsg = String.format (Messages.errors.get (errorCode), errorString);
428                         }
429                 } else if (errorCode.equals (ErrorNumbers.LOCKED_CREATE_ON_THE_SAME_VNF_NAME_IN_PROGRESS)) {
430                     errorMsg = String.format (Messages.errors.get (errorCode),
431                                                                   "volume",
432                                               inProgress.getVnfName (),
433                                               inProgress.getRequestStatus (),
434                                               "volume");
435                 } else if (errorCode.equals (ErrorNumbers.LOCKED_SAME_ACTION_AND_VNF_ID)) {
436                     errorMsg = String.format (Messages.errors.get (errorCode),
437                                                                   "volume",
438                                               inProgress.getVnfId (),
439                                               inProgress.getRequestStatus (),
440                                               inProgress.getAction (),
441                                               "volume");
442                 }
443             }
444
445             ri.setStatusMessage (errorMsg);
446             this.errorMessage = errorMsg;
447         }
448         ri.setProgress ((int) this.progress);
449
450         Date startDate = new Date (this.startTime);
451         SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss.SSS");
452         String startTimeString = sdf.format (startDate);
453
454         ri.setStartTime (startTimeString);
455
456         vr.setRequestInfo (ri);
457         vr.setVolumeInputs (this.volumeInputs);
458
459         StringWriter stringWriter = new StringWriter ();
460         try {
461             JAXBContext jaxbContext = JAXBContext.newInstance (VolumeRequest.class);
462             Marshaller jaxbMarshaller = jaxbContext.createMarshaller ();
463             jaxbMarshaller.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT, true);
464
465             jaxbMarshaller.marshal (vr, stringWriter);
466
467         } catch (JAXBException e) {
468             msoLogger.debug ("Exception: ", e);
469         }
470
471         String response = stringWriter.toString ();
472
473         this.httpResponse = Integer.toString (httpResponseCode);
474         this.responseBody = response;
475
476         // Log the failed request into the MSO Requests database
477
478         return Response.status (httpResponseCode).entity (response).build ();
479
480     }
481
482     public Response buildResponseFailedValidation (int httpResponseCode, String exceptionMessage) {
483
484         ObjectFactory beansObjectFactory = new ObjectFactory ();
485         VolumeRequest vr = beansObjectFactory.createVolumeRequest ();
486
487         RequestInfo ri = beansObjectFactory.createRequestInfo ();
488         ri.setRequestId (requestId);
489
490         if (this.rinfo != null) {
491             if (this.rinfo.getAction () != null) {
492                 ri.setAction (this.rinfo.getAction ());
493             } else {
494                 ri.setAction (ActionType.NOT_PROVIDED);
495             }
496             if (this.rinfo.getSource () != null) {
497                 ri.setSource (this.rinfo.getSource ());
498             }
499         } else {
500             ri.setAction (ActionType.NOT_PROVIDED);
501         }
502
503         // Nothing more is expected for this request
504
505         String errorMsg = String.format (Messages.errors.get (ErrorNumbers.REQUEST_FAILED_SCHEMA_VALIDATION
506                                                               + "_service"),
507                                          exceptionMessage);
508         ri.setStatusMessage (errorMsg);
509         this.errorMessage = errorMsg;
510
511         ri.setProgress ((int) this.progress);
512         ri.setRequestStatus (RequestStatusType.FAILED);
513         Date startDate = new Date (this.startTime);
514         SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss.SSS");
515         String startTimeString = sdf.format (startDate);
516
517         ri.setStartTime (startTimeString);
518
519         vr.setRequestInfo (ri);
520         vr.setVolumeInputs (this.volumeInputs);
521
522         StringWriter stringWriter = new StringWriter ();
523         try {
524             JAXBContext jaxbContext = JAXBContext.newInstance (VolumeRequest.class);
525             Marshaller jaxbMarshaller = jaxbContext.createMarshaller ();
526
527             // output pretty printed
528             jaxbMarshaller.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT, true);
529
530             jaxbMarshaller.marshal (vr, stringWriter);
531
532         } catch (JAXBException e) {
533             msoLogger.debug ("Error marshalling", e);
534         }
535
536         String response = stringWriter.toString ();
537
538         this.httpResponse = Integer.toString (httpResponseCode);
539         this.responseBody = response;
540
541         return Response.status (httpResponseCode).entity (response).build ();
542     }
543
544     public String getRequestUri () {
545         return requestUri;
546     }
547
548     public void setRequestUri (String requestUri) {
549         this.requestUri = requestUri;
550     }
551
552     public VolumeInputs getVolumeInputs () {
553         return volumeInputs;
554     }
555
556     public RequestInfo getRequestInfo () {
557         return rinfo;
558     }
559
560     public String getResponseBody () {
561         return responseBody;
562     }
563
564     public void setResponseBody (String responseBody) {
565         this.responseBody = responseBody;
566     }
567
568     public String getHttpResponse () {
569         return httpResponse;
570     }
571
572     public void setHttpResponse (String httpResponse) {
573         this.httpResponse = httpResponse;
574     }
575
576     public String getRequestId () {
577         return requestId;
578     }
579
580     public String getRequestXML () {
581         return requestXML;
582     }
583
584     public void setRequestXML (String requestXML) {
585         this.requestXML = requestXML;
586     }
587
588     public RequestStatusType getStatus () {
589         return status;
590     }
591
592     public void setStatus (RequestStatusType status) {
593         this.status = status;
594         switch (status) {
595         case FAILED:
596         case COMPLETE:
597                 this.progress = Constants.PROGRESS_REQUEST_COMPLETED;
598                 break;
599         case IN_PROGRESS:
600                 this.progress = Constants.PROGRESS_REQUEST_IN_PROGRESS;
601                 break;
602         }
603     }
604
605     public String getServiceType () {
606         if (this.volumeInputs.getServiceType () != null)
607                 return this.volumeInputs.getServiceType ();
608         if (this.volumeInputs.getServiceId () != null)
609                 return this.volumeInputs.getServiceId ();
610         return null;
611     }
612
613     public static String domToStr (Document doc) {
614         if (doc == null) {
615             return null;
616         }
617
618         try {
619             StringWriter sw = new StringWriter ();
620             StreamResult sr = new StreamResult (sw);
621             TransformerFactory tf = TransformerFactory.newInstance ();
622             Transformer t = tf.newTransformer ();
623             t.setOutputProperty (OutputKeys.STANDALONE, "yes");
624             NodeList nl = doc.getDocumentElement ().getChildNodes ();
625             DOMSource source = null;
626             for (int x = 0; x < nl.getLength (); x++) {
627                 Node e = nl.item (x);
628                 if (e instanceof Element) {
629                     source = new DOMSource (e);
630                     break;
631                 }
632             }
633             if (source != null) {
634                 t.transform (source, sr);
635
636                         String s = sw.toString ();
637                         return s;
638             }
639
640                 return null;
641
642             } catch (Exception e) {
643                 msoLogger.error (MessageEnum.APIH_DOM2STR_ERROR, "", "", MsoLogger.ErrorCode.AvailabilityError, "Exception in domToStr", e);
644             }
645         return null;
646     }
647 }