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
024 package microsoft.exchange.webservices.data.autodiscover.request;
025
026 import microsoft.exchange.webservices.data.EWSConstants;
027 import microsoft.exchange.webservices.data.autodiscover.AutodiscoverService;
028 import microsoft.exchange.webservices.data.autodiscover.enumeration.AutodiscoverErrorCode;
029 import microsoft.exchange.webservices.data.autodiscover.exception.AutodiscoverResponseException;
030 import microsoft.exchange.webservices.data.autodiscover.response.AutodiscoverResponse;
031 import microsoft.exchange.webservices.data.core.EwsServiceXmlWriter;
032 import microsoft.exchange.webservices.data.core.EwsUtilities;
033 import microsoft.exchange.webservices.data.core.EwsXmlReader;
034 import microsoft.exchange.webservices.data.core.ExchangeServerInfo;
035 import microsoft.exchange.webservices.data.core.XmlElementNames;
036 import microsoft.exchange.webservices.data.core.request.HttpWebRequest;
037 import microsoft.exchange.webservices.data.core.response.ServiceResponse;
038 import microsoft.exchange.webservices.data.core.enumeration.misc.TraceFlags;
039 import microsoft.exchange.webservices.data.core.enumeration.misc.XmlNamespace;
040 import microsoft.exchange.webservices.data.core.exception.http.EWSHttpException;
041 import microsoft.exchange.webservices.data.core.exception.service.remote.ServiceRemoteException;
042 import microsoft.exchange.webservices.data.core.exception.service.remote.ServiceRequestException;
043 import microsoft.exchange.webservices.data.core.exception.service.remote.ServiceResponseException;
044 import microsoft.exchange.webservices.data.core.exception.service.local.ServiceXmlDeserializationException;
045 import microsoft.exchange.webservices.data.core.exception.service.local.ServiceXmlSerializationException;
046 import microsoft.exchange.webservices.data.misc.SoapFaultDetails;
047 import microsoft.exchange.webservices.data.security.XmlNodeType;
048 import org.apache.commons.logging.Log;
049 import org.apache.commons.logging.LogFactory;
050
051 import javax.xml.stream.XMLStreamException;
052
053 import java.io.ByteArrayInputStream;
054 import java.io.ByteArrayOutputStream;
055 import java.io.IOException;
056 import java.io.InputStream;
057 import java.io.OutputStream;
058 import java.net.URI;
059 import java.net.URISyntaxException;
060 import java.util.zip.GZIPInputStream;
061 import java.util.zip.InflaterInputStream;
062
063 /**
064 * Represents the base class for all requested made to the Autodiscover service.
065 */
066 public 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 }