001: /*
002: * $Id: SOAPPartImpl.java,v 1.1.1.1 2006/01/27 13:10:55 kumarjayanti Exp $
003: * $Revision: 1.1.1.1 $
004: * $Date: 2006/01/27 13:10:55 $
005: */
006:
007: /*
008: * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
009: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
010: *
011: * This code is free software; you can redistribute it and/or modify it
012: * under the terms of the GNU General Public License version 2 only, as
013: * published by the Free Software Foundation. Sun designates this
014: * particular file as subject to the "Classpath" exception as provided
015: * by Sun in the LICENSE file that accompanied this code.
016: *
017: * This code is distributed in the hope that it will be useful, but WITHOUT
018: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
019: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
020: * version 2 for more details (a copy is included in the LICENSE file that
021: * accompanied this code).
022: *
023: * You should have received a copy of the GNU General Public License version
024: * 2 along with this work; if not, write to the Free Software Foundation,
025: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
026: *
027: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
028: * CA 95054 USA or visit www.sun.com if you need additional information or
029: * have any questions.
030: */
031: package com.sun.xml.internal.messaging.saaj.soap;
032:
033: import java.io.*;
034: import java.util.Iterator;
035: import java.util.logging.Logger;
036: import java.util.logging.Level;
037:
038: import javax.activation.DataHandler;
039: import javax.activation.DataSource;
040: import javax.xml.soap.*;
041: import javax.xml.transform.Source;
042: import javax.xml.transform.stream.StreamSource;
043:
044: import org.w3c.dom.*;
045:
046: import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.MimeBodyPart;
047:
048: import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl;
049: import com.sun.xml.internal.messaging.saaj.soap.impl.ElementImpl;
050: import com.sun.xml.internal.messaging.saaj.soap.impl.EnvelopeImpl;
051: import com.sun.xml.internal.messaging.saaj.soap.name.NameImpl;
052: import com.sun.xml.internal.messaging.saaj.util.*;
053: import javax.xml.transform.sax.SAXSource;
054:
055: /**
056: * SOAPPartImpl is the first attachment. This contains the XML/SOAP document.
057: *
058: * @author Anil Vijendran (anil@sun.com)
059: */
060: public abstract class SOAPPartImpl extends SOAPPart implements
061: SOAPDocument {
062: protected static Logger log = Logger.getLogger(
063: LogDomainConstants.SOAP_DOMAIN,
064: "com.sun.xml.internal.messaging.saaj.soap.LocalStrings");
065:
066: protected MimeHeaders headers;
067: protected Envelope envelope;
068: protected Source source;
069: protected SOAPDocumentImpl document;
070:
071: //flag to indicate if a setContent happened.
072: private boolean sourceWasSet = false;
073:
074: // Records whether the input source had an xml decl or not.
075: protected boolean omitXmlDecl = true;
076:
077: // Records the charset encoding of the input stream source if provided.
078: protected String sourceCharsetEncoding = null;
079:
080: /**
081: * Reference to containing message (may be null)
082: */
083: protected MessageImpl message;
084:
085: protected SOAPPartImpl() {
086: this (null);
087: }
088:
089: protected SOAPPartImpl(MessageImpl message) {
090: document = new SOAPDocumentImpl(this );
091: headers = new MimeHeaders();
092: this .message = message;
093: headers.setHeader("Content-Type", getContentType());
094: }
095:
096: protected abstract String getContentType();
097:
098: protected abstract Envelope createEnvelopeFromSource()
099: throws SOAPException;
100:
101: protected abstract Envelope createEmptyEnvelope(String prefix)
102: throws SOAPException;
103:
104: protected abstract SOAPPartImpl duplicateType();
105:
106: protected String getContentTypeString() {
107: return getContentType();
108: }
109:
110: public boolean isFastInfoset() {
111: return (message != null) ? message.isFastInfoset() : false;
112: }
113:
114: public SOAPEnvelope getEnvelope() throws SOAPException {
115:
116: // If there is no SOAP envelope already created, then create
117: // one from a source if one exists. If there is a newer source
118: // then use that source.
119:
120: if (sourceWasSet)
121: sourceWasSet = false;
122:
123: lookForEnvelope();
124: if (envelope != null) {
125: if (source != null) { // there's a newer source, use it
126: document.removeChild(envelope);
127: envelope = createEnvelopeFromSource();
128: }
129: } else if (source != null) {
130: envelope = createEnvelopeFromSource();
131: } else {
132: envelope = createEmptyEnvelope(null);
133: document.insertBefore(envelope, null);
134: }
135: return envelope;
136: }
137:
138: protected void lookForEnvelope() throws SOAPException {
139: Element envelopeChildElement = document.doGetDocumentElement();
140: if (envelopeChildElement == null
141: || envelopeChildElement instanceof Envelope) {
142: envelope = (EnvelopeImpl) envelopeChildElement;
143: } else if (!(envelopeChildElement instanceof ElementImpl)) {
144: log.severe("SAAJ0512.soap.incorrect.factory.used");
145: throw new SOAPExceptionImpl(
146: "Unable to create envelope: incorrect factory used during tree construction");
147: } else {
148: ElementImpl soapElement = (ElementImpl) envelopeChildElement;
149: if (soapElement.getLocalName().equalsIgnoreCase("Envelope")) {
150: String prefix = soapElement.getPrefix();
151: String uri = (prefix == null) ? soapElement
152: .getNamespaceURI() : soapElement
153: .getNamespaceURI(prefix);
154: if (!uri.equals(NameImpl.SOAP11_NAMESPACE)
155: && !uri.equals(NameImpl.SOAP12_NAMESPACE)) {
156: log.severe("SAAJ0513.soap.unknown.ns");
157: throw new SOAPVersionMismatchException(
158: "Unable to create envelope from given source because the namespace was not recognized");
159: }
160: } else {
161: log
162: .severe("SAAJ0514.soap.root.elem.not.named.envelope");
163: throw new SOAPExceptionImpl(
164: "Unable to create envelope from given source because the root element is not named \"Envelope\"");
165: }
166: }
167: }
168:
169: public void removeAllMimeHeaders() {
170: headers.removeAllHeaders();
171: }
172:
173: public void removeMimeHeader(String header) {
174: headers.removeHeader(header);
175: }
176:
177: public String[] getMimeHeader(String name) {
178: return headers.getHeader(name);
179: }
180:
181: public void setMimeHeader(String name, String value) {
182: headers.setHeader(name, value);
183: }
184:
185: public void addMimeHeader(String name, String value) {
186: headers.addHeader(name, value);
187: }
188:
189: public Iterator getAllMimeHeaders() {
190: return headers.getAllHeaders();
191: }
192:
193: public Iterator getMatchingMimeHeaders(String[] names) {
194: return headers.getMatchingHeaders(names);
195: }
196:
197: public Iterator getNonMatchingMimeHeaders(String[] names) {
198: return headers.getNonMatchingHeaders(names);
199: }
200:
201: public Source getContent() throws SOAPException {
202: if (source != null) {
203: InputStream bis = null;
204: if (source instanceof JAXMStreamSource) {
205: StreamSource streamSource = (StreamSource) source;
206: bis = streamSource.getInputStream();
207: } else if (FastInfosetReflection
208: .isFastInfosetSource(source)) {
209: // FastInfosetSource inherits from SAXSource
210: SAXSource saxSource = (SAXSource) source;
211: bis = saxSource.getInputSource().getByteStream();
212: }
213:
214: if (bis != null) {
215: try {
216: bis.reset();
217: } catch (IOException e) {
218: /* This exception will never be thrown.
219: *
220: * The setContent method will modify the source
221: * if StreamSource to JAXMStreamSource, that uses
222: * a ByteInputStream, and for a FastInfosetSource will
223: * replace the InputStream with a ByteInputStream.
224: */
225: }
226: }
227: return source;
228: }
229:
230: return ((Envelope) getEnvelope()).getContent();
231: }
232:
233: public void setContent(Source source) throws SOAPException {
234: try {
235: if (source instanceof StreamSource) {
236: InputStream is = ((StreamSource) source)
237: .getInputStream();
238: Reader rdr = ((StreamSource) source).getReader();
239:
240: if (is != null) {
241: this .source = new JAXMStreamSource(is);
242: } else if (rdr != null) {
243: this .source = new JAXMStreamSource(rdr);
244: } else {
245: log.severe("SAAJ0544.soap.no.valid.reader.for.src");
246: throw new SOAPExceptionImpl(
247: "Source does not have a valid Reader or InputStream");
248: }
249: } else if (FastInfosetReflection
250: .isFastInfosetSource(source)) {
251: // InputStream is = source.getInputStream()
252: InputStream is = FastInfosetReflection
253: .FastInfosetSource_getInputStream(source);
254:
255: /*
256: * Underlying stream must be ByteInputStream for getContentAsStream(). We pay the
257: * cost of copying the underlying bytes here to avoid multiple copies every time
258: * getBytes() is called on a ByteInputStream.
259: */
260: if (!(is instanceof ByteInputStream)) {
261: ByteOutputStream bout = new ByteOutputStream();
262: bout.write(is);
263:
264: // source.setInputStream(new ByteInputStream(...))
265: FastInfosetReflection
266: .FastInfosetSource_setInputStream(source,
267: bout.newInputStream());
268: }
269: this .source = source;
270: } else {
271: this .source = source;
272: }
273: sourceWasSet = true;
274: } catch (Exception ex) {
275: ex.printStackTrace();
276:
277: log.severe("SAAJ0545.soap.cannot.set.src.for.part");
278: throw new SOAPExceptionImpl(
279: "Error setting the source for SOAPPart: "
280: + ex.getMessage());
281: }
282: }
283:
284: public ByteInputStream getContentAsStream() throws IOException {
285: if (source != null) {
286: InputStream is = null;
287:
288: // Allow message to be transcode if so requested
289: if (source instanceof StreamSource && !isFastInfoset()) {
290: is = ((StreamSource) source).getInputStream();
291: } else if (FastInfosetReflection
292: .isFastInfosetSource(source)
293: && isFastInfoset()) {
294: try {
295: // InputStream is = source.getInputStream()
296: is = FastInfosetReflection
297: .FastInfosetSource_getInputStream(source);
298: } catch (Exception e) {
299: throw new IOException(e.toString());
300: }
301: }
302:
303: if (is != null) {
304: if (!(is instanceof ByteInputStream)) {
305: log.severe("SAAJ0546.soap.stream.incorrect.type");
306: throw new IOException(
307: "Internal error: stream not of the right type");
308: }
309: return (ByteInputStream) is;
310: }
311: // need to do something here for reader...
312: // for now we'll see if we can fallback...
313: }
314:
315: ByteOutputStream b = new ByteOutputStream();
316:
317: Envelope env = null;
318:
319: try {
320: env = (Envelope) getEnvelope();
321: env.output(b, isFastInfoset());
322: } catch (SOAPException soapException) {
323: log.severe("SAAJ0547.soap.cannot.externalize");
324: throw new SOAPIOException(
325: "SOAP exception while trying to externalize: ",
326: soapException);
327: }
328:
329: return b.newInputStream();
330: }
331:
332: MimeBodyPart getMimePart() throws SOAPException {
333: try {
334: MimeBodyPart headerEnvelope = new MimeBodyPart();
335:
336: headerEnvelope.setDataHandler(getDataHandler());
337: AttachmentPartImpl.copyMimeHeaders(headers, headerEnvelope);
338:
339: return headerEnvelope;
340: } catch (SOAPException ex) {
341: throw ex;
342: } catch (Exception ex) {
343: log.severe("SAAJ0548.soap.cannot.externalize.hdr");
344: throw new SOAPExceptionImpl("Unable to externalize header",
345: ex);
346: }
347: }
348:
349: MimeHeaders getMimeHeaders() {
350: return headers;
351: }
352:
353: DataHandler getDataHandler() {
354: DataSource ds = new DataSource() {
355: public OutputStream getOutputStream() throws IOException {
356: throw new IOException("Illegal Operation");
357: }
358:
359: public String getContentType() {
360: return getContentTypeString();
361: }
362:
363: public String getName() {
364: return getContentId();
365: }
366:
367: public InputStream getInputStream() throws IOException {
368: return getContentAsStream();
369: }
370: };
371: return new DataHandler(ds);
372: }
373:
374: public SOAPDocumentImpl getDocument() {
375: handleNewSource();
376: return document;
377: }
378:
379: public SOAPPartImpl getSOAPPart() {
380: return this ;
381: }
382:
383: public DocumentType getDoctype() {
384: return document.getDoctype();
385: }
386:
387: // Forward all of these calls to the document to ensure that they work the
388: // same way whether they are called from here or directly from the document.
389: // If the document needs any help from this SOAPPart then
390: // Make it use a call-back as in doGetDocumentElement() below
391: public DOMImplementation getImplementation() {
392: return document.getImplementation();
393: }
394:
395: public Element getDocumentElement() {
396: // If there is no SOAP envelope already created, then create
397: // one from a source if one exists. If there is a newer source
398: // then use that source.
399: try {
400: getEnvelope();
401: } catch (SOAPException e) {
402: }
403: return document.getDocumentElement();
404: }
405:
406: protected void doGetDocumentElement() {
407: handleNewSource();
408: try {
409: lookForEnvelope();
410: } catch (SOAPException e) {
411: }
412: }
413:
414: public Element createElement(String tagName) throws DOMException {
415: return document.createElement(tagName);
416: }
417:
418: public DocumentFragment createDocumentFragment() {
419: return document.createDocumentFragment();
420: }
421:
422: public org.w3c.dom.Text createTextNode(String data) {
423: return document.createTextNode(data);
424: }
425:
426: public Comment createComment(String data) {
427: return document.createComment(data);
428: }
429:
430: public CDATASection createCDATASection(String data)
431: throws DOMException {
432: return document.createCDATASection(data);
433: }
434:
435: public ProcessingInstruction createProcessingInstruction(
436: String target, String data) throws DOMException {
437: return document.createProcessingInstruction(target, data);
438: }
439:
440: public Attr createAttribute(String name) throws DOMException {
441: return document.createAttribute(name);
442: }
443:
444: public EntityReference createEntityReference(String name)
445: throws DOMException {
446: return document.createEntityReference(name);
447: }
448:
449: public NodeList getElementsByTagName(String tagname) {
450: handleNewSource();
451: return document.getElementsByTagName(tagname);
452: }
453:
454: public org.w3c.dom.Node importNode(org.w3c.dom.Node importedNode,
455: boolean deep) throws DOMException {
456: handleNewSource();
457: return document.importNode(importedNode, deep);
458: }
459:
460: public Element createElementNS(String namespaceURI,
461: String qualifiedName) throws DOMException {
462: return document.createElementNS(namespaceURI, qualifiedName);
463: }
464:
465: public Attr createAttributeNS(String namespaceURI,
466: String qualifiedName) throws DOMException {
467: return document.createAttributeNS(namespaceURI, qualifiedName);
468: }
469:
470: public NodeList getElementsByTagNameNS(String namespaceURI,
471: String localName) {
472: handleNewSource();
473: return document.getElementsByTagNameNS(namespaceURI, localName);
474: }
475:
476: public Element getElementById(String elementId) {
477: handleNewSource();
478: return document.getElementById(elementId);
479: }
480:
481: public org.w3c.dom.Node appendChild(org.w3c.dom.Node newChild)
482: throws DOMException {
483: handleNewSource();
484: return document.appendChild(newChild);
485: }
486:
487: public org.w3c.dom.Node cloneNode(boolean deep) {
488: handleNewSource();
489: return document.cloneNode(deep);
490: }
491:
492: protected SOAPPartImpl doCloneNode() {
493: handleNewSource();
494: SOAPPartImpl newSoapPart = duplicateType();
495:
496: newSoapPart.headers = MimeHeadersUtil.copy(this .headers);
497: newSoapPart.source = this .source;
498: return newSoapPart;
499: }
500:
501: public NamedNodeMap getAttributes() {
502: return document.getAttributes();
503: }
504:
505: public NodeList getChildNodes() {
506: handleNewSource();
507: return document.getChildNodes();
508: }
509:
510: public org.w3c.dom.Node getFirstChild() {
511: handleNewSource();
512: return document.getFirstChild();
513: }
514:
515: public org.w3c.dom.Node getLastChild() {
516: handleNewSource();
517: return document.getLastChild();
518: }
519:
520: public String getLocalName() {
521: return document.getLocalName();
522: }
523:
524: public String getNamespaceURI() {
525: return document.getNamespaceURI();
526: }
527:
528: public org.w3c.dom.Node getNextSibling() {
529: handleNewSource();
530: return document.getNextSibling();
531: }
532:
533: public String getNodeName() {
534: return document.getNodeName();
535: }
536:
537: public short getNodeType() {
538: return document.getNodeType();
539: }
540:
541: public String getNodeValue() throws DOMException {
542: return document.getNodeValue();
543: }
544:
545: public Document getOwnerDocument() {
546: return document.getOwnerDocument();
547: }
548:
549: public org.w3c.dom.Node getParentNode() {
550: return document.getParentNode();
551: }
552:
553: public String getPrefix() {
554: return document.getPrefix();
555: }
556:
557: public org.w3c.dom.Node getPreviousSibling() {
558: return document.getPreviousSibling();
559: }
560:
561: public boolean hasAttributes() {
562: return document.hasAttributes();
563: }
564:
565: public boolean hasChildNodes() {
566: handleNewSource();
567: return document.hasChildNodes();
568: }
569:
570: public org.w3c.dom.Node insertBefore(org.w3c.dom.Node arg0,
571: org.w3c.dom.Node arg1) throws DOMException {
572: handleNewSource();
573: return document.insertBefore(arg0, arg1);
574: }
575:
576: public boolean isSupported(String arg0, String arg1) {
577: return document.isSupported(arg0, arg1);
578: }
579:
580: public void normalize() {
581: handleNewSource();
582: document.normalize();
583: }
584:
585: public org.w3c.dom.Node removeChild(org.w3c.dom.Node arg0)
586: throws DOMException {
587: handleNewSource();
588: return document.removeChild(arg0);
589: }
590:
591: public org.w3c.dom.Node replaceChild(org.w3c.dom.Node arg0,
592: org.w3c.dom.Node arg1) throws DOMException {
593: handleNewSource();
594: return document.replaceChild(arg0, arg1);
595: }
596:
597: public void setNodeValue(String arg0) throws DOMException {
598: document.setNodeValue(arg0);
599: }
600:
601: public void setPrefix(String arg0) throws DOMException {
602: document.setPrefix(arg0);
603: }
604:
605: private void handleNewSource() {
606: if (sourceWasSet) {
607: // There is a newer source use that source.
608: try {
609: getEnvelope();
610: } catch (SOAPException e) {
611: }
612: }
613: }
614:
615: protected XMLDeclarationParser lookForXmlDecl()
616: throws SOAPException {
617: if ((source != null) && (source instanceof StreamSource)) {
618:
619: Reader reader = null;
620:
621: InputStream inputStream = ((StreamSource) source)
622: .getInputStream();
623: if (inputStream != null) {
624: if (sourceCharsetEncoding == null) {
625: reader = new InputStreamReader(inputStream);
626: } else {
627: try {
628: reader = new InputStreamReader(inputStream,
629: sourceCharsetEncoding);
630: } catch (UnsupportedEncodingException uee) {
631: log.log(Level.SEVERE,
632: "SAAJ0551.soap.unsupported.encoding",
633: new Object[] { sourceCharsetEncoding });
634: throw new SOAPExceptionImpl(
635: "Unsupported encoding "
636: + sourceCharsetEncoding, uee);
637: }
638: }
639: } else {
640: reader = ((StreamSource) source).getReader();
641: }
642: if (reader != null) {
643: PushbackReader pushbackReader = new PushbackReader(
644: reader, 4096); //some size to unread <?xml ....?>
645: XMLDeclarationParser ev = new XMLDeclarationParser(
646: pushbackReader);
647: try {
648: ev.parse();
649: } catch (Exception e) {
650: log.log(Level.SEVERE,
651: "SAAJ0552.soap.xml.decl.parsing.failed");
652: throw new SOAPExceptionImpl(
653: "XML declaration parsing failed", e);
654: }
655: String xmlDecl = ev.getXmlDeclaration();
656: if ((xmlDecl != null) && (xmlDecl.length() > 0))
657: this .omitXmlDecl = false;
658: return ev;
659: }
660: }
661: return null;
662: }
663:
664: public void setSourceCharsetEncoding(String charset) {
665: this .sourceCharsetEncoding = charset;
666: }
667:
668: public org.w3c.dom.Node renameNode(org.w3c.dom.Node n,
669: String namespaceURI, String qualifiedName)
670: throws DOMException {
671: handleNewSource();
672: return document.renameNode(n, namespaceURI, qualifiedName);
673: }
674:
675: public void normalizeDocument() {
676: document.normalizeDocument();
677: }
678:
679: public DOMConfiguration getDomConfig() {
680: return document.getDomConfig();
681: }
682:
683: public org.w3c.dom.Node adoptNode(org.w3c.dom.Node source)
684: throws DOMException {
685: handleNewSource();
686: return document.adoptNode(source);
687: }
688:
689: public void setDocumentURI(String documentURI) {
690: document.setDocumentURI(documentURI);
691: }
692:
693: public String getDocumentURI() {
694: return document.getDocumentURI();
695: }
696:
697: public void setStrictErrorChecking(boolean strictErrorChecking) {
698: document.setStrictErrorChecking(strictErrorChecking);
699: }
700:
701: public String getInputEncoding() {
702: return document.getInputEncoding();
703: }
704:
705: public String getXmlEncoding() {
706: return document.getXmlEncoding();
707: }
708:
709: public boolean getXmlStandalone() {
710: return document.getXmlStandalone();
711: }
712:
713: public void setXmlStandalone(boolean xmlStandalone)
714: throws DOMException {
715: document.setXmlStandalone(xmlStandalone);
716: }
717:
718: public String getXmlVersion() {
719: return document.getXmlVersion();
720: }
721:
722: public void setXmlVersion(String xmlVersion) throws DOMException {
723: document.setXmlVersion(xmlVersion);
724: }
725:
726: public boolean getStrictErrorChecking() {
727: return document.getStrictErrorChecking();
728: }
729:
730: // DOM L3 methods from org.w3c.dom.Node
731: public String getBaseURI() {
732: return document.getBaseURI();
733: }
734:
735: public short compareDocumentPosition(org.w3c.dom.Node other)
736: throws DOMException {
737: return document.compareDocumentPosition(other);
738: }
739:
740: public String getTextContent() throws DOMException {
741: return document.getTextContent();
742: }
743:
744: public void setTextContent(String textContent) throws DOMException {
745: document.setTextContent(textContent);
746: }
747:
748: public boolean isSameNode(org.w3c.dom.Node other) {
749: return document.isSameNode(other);
750: }
751:
752: public String lookupPrefix(String namespaceURI) {
753: return document.lookupPrefix(namespaceURI);
754: }
755:
756: public boolean isDefaultNamespace(String namespaceURI) {
757: return document.isDefaultNamespace(namespaceURI);
758: }
759:
760: public String lookupNamespaceURI(String prefix) {
761: return document.lookupNamespaceURI(prefix);
762: }
763:
764: public boolean isEqualNode(org.w3c.dom.Node arg) {
765: return document.isEqualNode(arg);
766: }
767:
768: public Object getFeature(String feature, String version) {
769: return document.getFeature(feature, version);
770: }
771:
772: public Object setUserData(String key, Object data,
773: UserDataHandler handler) {
774: return document.setUserData(key, data, handler);
775: }
776:
777: public Object getUserData(String key) {
778: return document.getUserData(key);
779: }
780:
781: public void recycleNode() {
782: // Nothing seems to be required to be done here
783: }
784:
785: public String getValue() {
786: return null;
787: }
788:
789: public void setValue(String value) {
790: log.severe("SAAJ0571.soappart.setValue.not.defined");
791: throw new IllegalStateException(
792: "Setting value of a soap part is not defined");
793: }
794:
795: public void setParentElement(SOAPElement parent)
796: throws SOAPException {
797: log.severe("SAAJ0570.soappart.parent.element.not.defined");
798: throw new SOAPExceptionImpl(
799: "The parent element of a soap part is not defined");
800: }
801:
802: public SOAPElement getParentElement() {
803: return null;
804: }
805:
806: public void detachNode() {
807: // Nothing seems to be required to be done here
808: }
809: }
|