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