001/* 002 * The MIT License 003 * Copyright (c) 2012 Microsoft Corporation 004 * 005 * Permission is hereby granted, free of charge, to any person obtaining a copy 006 * of this software and associated documentation files (the "Software"), to deal 007 * in the Software without restriction, including without limitation the rights 008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 009 * copies of the Software, and to permit persons to whom the Software is 010 * furnished to do so, subject to the following conditions: 011 * 012 * The above copyright notice and this permission notice shall be included in 013 * all copies or substantial portions of the Software. 014 * 015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 021 * THE SOFTWARE. 022 */ 023 024package microsoft.exchange.webservices.data.autodiscover.request; 025 026import microsoft.exchange.webservices.data.EWSConstants; 027import microsoft.exchange.webservices.data.autodiscover.AutodiscoverService; 028import microsoft.exchange.webservices.data.autodiscover.enumeration.AutodiscoverErrorCode; 029import microsoft.exchange.webservices.data.autodiscover.exception.AutodiscoverResponseException; 030import microsoft.exchange.webservices.data.autodiscover.response.AutodiscoverResponse; 031import microsoft.exchange.webservices.data.core.EwsServiceXmlWriter; 032import microsoft.exchange.webservices.data.core.EwsUtilities; 033import microsoft.exchange.webservices.data.core.EwsXmlReader; 034import microsoft.exchange.webservices.data.core.ExchangeServerInfo; 035import microsoft.exchange.webservices.data.core.XmlElementNames; 036import microsoft.exchange.webservices.data.core.request.HttpWebRequest; 037import microsoft.exchange.webservices.data.core.response.ServiceResponse; 038import microsoft.exchange.webservices.data.core.enumeration.misc.TraceFlags; 039import microsoft.exchange.webservices.data.core.enumeration.misc.XmlNamespace; 040import microsoft.exchange.webservices.data.core.exception.http.EWSHttpException; 041import microsoft.exchange.webservices.data.core.exception.service.remote.ServiceRemoteException; 042import microsoft.exchange.webservices.data.core.exception.service.remote.ServiceRequestException; 043import microsoft.exchange.webservices.data.core.exception.service.remote.ServiceResponseException; 044import microsoft.exchange.webservices.data.core.exception.service.local.ServiceXmlDeserializationException; 045import microsoft.exchange.webservices.data.core.exception.service.local.ServiceXmlSerializationException; 046import microsoft.exchange.webservices.data.misc.SoapFaultDetails; 047import microsoft.exchange.webservices.data.security.XmlNodeType; 048import org.apache.commons.logging.Log; 049import org.apache.commons.logging.LogFactory; 050 051import javax.xml.stream.XMLStreamException; 052 053import java.io.ByteArrayInputStream; 054import java.io.ByteArrayOutputStream; 055import java.io.IOException; 056import java.io.InputStream; 057import java.io.OutputStream; 058import java.net.URI; 059import java.net.URISyntaxException; 060import java.util.zip.GZIPInputStream; 061import java.util.zip.InflaterInputStream; 062 063/** 064 * Represents the base class for all requested made to the Autodiscover service. 065 */ 066public abstract class AutodiscoverRequest { 067 068 private static final Log LOG = LogFactory.getLog(AutodiscoverRequest.class); 069 070 /** 071 * The service. 072 */ 073 private AutodiscoverService service; 074 075 /** 076 * The url. 077 */ 078 private URI url; 079 080 /** 081 * Initializes a new instance of the AutodiscoverResponse class. 082 * 083 * @param service Autodiscover service associated with this request. 084 * @param url URL of Autodiscover service. 085 */ 086 protected AutodiscoverRequest(AutodiscoverService service, URI url) { 087 this.service = service; 088 this.url = url; 089 } 090 091 /** 092 * Determines whether response is a redirection. 093 * 094 * @param request the request 095 * @return True if redirection response. 096 * @throws EWSHttpException the EWS http exception 097 */ 098 public static boolean isRedirectionResponse(HttpWebRequest request) 099 throws EWSHttpException { 100 return ((request.getResponseCode() == 301) 101 || (request.getResponseCode() == 302) 102 || (request.getResponseCode() == 307) || (request 103 .getResponseCode() == 303)); 104 } 105 106 /** 107 * Validates the request. 108 * 109 * @throws Exception the exception 110 */ 111 protected void validate() throws Exception { 112 this.getService().validate(); 113 } 114 115 /** 116 * Executes this instance. 117 * 118 * @return the autodiscover response 119 * @throws Exception the exception 120 */ 121 protected AutodiscoverResponse internalExecute() throws Exception { 122 this.validate(); 123 HttpWebRequest request = null; 124 try { 125 request = this.service.prepareHttpWebRequestForUrl(this.url); 126 this.service.traceHttpRequestHeaders( 127 TraceFlags.AutodiscoverRequestHttpHeaders, request); 128 129 boolean needSignature = this.getService().getCredentials() != null 130 && this.getService().getCredentials().isNeedSignature(); 131 boolean needTrace = this.getService().isTraceEnabledFor( 132 TraceFlags.AutodiscoverRequest); 133 134 OutputStream urlOutStream = request.getOutputStream(); 135 // OutputStreamWriter out = new OutputStreamWriter(request 136 // .getOutputStream()); 137 138 ByteArrayOutputStream memoryStream = new ByteArrayOutputStream(); 139 EwsServiceXmlWriter writer = new EwsServiceXmlWriter(this 140 .getService(), memoryStream); 141 writer.setRequireWSSecurityUtilityNamespace(needSignature); 142 this.writeSoapRequest(this.url, writer); 143 144 if (needSignature) { 145 this.service.getCredentials().sign(memoryStream); 146 } 147 148 if (needTrace) { 149 memoryStream.flush(); 150 this.service.traceXml(TraceFlags.AutodiscoverRequest, 151 memoryStream); 152 } 153 memoryStream.writeTo(urlOutStream); 154 urlOutStream.flush(); 155 urlOutStream.close(); 156 memoryStream.close(); 157 // out.write(memoryStream.toString()); 158 // out.close(); 159 request.executeRequest(); 160 request.getResponseCode(); 161 if (AutodiscoverRequest.isRedirectionResponse(request)) { 162 AutodiscoverResponse response = this 163 .createRedirectionResponse(request); 164 if (response != null) { 165 return response; 166 } else { 167 throw new ServiceRemoteException("The service returned an invalid redirection response."); 168 } 169 } 170 171 memoryStream = new ByteArrayOutputStream(); 172 InputStream serviceResponseStream = request.getInputStream(); 173 174 while (true) { 175 int data = serviceResponseStream.read(); 176 if (-1 == data) { 177 break; 178 } else { 179 memoryStream.write(data); 180 } 181 } 182 memoryStream.flush(); 183 serviceResponseStream.close(); 184 185 if (this.service.isTraceEnabled()) { 186 this.service.traceResponse(request, memoryStream); 187 } 188 ByteArrayInputStream memoryStreamIn = new ByteArrayInputStream( 189 memoryStream.toByteArray()); 190 EwsXmlReader ewsXmlReader = new EwsXmlReader(memoryStreamIn); 191 192 // WCF may not generate an XML declaration. 193 ewsXmlReader.read(); 194 if (ewsXmlReader.getNodeType().getNodeType() == XmlNodeType.START_DOCUMENT) { 195 ewsXmlReader.readStartElement(XmlNamespace.Soap, 196 XmlElementNames.SOAPEnvelopeElementName); 197 } else if ((ewsXmlReader.getNodeType().getNodeType() != XmlNodeType.START_ELEMENT) 198 || (!ewsXmlReader.getLocalName().equals( 199 XmlElementNames.SOAPEnvelopeElementName)) 200 || (!ewsXmlReader.getNamespaceUri().equals( 201 EwsUtilities.getNamespaceUri(XmlNamespace.Soap)))) { 202 throw new ServiceXmlDeserializationException("The Autodiscover service response was invalid."); 203 } 204 205 this.readSoapHeaders(ewsXmlReader); 206 207 AutodiscoverResponse response = this.readSoapBody(ewsXmlReader); 208 209 ewsXmlReader.readEndElement(XmlNamespace.Soap, 210 XmlElementNames.SOAPEnvelopeElementName); 211 212 if (response.getErrorCode() == AutodiscoverErrorCode.NoError) { 213 return response; 214 } else { 215 throw new AutodiscoverResponseException( 216 response.getErrorCode(), response.getErrorMessage()); 217 } 218 219 } catch (XMLStreamException ex) { 220 this.service.traceMessage(TraceFlags.AutodiscoverConfiguration, 221 String.format("XML parsing error: %s", ex.getMessage())); 222 223 // Wrap exception 224 throw new ServiceRequestException(String.format("The request failed. %s", ex.getMessage()), ex); 225 } catch (IOException ex) { 226 this.service.traceMessage(TraceFlags.AutodiscoverConfiguration, 227 String.format("I/O error: %s", ex.getMessage())); 228 229 // Wrap exception 230 throw new ServiceRequestException(String.format("The request failed. %s", ex.getMessage()), ex); 231 } catch (Exception ex) { 232 // HttpWebRequest httpWebResponse = (HttpWebRequest)ex; 233 234 if (null != request && request.getResponseCode() == 7) { 235 if (AutodiscoverRequest.isRedirectionResponse(request)) { 236 this.service 237 .processHttpResponseHeaders( 238 TraceFlags.AutodiscoverResponseHttpHeaders, 239 request); 240 241 AutodiscoverResponse response = this 242 .createRedirectionResponse(request); 243 if (response != null) { 244 return response; 245 } 246 } else { 247 this.processWebException(ex, request); 248 } 249 } 250 251 // Wrap exception if the above code block didn't throw 252 throw new ServiceRequestException(String.format("The request failed. %s", ex.getMessage()), ex); 253 } finally { 254 try { 255 if (request != null) { 256 request.close(); 257 } 258 } catch (Exception e) { 259 // do nothing 260 } 261 } 262 } 263 264 /** 265 * Processes the web exception. 266 * 267 * @param exception WebException 268 * @param req HttpWebRequest 269 */ 270 private void processWebException(Exception exception, HttpWebRequest req) { 271 if (null != req) { 272 try { 273 if (500 == req.getResponseCode()) { 274 if (this.service 275 .isTraceEnabledFor( 276 TraceFlags.AutodiscoverRequest)) { 277 ByteArrayOutputStream memoryStream = 278 new ByteArrayOutputStream(); 279 InputStream serviceResponseStream = AutodiscoverRequest 280 .getResponseStream(req); 281 while (true) { 282 int data = serviceResponseStream.read(); 283 if (-1 == data) { 284 break; 285 } else { 286 memoryStream.write(data); 287 } 288 } 289 memoryStream.flush(); 290 serviceResponseStream.close(); 291 this.service.traceResponse(req, memoryStream); 292 ByteArrayInputStream memoryStreamIn = 293 new ByteArrayInputStream( 294 memoryStream.toByteArray()); 295 EwsXmlReader reader = new EwsXmlReader(memoryStreamIn); 296 this.readSoapFault(reader); 297 memoryStream.close(); 298 } else { 299 InputStream serviceResponseStream = AutodiscoverRequest 300 .getResponseStream(req); 301 EwsXmlReader reader = new EwsXmlReader( 302 serviceResponseStream); 303 SoapFaultDetails soapFaultDetails = this.readSoapFault(reader); 304 serviceResponseStream.close(); 305 306 if (soapFaultDetails != null) { 307 throw new ServiceResponseException( 308 new ServiceResponse(soapFaultDetails)); 309 } 310 } 311 } else { 312 this.service.processHttpErrorResponse(req, exception); 313 } 314 } catch (Exception e) { 315 LOG.error(e); 316 } 317 } 318 } 319 320 /** 321 * Create a redirection response. 322 * 323 * @param httpWebResponse the HTTP web response 324 * @return AutodiscoverResponse autodiscoverResponse object 325 * @throws XMLStreamException the XML stream exception 326 * @throws IOException signals that an I/O exception has occurred 327 * @throws EWSHttpException the EWS http exception 328 */ 329 private AutodiscoverResponse createRedirectionResponse( 330 HttpWebRequest httpWebResponse) throws XMLStreamException, 331 IOException, EWSHttpException { 332 String location = httpWebResponse.getResponseHeaderField("Location"); 333 if (!(location == null || location.isEmpty())) { 334 try { 335 URI redirectionUri = new URI(location); 336 String scheme = redirectionUri.getScheme(); 337 338 if (scheme.equalsIgnoreCase(EWSConstants.HTTP_SCHEME) 339 || scheme.equalsIgnoreCase(EWSConstants.HTTPS_SCHEME)) { 340 AutodiscoverResponse response = this.createServiceResponse(); 341 response.setErrorCode(AutodiscoverErrorCode.RedirectUrl); 342 response.setRedirectionUrl(redirectionUri); 343 return response; 344 } 345 346 this.service 347 .traceMessage( 348 TraceFlags.AutodiscoverConfiguration, 349 String 350 .format( 351 "Invalid redirection" + 352 " URL '%s' " + 353 "returned by Autodiscover " + 354 "service.", 355 redirectionUri.toString())); 356 357 } catch (URISyntaxException ex) { 358 this.service 359 .traceMessage( 360 TraceFlags.AutodiscoverConfiguration, 361 String 362 .format( 363 "Invalid redirection " + 364 "location '%s' " + 365 "returned by Autodiscover " + 366 "service.", 367 location)); 368 } 369 } else { 370 this.service 371 .traceMessage( 372 TraceFlags.AutodiscoverConfiguration, 373 "Redirection response returned by Autodiscover " + 374 "service without redirection location."); 375 } 376 377 return null; 378 } 379 380 /** 381 * Reads the SOAP fault. 382 * 383 * @param reader The reader. 384 * @return SOAP fault details. 385 */ 386 private SoapFaultDetails readSoapFault(EwsXmlReader reader) { 387 SoapFaultDetails soapFaultDetails = null; 388 389 try { 390 391 reader.read(); 392 if (reader.getNodeType().getNodeType() == XmlNodeType.START_DOCUMENT) { 393 reader.read(); 394 } 395 if (!reader.isStartElement() 396 || (!reader.getLocalName().equals( 397 XmlElementNames.SOAPEnvelopeElementName))) { 398 return null; 399 } 400 401 // Get the namespace URI from the envelope element and use it for 402 // the rest of the parsing. 403 // If it's not 1.1 or 1.2, we can't continue. 404 XmlNamespace soapNamespace = EwsUtilities 405 .getNamespaceFromUri(reader.getNamespaceUri()); 406 if (soapNamespace == XmlNamespace.NotSpecified) { 407 return null; 408 } 409 410 reader.read(); 411 412 // Skip SOAP header. 413 if (reader.isStartElement(soapNamespace, 414 XmlElementNames.SOAPHeaderElementName)) { 415 do { 416 reader.read(); 417 } while (!reader.isEndElement(soapNamespace, 418 XmlElementNames.SOAPHeaderElementName)); 419 420 // Queue up the next read 421 reader.read(); 422 } 423 424 // Parse the fault element contained within the SOAP body. 425 if (reader.isStartElement(soapNamespace, 426 XmlElementNames.SOAPBodyElementName)) { 427 do { 428 reader.read(); 429 430 // Parse Fault element 431 if (reader.isStartElement(soapNamespace, 432 XmlElementNames.SOAPFaultElementName)) { 433 soapFaultDetails = SoapFaultDetails.parse(reader, 434 soapNamespace); 435 } 436 } while (!reader.isEndElement(soapNamespace, 437 XmlElementNames.SOAPBodyElementName)); 438 } 439 440 reader.readEndElement(soapNamespace, 441 XmlElementNames.SOAPEnvelopeElementName); 442 } catch (Exception e) { 443 // If response doesn't contain a valid SOAP fault, just ignore 444 // exception and 445 // return null for SOAP fault details. 446 LOG.error(e); 447 } 448 449 return soapFaultDetails; 450 } 451 452 /** 453 * Writes the autodiscover SOAP request. 454 * 455 * @param requestUrl request URL 456 * @param writer writer object 457 * @throws XMLStreamException the XML stream exception 458 * @throws ServiceXmlSerializationException the service xml serialization exception 459 */ 460 protected void writeSoapRequest(URI requestUrl, 461 EwsServiceXmlWriter writer) throws XMLStreamException, ServiceXmlSerializationException { 462 463 if (writer.isRequireWSSecurityUtilityNamespace()) { 464 writer.writeAttributeValue("xmlns", 465 EwsUtilities.WSSecurityUtilityNamespacePrefix, 466 EwsUtilities.WSSecurityUtilityNamespace); 467 } 468 writer.writeStartDocument(); 469 writer.writeStartElement(XmlNamespace.Soap, 470 XmlElementNames.SOAPEnvelopeElementName); 471 writer.writeAttributeValue("xmlns", EwsUtilities 472 .getNamespacePrefix(XmlNamespace.Soap), EwsUtilities 473 .getNamespaceUri(XmlNamespace.Soap)); 474 writer.writeAttributeValue("xmlns", 475 EwsUtilities.AutodiscoverSoapNamespacePrefix, 476 EwsUtilities.AutodiscoverSoapNamespace); 477 writer.writeAttributeValue("xmlns", 478 EwsUtilities.WSAddressingNamespacePrefix, 479 EwsUtilities.WSAddressingNamespace); 480 writer.writeAttributeValue("xmlns", 481 EwsUtilities.EwsXmlSchemaInstanceNamespacePrefix, 482 EwsUtilities.EwsXmlSchemaInstanceNamespace); 483 484 writer.writeStartElement(XmlNamespace.Soap, 485 XmlElementNames.SOAPHeaderElementName); 486 487 if (this.service.getCredentials() != null) { 488 this.service.getCredentials().emitExtraSoapHeaderNamespaceAliases( 489 writer.getInternalWriter()); 490 } 491 492 writer.writeElementValue(XmlNamespace.Autodiscover, 493 XmlElementNames.RequestedServerVersion, this.service 494 .getRequestedServerVersion().toString()); 495 496 writer.writeElementValue(XmlNamespace.WSAddressing, 497 XmlElementNames.Action, this.getWsAddressingActionName()); 498 499 writer.writeElementValue(XmlNamespace.WSAddressing, XmlElementNames.To, 500 requestUrl.toString()); 501 502 this.writeExtraCustomSoapHeadersToXml(writer); 503 504 if (this.service.getCredentials() != null) { 505 this.service.getCredentials().serializeWSSecurityHeaders( 506 writer.getInternalWriter()); 507 } 508 509 this.service.doOnSerializeCustomSoapHeaders(writer.getInternalWriter()); 510 511 writer.writeEndElement(); // soap:Header 512 513 writer.writeStartElement(XmlNamespace.Soap, 514 XmlElementNames.SOAPBodyElementName); 515 516 this.writeBodyToXml(writer); 517 518 writer.writeEndElement(); // soap:Body 519 writer.writeEndElement(); // soap:Envelope 520 writer.flush(); 521 writer.dispose(); 522 } 523 524 /** 525 * Write extra headers. 526 * 527 * @param writer the writer 528 * @throws ServiceXmlSerializationException the service xml serialization exception 529 * @throws XMLStreamException the XML stream exception 530 */ 531 protected void writeExtraCustomSoapHeadersToXml(EwsServiceXmlWriter writer) 532 throws XMLStreamException, ServiceXmlSerializationException { 533 // do nothing here. 534 // currently used only by GetUserSettingRequest to emit the BinarySecret header. 535 } 536 537 538 /** 539 * Writes XML body. 540 * 541 * @param writer the writer 542 * @throws ServiceXmlSerializationException the service xml serialization exception 543 * @throws XMLStreamException the XML stream exception 544 */ 545 protected void writeBodyToXml(EwsServiceXmlWriter writer) 546 throws ServiceXmlSerializationException, XMLStreamException { 547 writer.writeStartElement(XmlNamespace.Autodiscover, this 548 .getRequestXmlElementName()); 549 550 this.writeAttributesToXml(writer); 551 this.writeElementsToXml(writer); 552 553 writer.writeEndElement(); // m:this.GetXmlElementName() 554 } 555 556 /** 557 * Gets the response stream (may be wrapped with GZip/Deflate stream to 558 * decompress content). 559 * 560 * @param request the request 561 * @return ResponseStream 562 * @throws EWSHttpException the EWS http exception 563 * @throws IOException signals that an I/O exception has occurred. 564 */ 565 protected static InputStream getResponseStream(HttpWebRequest request) 566 throws EWSHttpException, IOException { 567 String contentEncoding = ""; 568 569 if (null != request.getContentEncoding()) { 570 contentEncoding = request.getContentEncoding().toLowerCase(); 571 } 572 573 InputStream responseStream; 574 575 if (contentEncoding.contains("gzip")) { 576 responseStream = new GZIPInputStream(request.getInputStream()); 577 } else if (contentEncoding.contains("deflate")) { 578 responseStream = new InflaterInputStream(request.getInputStream()); 579 } else { 580 responseStream = request.getInputStream(); 581 } 582 return responseStream; 583 } 584 585 /** 586 * Read SOAP header. 587 * 588 * @param reader EwsXmlReader. 589 * @throws Exception the exception 590 */ 591 protected void readSoapHeaders(EwsXmlReader reader) throws Exception { 592 reader.readStartElement(XmlNamespace.Soap, 593 XmlElementNames.SOAPHeaderElementName); 594 do { 595 reader.read(); 596 597 this.readSoapHeader(reader); 598 } while (!reader.isEndElement(XmlNamespace.Soap, 599 XmlElementNames.SOAPHeaderElementName)); 600 } 601 602 /** 603 * Reads a single SOAP header. 604 * 605 * @param reader EwsXmlReader 606 * @throws Exception on error 607 */ 608 protected void readSoapHeader(EwsXmlReader reader) throws Exception { 609 // Is this the ServerVersionInfo? 610 if (reader.isStartElement(XmlNamespace.Autodiscover, 611 XmlElementNames.ServerVersionInfo)) { 612 this.service.setServerInfo(this.readServerVersionInfo(reader)); 613 } 614 } 615 616 /** 617 * Read ServerVersionInfo SOAP header. 618 * 619 * @param reader EwsXmlReader. 620 * @return ExchangeServerInfo ExchangeServerInfo object 621 * @throws Exception the exception 622 */ 623 private ExchangeServerInfo readServerVersionInfo(EwsXmlReader reader) 624 throws Exception { 625 ExchangeServerInfo serverInfo = new ExchangeServerInfo(); 626 do { 627 reader.read(); 628 629 if (reader.isStartElement()) { 630 if (reader.getLocalName().equals(XmlElementNames.MajorVersion)) { 631 serverInfo.setMajorVersion(reader 632 .readElementValue(Integer.class)); 633 } else if (reader.getLocalName().equals( 634 XmlElementNames.MinorVersion)) { 635 serverInfo.setMinorVersion(reader 636 .readElementValue(Integer.class)); 637 } else if (reader.getLocalName().equals( 638 XmlElementNames.MajorBuildNumber)) { 639 serverInfo.setMajorBuildNumber(reader 640 .readElementValue(Integer.class)); 641 } else if (reader.getLocalName().equals( 642 XmlElementNames.MinorBuildNumber)) { 643 serverInfo.setMinorBuildNumber(reader 644 .readElementValue(Integer.class)); 645 } else if (reader.getLocalName() 646 .equals(XmlElementNames.Version)) { 647 serverInfo.setVersionString(reader.readElementValue()); 648 } 649 } 650 } while (!reader.isEndElement(XmlNamespace.Autodiscover, 651 XmlElementNames.ServerVersionInfo)); 652 653 return serverInfo; 654 } 655 656 /** 657 * Read SOAP body. 658 * 659 * @param reader EwsXmlReader. 660 * @return AutodiscoverResponse AutodiscoverResponse object 661 * @throws Exception the exception 662 */ 663 protected AutodiscoverResponse readSoapBody(EwsXmlReader reader) throws Exception { 664 reader.readStartElement(XmlNamespace.Soap, 665 XmlElementNames.SOAPBodyElementName); 666 AutodiscoverResponse responses = this.loadFromXml(reader); 667 reader.readEndElement(XmlNamespace.Soap, 668 XmlElementNames.SOAPBodyElementName); 669 return responses; 670 } 671 672 /** 673 * Loads response from XML. 674 * 675 * @param reader The reader. 676 * @return AutodiscoverResponse object 677 * @throws Exception the exception 678 */ 679 protected AutodiscoverResponse loadFromXml(EwsXmlReader reader) throws Exception { 680 String elementName = this.getResponseXmlElementName(); 681 reader.readStartElement(XmlNamespace.Autodiscover, elementName); 682 AutodiscoverResponse response = this.createServiceResponse(); 683 response.loadFromXml(reader, elementName); 684 return response; 685 } 686 687 /** 688 * Gets the name of the request XML element. 689 * 690 * @return RequestXmlElementName gets XmlElementName. 691 */ 692 protected abstract String getRequestXmlElementName(); 693 694 /** 695 * Gets the name of the response XML element. 696 * 697 * @return ResponseXmlElementName gets XmlElementName. 698 */ 699 protected abstract String getResponseXmlElementName(); 700 701 /** 702 * Gets the WS-Addressing action name. 703 * 704 * @return WsAddressingActionName gets WsAddressingActionName. 705 */ 706 protected abstract String getWsAddressingActionName(); 707 708 /** 709 * Creates the service response. 710 * 711 * @return AutodiscoverResponse AutodiscoverResponse object. 712 */ 713 protected abstract AutodiscoverResponse createServiceResponse(); 714 715 /** 716 * Writes attribute to request XML. 717 * 718 * @param writer The writer. 719 * @throws ServiceXmlSerializationException the service xml serialization exception 720 */ 721 protected abstract void writeAttributesToXml(EwsServiceXmlWriter writer) 722 throws ServiceXmlSerializationException; 723 724 /** 725 * Writes elements to request XML. 726 * 727 * @param writer the writer 728 * @throws XMLStreamException the XML stream exception 729 * @throws ServiceXmlSerializationException the service xml serialization exception 730 */ 731 protected abstract void writeElementsToXml(EwsServiceXmlWriter writer) 732 throws XMLStreamException, ServiceXmlSerializationException; 733 734 /** 735 * Gets the Service. 736 * 737 * @return AutodiscoverService AutodiscoverService object. 738 */ 739 protected AutodiscoverService getService() { 740 return this.service; 741 } 742 743 /** 744 * Gets the URL. 745 * 746 * @return url URL Object. 747 */ 748 protected URI getUrl() { 749 return this.url; 750 } 751}