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.core; 025 026import java.net.URI; 027import java.net.URISyntaxException; 028import java.util.ArrayList; 029import java.util.Arrays; 030import java.util.Collection; 031import java.util.Date; 032import java.util.EnumSet; 033import java.util.Enumeration; 034import java.util.HashMap; 035import java.util.Iterator; 036import java.util.List; 037import java.util.Locale; 038import java.util.Map; 039import java.util.TimeZone; 040 041import microsoft.exchange.webservices.data.autodiscover.AutodiscoverService; 042import microsoft.exchange.webservices.data.autodiscover.IAutodiscoverRedirectionUrl; 043import microsoft.exchange.webservices.data.autodiscover.enumeration.UserSettingName; 044import microsoft.exchange.webservices.data.autodiscover.exception.AutodiscoverLocalException; 045import microsoft.exchange.webservices.data.autodiscover.request.ApplyConversationActionRequest; 046import microsoft.exchange.webservices.data.autodiscover.response.GetUserSettingsResponse; 047import microsoft.exchange.webservices.data.core.enumeration.availability.AvailabilityData; 048import microsoft.exchange.webservices.data.core.enumeration.misc.ConversationActionType; 049import microsoft.exchange.webservices.data.core.enumeration.misc.DateTimePrecision; 050import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion; 051import microsoft.exchange.webservices.data.core.enumeration.misc.IdFormat; 052import microsoft.exchange.webservices.data.core.enumeration.misc.TraceFlags; 053import microsoft.exchange.webservices.data.core.enumeration.misc.UserConfigurationProperties; 054import microsoft.exchange.webservices.data.core.enumeration.notification.EventType; 055import microsoft.exchange.webservices.data.core.enumeration.property.BodyType; 056import microsoft.exchange.webservices.data.core.enumeration.property.WellKnownFolderName; 057import microsoft.exchange.webservices.data.core.enumeration.search.ResolveNameSearchLocation; 058import microsoft.exchange.webservices.data.core.enumeration.service.ConflictResolutionMode; 059import microsoft.exchange.webservices.data.core.enumeration.service.DeleteMode; 060import microsoft.exchange.webservices.data.core.enumeration.service.MeetingRequestsDeliveryScope; 061import microsoft.exchange.webservices.data.core.enumeration.service.MessageDisposition; 062import microsoft.exchange.webservices.data.core.enumeration.service.SendCancellationsMode; 063import microsoft.exchange.webservices.data.core.enumeration.service.SendInvitationsMode; 064import microsoft.exchange.webservices.data.core.enumeration.service.SendInvitationsOrCancellationsMode; 065import microsoft.exchange.webservices.data.core.enumeration.service.SyncFolderItemsScope; 066import microsoft.exchange.webservices.data.core.enumeration.service.calendar.AffectedTaskOccurrence; 067import microsoft.exchange.webservices.data.core.enumeration.service.error.ServiceErrorHandling; 068import microsoft.exchange.webservices.data.core.exception.misc.ArgumentOutOfRangeException; 069import microsoft.exchange.webservices.data.core.exception.service.local.ServiceLocalException; 070import microsoft.exchange.webservices.data.core.exception.service.local.ServiceValidationException; 071import microsoft.exchange.webservices.data.core.exception.service.remote.AccountIsLockedException; 072import microsoft.exchange.webservices.data.core.exception.service.remote.ServiceRemoteException; 073import microsoft.exchange.webservices.data.core.exception.service.remote.ServiceResponseException; 074import microsoft.exchange.webservices.data.core.request.*; 075import microsoft.exchange.webservices.data.core.response.*; 076import microsoft.exchange.webservices.data.core.service.ServiceObject; 077import microsoft.exchange.webservices.data.core.service.folder.Folder; 078import microsoft.exchange.webservices.data.core.service.item.*; 079import microsoft.exchange.webservices.data.messaging.UnifiedMessaging; 080import microsoft.exchange.webservices.data.misc.AsyncCallback; 081import microsoft.exchange.webservices.data.misc.AsyncRequestResult; 082import microsoft.exchange.webservices.data.misc.ConversationAction; 083import microsoft.exchange.webservices.data.misc.DelegateInformation; 084import microsoft.exchange.webservices.data.misc.ExpandGroupResults; 085import microsoft.exchange.webservices.data.misc.FolderIdWrapper; 086import microsoft.exchange.webservices.data.misc.IAsyncResult; 087import microsoft.exchange.webservices.data.misc.ImpersonatedUserId; 088import microsoft.exchange.webservices.data.misc.NameResolutionCollection; 089import microsoft.exchange.webservices.data.misc.OutParam; 090import microsoft.exchange.webservices.data.misc.UserConfiguration; 091import microsoft.exchange.webservices.data.misc.availability.AttendeeInfo; 092import microsoft.exchange.webservices.data.misc.availability.AvailabilityOptions; 093import microsoft.exchange.webservices.data.misc.availability.GetUserAvailabilityResults; 094import microsoft.exchange.webservices.data.misc.availability.TimeWindow; 095import microsoft.exchange.webservices.data.misc.id.AlternateIdBase; 096import microsoft.exchange.webservices.data.notification.GetEventsResults; 097import microsoft.exchange.webservices.data.notification.PullSubscription; 098import microsoft.exchange.webservices.data.notification.PushSubscription; 099import microsoft.exchange.webservices.data.notification.StreamingSubscription; 100import microsoft.exchange.webservices.data.property.complex.Attachment; 101import microsoft.exchange.webservices.data.property.complex.ConversationId; 102import microsoft.exchange.webservices.data.property.complex.DelegateUser; 103import microsoft.exchange.webservices.data.property.complex.EmailAddress; 104import microsoft.exchange.webservices.data.property.complex.EmailAddressCollection; 105import microsoft.exchange.webservices.data.property.complex.FolderId; 106import microsoft.exchange.webservices.data.property.complex.ItemId; 107import microsoft.exchange.webservices.data.property.complex.Mailbox; 108import microsoft.exchange.webservices.data.property.complex.RuleCollection; 109import microsoft.exchange.webservices.data.property.complex.RuleOperation; 110import microsoft.exchange.webservices.data.property.complex.StringList; 111import microsoft.exchange.webservices.data.property.complex.UserId; 112import microsoft.exchange.webservices.data.property.complex.availability.OofSettings; 113import microsoft.exchange.webservices.data.property.complex.time.TimeZoneDefinition; 114import microsoft.exchange.webservices.data.property.definition.PropertyDefinitionBase; 115import microsoft.exchange.webservices.data.search.CalendarView; 116import microsoft.exchange.webservices.data.search.ConversationIndexedItemView; 117import microsoft.exchange.webservices.data.search.FindFoldersResults; 118import microsoft.exchange.webservices.data.search.FindItemsResults; 119import microsoft.exchange.webservices.data.search.FolderView; 120import microsoft.exchange.webservices.data.search.GroupedFindItemsResults; 121import microsoft.exchange.webservices.data.search.Grouping; 122import microsoft.exchange.webservices.data.search.ItemView; 123import microsoft.exchange.webservices.data.search.ViewBase; 124import microsoft.exchange.webservices.data.search.filter.SearchFilter; 125import microsoft.exchange.webservices.data.sync.ChangeCollection; 126import microsoft.exchange.webservices.data.sync.FolderChange; 127import microsoft.exchange.webservices.data.sync.ItemChange; 128 129import org.apache.commons.logging.Log; 130import org.apache.commons.logging.LogFactory; 131import org.apache.http.impl.client.CloseableHttpClient; 132import org.w3c.dom.Document; 133import org.w3c.dom.Node; 134 135/** 136 * Represents a binding to the Exchange Web Services. 137 */ 138public class ExchangeService extends ExchangeServiceBase implements IAutodiscoverRedirectionUrl { 139 140 private static final Log LOG = LogFactory.getLog(ExchangeService.class); 141 142 /** 143 * The url. 144 */ 145 private URI url; 146 147 /** 148 * The preferred culture. 149 */ 150 private Locale preferredCulture; 151 152 /** 153 * The DateTimePrecision 154 */ 155 private DateTimePrecision dateTimePrecision = DateTimePrecision.Default; 156 157 /** 158 * The impersonated user id. 159 */ 160 private ImpersonatedUserId impersonatedUserId; 161 // private Iterator<ItemId> Iterator; 162 /** 163 * The file attachment content handler. 164 */ 165 private IFileAttachmentContentHandler fileAttachmentContentHandler; 166 167 /** 168 * The unified messaging. 169 */ 170 private UnifiedMessaging unifiedMessaging; 171 172 private boolean enableScpLookup = true; 173 174 /** 175 * When false, used to indicate that we should use "Exchange2007" as the server version String rather than 176 * Exchange2007_SP1 (@see #getExchange2007CompatibilityMode). 177 * 178 */ 179 private boolean exchange2007CompatibilityMode = false; 180 181 /** 182 * Create response object. 183 * 184 * @param responseObject the response object 185 * @param parentFolderId the parent folder id 186 * @param messageDisposition the message disposition 187 * @return The list of item created or modified as a result of the 188 * "creation" of the response object. 189 * @throws Exception the exception 190 */ 191 public List<Item> internalCreateResponseObject(ServiceObject responseObject, FolderId parentFolderId, 192 MessageDisposition messageDisposition) throws Exception { 193 CreateResponseObjectRequest request = new CreateResponseObjectRequest( 194 this, ServiceErrorHandling.ThrowOnError); 195 Collection<ServiceObject> serviceList = new ArrayList<ServiceObject>(); 196 serviceList.add(responseObject); 197 request.setParentFolderId(parentFolderId); 198 request.setItems(serviceList); 199 request.setMessageDisposition(messageDisposition); 200 201 ServiceResponseCollection<CreateResponseObjectResponse> responses = request 202 .execute(); 203 204 return responses.getResponseAtIndex(0).getItems(); 205 } 206 207 /** 208 * Creates a folder. Calling this method results in a call to EWS. 209 * 210 * @param folder The folder. 211 * @param parentFolderId The parent folder Id 212 * @throws Exception the exception 213 */ 214 public void createFolder(Folder folder, FolderId parentFolderId) 215 throws Exception { 216 CreateFolderRequest request = new CreateFolderRequest(this, 217 ServiceErrorHandling.ThrowOnError); 218 List<Folder> folArry = new ArrayList<Folder>(); 219 folArry.add(folder); 220 request.setFolders(folArry); 221 request.setParentFolderId(parentFolderId); 222 223 request.execute(); 224 } 225 226 /** 227 * Updates a folder. 228 * 229 * @param folder The folder. 230 * @throws Exception the exception 231 */ 232 public void updateFolder(Folder folder) throws Exception { 233 UpdateFolderRequest request = new UpdateFolderRequest(this, 234 ServiceErrorHandling.ThrowOnError); 235 236 request.getFolders().add(folder); 237 238 request.execute(); 239 } 240 241 /** 242 * Copies a folder. Calling this method results in a call to EWS. 243 * 244 * @param folderId The folderId. 245 * @param destinationFolderId The destination folder id. 246 * @return the folder 247 * @throws Exception the exception 248 */ 249 public Folder copyFolder(FolderId folderId, FolderId destinationFolderId) 250 throws Exception { 251 CopyFolderRequest request = new CopyFolderRequest(this, 252 ServiceErrorHandling.ThrowOnError); 253 254 request.setDestinationFolderId(destinationFolderId); 255 request.getFolderIds().add(folderId); 256 257 ServiceResponseCollection<MoveCopyFolderResponse> responses = request 258 .execute(); 259 260 return responses.getResponseAtIndex(0).getFolder(); 261 } 262 263 /** 264 * Move a folder. 265 * 266 * @param folderId The folderId. 267 * @param destinationFolderId The destination folder id. 268 * @return the folder 269 * @throws Exception the exception 270 */ 271 public Folder moveFolder(FolderId folderId, FolderId destinationFolderId) 272 throws Exception { 273 MoveFolderRequest request = new MoveFolderRequest(this, 274 ServiceErrorHandling.ThrowOnError); 275 276 request.setDestinationFolderId(destinationFolderId); 277 request.getFolderIds().add(folderId); 278 279 ServiceResponseCollection<MoveCopyFolderResponse> responses = request 280 .execute(); 281 282 return responses.getResponseAtIndex(0).getFolder(); 283 } 284 285 /** 286 * Finds folder. 287 * 288 * @param parentFolderIds The parent folder ids. 289 * @param searchFilter The search filter. Available search filter classes include 290 * SearchFilter.IsEqualTo, SearchFilter.ContainsSubstring and 291 * SearchFilter.SearchFilterCollection 292 * @param view The view controlling the number of folder returned. 293 * @param errorHandlingMode Indicates the type of error handling should be done. 294 * @return Collection of service response. 295 * @throws Exception the exception 296 */ 297 private ServiceResponseCollection<FindFolderResponse> internalFindFolders( 298 Iterable<FolderId> parentFolderIds, SearchFilter searchFilter, 299 FolderView view, ServiceErrorHandling errorHandlingMode) 300 throws Exception { 301 FindFolderRequest request = new FindFolderRequest(this, 302 errorHandlingMode); 303 304 request.getParentFolderIds().addRangeFolderId(parentFolderIds); 305 request.setSearchFilter(searchFilter); 306 request.setView(view); 307 308 return request.execute(); 309 310 } 311 312 /** 313 * Obtains a list of folder by searching the sub-folder of the specified 314 * folder. 315 * 316 * @param parentFolderId The Id of the folder in which to search for folder. 317 * @param searchFilter The search filter. Available search filter classes include 318 * SearchFilter.IsEqualTo, SearchFilter.ContainsSubstring and 319 * SearchFilter.SearchFilterCollection 320 * @param view The view controlling the number of folder returned. 321 * @return An object representing the results of the search operation. 322 * @throws Exception the exception 323 */ 324 public FindFoldersResults findFolders(FolderId parentFolderId, 325 SearchFilter searchFilter, FolderView view) throws Exception { 326 EwsUtilities.validateParam(parentFolderId, "parentFolderId"); 327 EwsUtilities.validateParam(view, "view"); 328 EwsUtilities.validateParamAllowNull(searchFilter, "searchFilter"); 329 330 List<FolderId> folderIdArray = new ArrayList<FolderId>(); 331 folderIdArray.add(parentFolderId); 332 ServiceResponseCollection<FindFolderResponse> responses = this 333 .internalFindFolders(folderIdArray, searchFilter, view, 334 ServiceErrorHandling.ThrowOnError); 335 336 return responses.getResponseAtIndex(0).getResults(); 337 } 338 339 /** 340 * Obtains a list of folder by searching the sub-folder of the specified 341 * folder. 342 * 343 * @param parentFolderId The Id of the folder in which to search for folder. 344 * @param view The view controlling the number of folder returned. 345 * @return An object representing the results of the search operation. 346 * @throws Exception the exception 347 */ 348 public FindFoldersResults findFolders(FolderId parentFolderId, 349 FolderView view) throws Exception { 350 EwsUtilities.validateParam(parentFolderId, "parentFolderId"); 351 EwsUtilities.validateParam(view, "view"); 352 353 List<FolderId> folderIdArray = new ArrayList<FolderId>(); 354 folderIdArray.add(parentFolderId); 355 356 ServiceResponseCollection<FindFolderResponse> responses = this 357 .internalFindFolders(folderIdArray, null, /* searchFilter */ 358 view, ServiceErrorHandling.ThrowOnError); 359 360 return responses.getResponseAtIndex(0).getResults(); 361 } 362 363 /** 364 * Obtains a list of folder by searching the sub-folder of the specified 365 * folder. 366 * 367 * @param parentFolderName The name of the folder in which to search for folder. 368 * @param searchFilter The search filter. Available search filter classes include 369 * SearchFilter.IsEqualTo, SearchFilter.ContainsSubstring and 370 * SearchFilter.SearchFilterCollection 371 * @param view The view controlling the number of folder returned. 372 * @return An object representing the results of the search operation. 373 * @throws Exception the exception 374 */ 375 public FindFoldersResults findFolders(WellKnownFolderName parentFolderName, 376 SearchFilter searchFilter, FolderView view) throws Exception { 377 return this.findFolders(new FolderId(parentFolderName), searchFilter, 378 view); 379 } 380 381 /** 382 * Obtains a list of folder by searching the sub-folder of the specified 383 * folder. 384 * 385 * @param parentFolderName the parent folder name 386 * @param view the view 387 * @return An object representing the results of the search operation. 388 * @throws Exception the exception 389 */ 390 public FindFoldersResults findFolders(WellKnownFolderName parentFolderName, 391 FolderView view) throws Exception { 392 return this.findFolders(new FolderId(parentFolderName), view); 393 } 394 395 /** 396 * Load specified property for a folder. 397 * 398 * @param folder The folder 399 * @param propertySet The property set 400 * @throws Exception the exception 401 */ 402 public void loadPropertiesForFolder(Folder folder, PropertySet propertySet) throws Exception { 403 EwsUtilities.validateParam(folder, "folder"); 404 EwsUtilities.validateParam(propertySet, "propertySet"); 405 406 GetFolderRequestForLoad request = new GetFolderRequestForLoad(this, 407 ServiceErrorHandling.ThrowOnError); 408 409 request.getFolderIds().add(folder); 410 request.setPropertySet(propertySet); 411 412 request.execute(); 413 } 414 415 /** 416 * Binds to a folder. 417 * 418 * 419 * @param folderId the folder id 420 * @param propertySet the property set 421 * @return Folder 422 * @throws Exception the exception 423 */ 424 public Folder bindToFolder(FolderId folderId, PropertySet propertySet) 425 throws Exception { 426 EwsUtilities.validateParam(folderId, "folderId"); 427 EwsUtilities.validateParam(propertySet, "propertySet"); 428 429 GetFolderRequest request = new GetFolderRequest(this, 430 ServiceErrorHandling.ThrowOnError); 431 432 request.getFolderIds().add(folderId); 433 request.setPropertySet(propertySet); 434 435 ServiceResponseCollection<GetFolderResponse> responses = request 436 .execute(); 437 438 return responses.getResponseAtIndex(0).getFolder(); 439 440 } 441 442 /** 443 * Binds to folder. 444 * 445 * @param <TFolder> The type of the folder. 446 * @param cls Folder class 447 * @param folderId The folder id. 448 * @param propertySet The property set. 449 * @return Folder 450 * @throws Exception the exception 451 */ 452 public <TFolder extends Folder> TFolder bindToFolder(Class<TFolder> cls, FolderId folderId, 453 PropertySet propertySet) throws Exception { 454 Folder result = this.bindToFolder(folderId, propertySet); 455 456 if (cls.isAssignableFrom(result.getClass())) { 457 return (TFolder) result; 458 } else { 459 throw new ServiceLocalException(String.format( 460 "The folder type returned by the service (%s) isn't compatible with the requested folder type (%s).", 461 result.getClass().getName(), cls.getName())); 462 } 463 } 464 465 /** 466 * Deletes a folder. Calling this method results in a call to EWS. 467 * 468 * @param folderId The folder id 469 * @param deleteMode The delete mode 470 * @throws Exception the exception 471 */ 472 public void deleteFolder(FolderId folderId, DeleteMode deleteMode) 473 throws Exception { 474 EwsUtilities.validateParam(folderId, "folderId"); 475 476 DeleteFolderRequest request = new DeleteFolderRequest(this, 477 ServiceErrorHandling.ThrowOnError); 478 479 request.getFolderIds().add(folderId); 480 request.setDeleteMode(deleteMode); 481 482 request.execute(); 483 } 484 485 /** 486 * Empties a folder. Calling this method results in a call to EWS. 487 * 488 * @param folderId The folder id 489 * @param deleteMode The delete mode 490 * @param deleteSubFolders if set to "true" empty folder should also delete sub folder. 491 * @throws Exception the exception 492 */ 493 public void emptyFolder(FolderId folderId, DeleteMode deleteMode, boolean deleteSubFolders) throws Exception { 494 EwsUtilities.validateParam(folderId, "folderId"); 495 496 EmptyFolderRequest request = new EmptyFolderRequest(this, 497 ServiceErrorHandling.ThrowOnError); 498 499 request.getFolderIds().add(folderId); 500 request.setDeleteMode(deleteMode); 501 request.setDeleteSubFolders(deleteSubFolders); 502 request.execute(); 503 } 504 505 /** 506 * Creates multiple item in a single EWS call. Supported item classes are 507 * EmailMessage, Appointment, Contact, PostItem, Task and Item. CreateItems 508 * does not support item that have unsaved attachments. 509 * 510 * @param items the item 511 * @param parentFolderId the parent folder id 512 * @param messageDisposition the message disposition 513 * @param sendInvitationsMode the send invitations mode 514 * @param errorHandling the error handling 515 * @return A ServiceResponseCollection providing creation results for each 516 * of the specified item. 517 * @throws Exception the exception 518 */ 519 private ServiceResponseCollection<ServiceResponse> internalCreateItems( 520 Collection<Item> items, FolderId parentFolderId, 521 MessageDisposition messageDisposition, 522 SendInvitationsMode sendInvitationsMode, 523 ServiceErrorHandling errorHandling) throws Exception { 524 CreateItemRequest request = new CreateItemRequest(this, errorHandling); 525 request.setParentFolderId(parentFolderId); 526 request.setItems(items); 527 request.setMessageDisposition(messageDisposition); 528 request.setSendInvitationsMode(sendInvitationsMode); 529 return request.execute(); 530 } 531 532 /** 533 * Creates multiple item in a single EWS call. Supported item classes are 534 * EmailMessage, Appointment, Contact, PostItem, Task and Item. CreateItems 535 * does not support item that have unsaved attachments. 536 * 537 * @param items the item 538 * @param parentFolderId the parent folder id 539 * @param messageDisposition the message disposition 540 * @param sendInvitationsMode the send invitations mode 541 * @return A ServiceResponseCollection providing creation results for each 542 * of the specified item. 543 * @throws Exception the exception 544 */ 545 public ServiceResponseCollection<ServiceResponse> createItems( 546 Collection<Item> items, FolderId parentFolderId, 547 MessageDisposition messageDisposition, 548 SendInvitationsMode sendInvitationsMode) throws Exception { 549 // All item have to be new. 550 if (!EwsUtilities.trueForAll(items, new IPredicate<Item>() { 551 @Override 552 public boolean predicate(Item obj) throws ServiceLocalException { 553 return obj.isNew(); 554 } 555 })) { 556 throw new ServiceValidationException( 557 "This operation can't be performed because at least one item already has an ID."); 558 } 559 560 // E14:298274 Make sure that all item do *not* have unprocessed 561 // attachments. 562 if (!EwsUtilities.trueForAll(items, new IPredicate<Item>() { 563 @Override 564 public boolean predicate(Item obj) throws ServiceLocalException { 565 return !obj.hasUnprocessedAttachmentChanges(); 566 } 567 })) { 568 throw new ServiceValidationException("This operation doesn't support item that have attachments."); 569 } 570 return this.internalCreateItems(items, parentFolderId, 571 messageDisposition, sendInvitationsMode, 572 ServiceErrorHandling.ReturnErrors); 573 } 574 575 /** 576 * Creates an item. Calling this method results in a call to EWS. 577 * 578 * @param item the item 579 * @param parentFolderId the parent folder id 580 * @param messageDisposition the message disposition 581 * @param sendInvitationsMode the send invitations mode 582 * @throws Exception the exception 583 */ 584 public void createItem(Item item, FolderId parentFolderId, MessageDisposition messageDisposition, 585 SendInvitationsMode sendInvitationsMode) throws Exception { 586 ArrayList<Item> items = new ArrayList<Item>(); 587 items.add(item); 588 internalCreateItems(items, parentFolderId, messageDisposition, sendInvitationsMode, 589 ServiceErrorHandling.ThrowOnError); 590 } 591 592 /** 593 * Updates multiple item in a single EWS call. UpdateItems does not 594 * support item that have unsaved attachments. 595 * 596 * @param items the item 597 * @param savedItemsDestinationFolderId the saved item destination folder id 598 * @param conflictResolution the conflict resolution 599 * @param messageDisposition the message disposition 600 * @param sendInvitationsOrCancellationsMode the send invitations or cancellations mode 601 * @param errorHandling the error handling 602 * @return A ServiceResponseCollection providing update results for each of 603 * the specified item. 604 * @throws Exception the exception 605 */ 606 private ServiceResponseCollection<UpdateItemResponse> internalUpdateItems( 607 Iterable<Item> items, 608 FolderId savedItemsDestinationFolderId, 609 ConflictResolutionMode conflictResolution, 610 MessageDisposition messageDisposition, 611 SendInvitationsOrCancellationsMode sendInvitationsOrCancellationsMode, 612 ServiceErrorHandling errorHandling) throws Exception { 613 UpdateItemRequest request = new UpdateItemRequest(this, errorHandling); 614 615 request.getItems().addAll((Collection<? extends Item>) items); 616 request.setSavedItemsDestinationFolder(savedItemsDestinationFolderId); 617 request.setMessageDisposition(messageDisposition); 618 request.setConflictResolutionMode(conflictResolution); 619 request 620 .setSendInvitationsOrCancellationsMode(sendInvitationsOrCancellationsMode); 621 622 return request.execute(); 623 } 624 625 /** 626 * Updates multiple item in a single EWS call. UpdateItems does not 627 * support item that have unsaved attachments. 628 * 629 * @param items the item 630 * @param savedItemsDestinationFolderId the saved item destination folder id 631 * @param conflictResolution the conflict resolution 632 * @param messageDisposition the message disposition 633 * @param sendInvitationsOrCancellationsMode the send invitations or cancellations mode 634 * @return A ServiceResponseCollection providing update results for each of 635 * the specified item. 636 * @throws Exception the exception 637 */ 638 public ServiceResponseCollection<UpdateItemResponse> updateItems( 639 Iterable<Item> items, 640 FolderId savedItemsDestinationFolderId, 641 ConflictResolutionMode conflictResolution, 642 MessageDisposition messageDisposition, 643 SendInvitationsOrCancellationsMode sendInvitationsOrCancellationsMode) 644 throws Exception { 645 646 // All item have to exist on the server (!new) and modified (dirty) 647 if (!EwsUtilities.trueForAll(items, new IPredicate<Item>() { 648 @Override 649 public boolean predicate(Item obj) throws ServiceLocalException { 650 return (!obj.isNew() && obj.isDirty()); 651 } 652 })) { 653 throw new ServiceValidationException( 654 "This operation can't be performed because one or more item are new or unmodified."); 655 } 656 657 // E14:298274 Make sure that all item do *not* have unprocessed 658 // attachments. 659 if (!EwsUtilities.trueForAll(items, new IPredicate<Item>() { 660 @Override 661 public boolean predicate(Item obj) throws ServiceLocalException { 662 return !obj.hasUnprocessedAttachmentChanges(); 663 } 664 })) { 665 throw new ServiceValidationException( 666 "This operation can't be performed because attachments have been added or deleted for one or more item."); 667 } 668 669 return this.internalUpdateItems(items, savedItemsDestinationFolderId, conflictResolution, 670 messageDisposition, sendInvitationsOrCancellationsMode, 671 ServiceErrorHandling.ReturnErrors); 672 } 673 674 /** 675 * Updates an item. 676 * 677 * @param item the item 678 * @param savedItemsDestinationFolderId the saved item destination folder id 679 * @param conflictResolution the conflict resolution 680 * @param messageDisposition the message disposition 681 * @param sendInvitationsOrCancellationsMode the send invitations or cancellations mode 682 * @return A ServiceResponseCollection providing deletion results for each 683 * of the specified item Ids. 684 * @throws Exception the exception 685 */ 686 public Item updateItem(Item item, FolderId savedItemsDestinationFolderId, 687 ConflictResolutionMode conflictResolution, MessageDisposition messageDisposition, 688 SendInvitationsOrCancellationsMode sendInvitationsOrCancellationsMode) 689 throws Exception { 690 List<Item> itemIdArray = new ArrayList<Item>(); 691 itemIdArray.add(item); 692 693 ServiceResponseCollection<UpdateItemResponse> responses = this 694 .internalUpdateItems(itemIdArray, 695 savedItemsDestinationFolderId, conflictResolution, 696 messageDisposition, sendInvitationsOrCancellationsMode, 697 ServiceErrorHandling.ThrowOnError); 698 699 return responses.getResponseAtIndex(0).getReturnedItem(); 700 } 701 702 /** 703 * Send item. 704 * 705 * @param item the item 706 * @param savedCopyDestinationFolderId the saved copy destination folder id 707 * @throws Exception the exception 708 */ 709 public void sendItem(Item item, FolderId savedCopyDestinationFolderId) 710 throws Exception { 711 SendItemRequest request = new SendItemRequest(this, 712 ServiceErrorHandling.ThrowOnError); 713 714 List<Item> itemIdArray = new ArrayList<Item>(); 715 itemIdArray.add(item); 716 717 request.setItems(itemIdArray); 718 request.setSavedCopyDestinationFolderId(savedCopyDestinationFolderId); 719 720 request.execute(); 721 } 722 723 /** 724 * Copies multiple item in a single call to EWS. 725 * 726 * @param itemIds the item ids 727 * @param destinationFolderId the destination folder id 728 * @param returnNewItemIds Flag indicating whether service should return new ItemIds or 729 * not. 730 * @param errorHandling the error handling 731 * @return A ServiceResponseCollection providing copy results for each of 732 * the specified item Ids. 733 * @throws Exception the exception 734 */ 735 private ServiceResponseCollection<MoveCopyItemResponse> internalCopyItems( 736 Iterable<ItemId> itemIds, FolderId destinationFolderId, 737 Boolean returnNewItemIds, ServiceErrorHandling errorHandling) 738 throws Exception { 739 CopyItemRequest request = new CopyItemRequest(this, errorHandling); 740 request.getItemIds().addRange(itemIds); 741 request.setDestinationFolderId(destinationFolderId); 742 request.setReturnNewItemIds(returnNewItemIds); 743 return request.execute(); 744 745 } 746 747 /** 748 * Copies multiple item in a single call to EWS. 749 * 750 * @param itemIds the item ids 751 * @param destinationFolderId the destination folder id 752 * @return A ServiceResponseCollection providing copy results for each of 753 * the specified item Ids. 754 * @throws Exception the exception 755 */ 756 public ServiceResponseCollection<MoveCopyItemResponse> copyItems( 757 Iterable<ItemId> itemIds, FolderId destinationFolderId) 758 throws Exception { 759 return this.internalCopyItems(itemIds, destinationFolderId, null, 760 ServiceErrorHandling.ReturnErrors); 761 } 762 763 /** 764 * Copies multiple item in a single call to EWS. 765 * 766 * @param itemIds The Ids of the item to copy. 767 * @param destinationFolderId The Id of the folder to copy the item to. 768 * @param returnNewItemIds Flag indicating whether service should return new ItemIds or 769 * not. 770 * @return A ServiceResponseCollection providing copy results for each of 771 * the specified item Ids. 772 * @throws Exception on error 773 */ 774 public ServiceResponseCollection<MoveCopyItemResponse> copyItems( 775 Iterable<ItemId> itemIds, FolderId destinationFolderId, 776 boolean returnNewItemIds) throws Exception { 777 EwsUtilities.validateMethodVersion(this, ExchangeVersion.Exchange2010_SP1, "CopyItems"); 778 779 return this.internalCopyItems(itemIds, destinationFolderId, returnNewItemIds, 780 ServiceErrorHandling.ReturnErrors); 781 } 782 783 /** 784 * Copies an item. Calling this method results in a call to EWS. 785 * 786 * @param itemId The Id of the item to copy. 787 * @param destinationFolderId The folder in which to save sent messages, meeting invitations 788 * or cancellations. If null, the message, meeting invitation or 789 * cancellation is saved in the Sent Items folder 790 * @return The copy of the item. 791 * @throws Exception the exception 792 */ 793 public Item copyItem(ItemId itemId, FolderId destinationFolderId) 794 throws Exception { 795 List<ItemId> itemIdArray = new ArrayList<ItemId>(); 796 itemIdArray.add(itemId); 797 798 return this.internalCopyItems(itemIdArray, destinationFolderId, null, 799 ServiceErrorHandling.ThrowOnError).getResponseAtIndex(0) 800 .getItem(); 801 } 802 803 /** 804 * Moves multiple item in a single call to EWS. 805 * 806 * @param itemIds the item ids 807 * @param destinationFolderId the destination folder id 808 * @param returnNewItemIds Flag indicating whether service should return new ItemIds or 809 * not. 810 * @param errorHandling the error handling 811 * @return A ServiceResponseCollection providing copy results for each of 812 * the specified item Ids. 813 * @throws Exception the exception 814 */ 815 private ServiceResponseCollection<MoveCopyItemResponse> internalMoveItems( 816 Iterable<ItemId> itemIds, FolderId destinationFolderId, 817 Boolean returnNewItemIds, ServiceErrorHandling errorHandling) 818 throws Exception { 819 MoveItemRequest request = new MoveItemRequest(this, errorHandling); 820 821 request.getItemIds().addRange(itemIds); 822 request.setDestinationFolderId(destinationFolderId); 823 request.setReturnNewItemIds(returnNewItemIds); 824 return request.execute(); 825 } 826 827 /** 828 * Moves multiple item in a single call to EWS. 829 * 830 * @param itemIds the item ids 831 * @param destinationFolderId the destination folder id 832 * @return A ServiceResponseCollection providing copy results for each of 833 * the specified item Ids. 834 * @throws Exception the exception 835 */ 836 public ServiceResponseCollection<MoveCopyItemResponse> moveItems( 837 Iterable<ItemId> itemIds, FolderId destinationFolderId) 838 throws Exception { 839 return this.internalMoveItems(itemIds, destinationFolderId, null, 840 ServiceErrorHandling.ReturnErrors); 841 } 842 843 /** 844 * Moves multiple item in a single call to EWS. 845 * 846 * @param itemIds The Ids of the item to move. 847 * @param destinationFolderId The Id of the folder to move the item to. 848 * @param returnNewItemIds Flag indicating whether service should return new ItemIds or 849 * not. 850 * @return A ServiceResponseCollection providing copy results for each of 851 * the specified item Ids. 852 * @throws Exception on error 853 */ 854 public ServiceResponseCollection<MoveCopyItemResponse> moveItems( 855 Iterable<ItemId> itemIds, FolderId destinationFolderId, 856 boolean returnNewItemIds) throws Exception { 857 EwsUtilities.validateMethodVersion(this, ExchangeVersion.Exchange2010_SP1, "MoveItems"); 858 859 return this.internalMoveItems(itemIds, destinationFolderId, returnNewItemIds, 860 ServiceErrorHandling.ReturnErrors); 861 } 862 863 /** 864 * Copies multiple item in a single call to EWS. 865 * 866 * @param itemId the item id 867 * @param destinationFolderId the destination folder id 868 * @return A ServiceResponseCollection providing copy results for each of 869 * the specified item Ids. 870 * @throws Exception the exception 871 */ 872 public Item moveItem(ItemId itemId, FolderId destinationFolderId) 873 throws Exception { 874 List<ItemId> itemIdArray = new ArrayList<ItemId>(); 875 itemIdArray.add(itemId); 876 877 return this.internalMoveItems(itemIdArray, destinationFolderId, null, 878 ServiceErrorHandling.ThrowOnError).getResponseAtIndex(0) 879 .getItem(); 880 } 881 882 /** 883 * Finds item. 884 * 885 * @param <TItem> The type of item 886 * @param parentFolderIds The parent folder ids. 887 * @param searchFilter The search filter. Available search filter classes include 888 * SearchFilter.IsEqualTo, SearchFilter.ContainsSubstring and 889 * SearchFilter.SearchFilterCollection 890 * @param queryString the query string 891 * @param view The view controlling the number of folder returned. 892 * @param groupBy The group by. 893 * @param errorHandlingMode Indicates the type of error handling should be done. 894 * @return Service response collection. 895 * @throws Exception the exception 896 */ 897 public <TItem extends Item> ServiceResponseCollection<FindItemResponse<TItem>> findItems( 898 Iterable<FolderId> parentFolderIds, SearchFilter searchFilter, String queryString, ViewBase view, 899 Grouping groupBy, ServiceErrorHandling errorHandlingMode) throws Exception { 900 EwsUtilities.validateParamCollection(parentFolderIds.iterator(), 901 "parentFolderIds"); 902 EwsUtilities.validateParam(view, "view"); 903 EwsUtilities.validateParamAllowNull(groupBy, "groupBy"); 904 EwsUtilities.validateParamAllowNull(queryString, "queryString"); 905 EwsUtilities.validateParamAllowNull(searchFilter, "searchFilter"); 906 907 FindItemRequest<TItem> request = new FindItemRequest<TItem>(this, 908 errorHandlingMode); 909 910 request.getParentFolderIds().addRangeFolderId(parentFolderIds); 911 request.setSearchFilter(searchFilter); 912 request.setQueryString(queryString); 913 request.setView(view); 914 request.setGroupBy(groupBy); 915 916 return request.execute(); 917 } 918 919 /** 920 * Obtains a list of item by searching the contents of a specific folder. 921 * Calling this method results in a call to EWS. 922 * 923 * @param parentFolderId the parent folder id 924 * @param queryString the query string 925 * @param view the view 926 * @return An object representing the results of the search operation. 927 * @throws Exception the exception 928 */ 929 public FindItemsResults<Item> findItems(FolderId parentFolderId, 930 String queryString, ItemView view) throws Exception { 931 EwsUtilities.validateParamAllowNull(queryString, "queryString"); 932 933 List<FolderId> folderIdArray = new ArrayList<FolderId>(); 934 folderIdArray.add(parentFolderId); 935 936 ServiceResponseCollection<FindItemResponse<Item>> responses = this 937 .findItems(folderIdArray, null, /* searchFilter */ 938 queryString, view, null, /* groupBy */ 939 ServiceErrorHandling.ThrowOnError); 940 941 return responses.getResponseAtIndex(0).getResults(); 942 } 943 944 /** 945 * Obtains a list of item by searching the contents of a specific folder. 946 * Calling this method results in a call to EWS. 947 * 948 * @param parentFolderId the parent folder id 949 * @param searchFilter the search filter 950 * @param view the view 951 * @return An object representing the results of the search operation. 952 * @throws Exception the exception 953 */ 954 public FindItemsResults<Item> findItems(FolderId parentFolderId, 955 SearchFilter searchFilter, ItemView view) throws Exception { 956 EwsUtilities.validateParamAllowNull(searchFilter, "searchFilter"); 957 List<FolderId> folderIdArray = new ArrayList<FolderId>(); 958 folderIdArray.add(parentFolderId); 959 ServiceResponseCollection<FindItemResponse<Item>> responses = this 960 .findItems(folderIdArray, searchFilter, null, /* queryString */ 961 view, null, /* groupBy */ 962 ServiceErrorHandling.ThrowOnError); 963 964 return responses.getResponseAtIndex(0).getResults(); 965 } 966 967 /** 968 * Obtains a list of item by searching the contents of a specific folder. 969 * Calling this method results in a call to EWS. 970 * 971 * @param parentFolderId the parent folder id 972 * @param view the view 973 * @return An object representing the results of the search operation. 974 * @throws Exception the exception 975 */ 976 public FindItemsResults<Item> findItems(FolderId parentFolderId, 977 ItemView view) throws Exception { 978 List<FolderId> folderIdArray = new ArrayList<FolderId>(); 979 folderIdArray.add(parentFolderId); 980 ServiceResponseCollection<FindItemResponse<Item>> responses = this 981 .findItems(folderIdArray, null, /* searchFilter */ 982 null, /* queryString */ 983 view, null, /* groupBy */ 984 ServiceErrorHandling.ThrowOnError); 985 986 return responses.getResponseAtIndex(0).getResults(); 987 } 988 989 /** 990 * Obtains a list of item by searching the contents of a specific folder. 991 * Calling this method results in a call to EWS. 992 * 993 * @param parentFolderName the parent folder name 994 * @param queryString the query string 995 * @param view the view 996 * @return An object representing the results of the search operation. 997 * @throws Exception the exception 998 */ 999 public FindItemsResults<Item> findItems( 1000 WellKnownFolderName parentFolderName, String queryString, 1001 ItemView view) throws Exception { 1002 return this 1003 .findItems(new FolderId(parentFolderName), queryString, view); 1004 } 1005 1006 /** 1007 * Obtains a list of item by searching the contents of a specific folder. 1008 * Calling this method results in a call to EWS. 1009 * 1010 * @param parentFolderName the parent folder name 1011 * @param searchFilter the search filter 1012 * @param view the view 1013 * @return An object representing the results of the search operation. 1014 * @throws Exception the exception 1015 */ 1016 public FindItemsResults<Item> findItems( 1017 WellKnownFolderName parentFolderName, SearchFilter searchFilter, 1018 ItemView view) throws Exception { 1019 return this.findItems(new FolderId(parentFolderName), searchFilter, 1020 view); 1021 } 1022 1023 /** 1024 * Obtains a list of item by searching the contents of a specific folder. 1025 * Calling this method results in a call to EWS. 1026 * 1027 * @param parentFolderName the parent folder name 1028 * @param view the view 1029 * @return An object representing the results of the search operation. 1030 * @throws Exception the exception 1031 */ 1032 public FindItemsResults<Item> findItems( 1033 WellKnownFolderName parentFolderName, ItemView view) 1034 throws Exception { 1035 return this.findItems(new FolderId(parentFolderName), (SearchFilter) null, view); 1036 } 1037 1038 /** 1039 * Obtains a grouped list of item by searching the contents of a specific 1040 * folder. Calling this method results in a call to EWS. 1041 * 1042 * @param parentFolderId the parent folder id 1043 * @param queryString the query string 1044 * @param view the view 1045 * @param groupBy the group by 1046 * @return A list of item containing the contents of the specified folder. 1047 * @throws Exception the exception 1048 */ 1049 public GroupedFindItemsResults<Item> findItems(FolderId parentFolderId, 1050 String queryString, ItemView view, Grouping groupBy) 1051 throws Exception { 1052 EwsUtilities.validateParam(groupBy, "groupBy"); 1053 EwsUtilities.validateParamAllowNull(queryString, "queryString"); 1054 1055 List<FolderId> folderIdArray = new ArrayList<FolderId>(); 1056 folderIdArray.add(parentFolderId); 1057 1058 ServiceResponseCollection<FindItemResponse<Item>> responses = this 1059 .findItems(folderIdArray, null, /* searchFilter */ 1060 queryString, view, groupBy, ServiceErrorHandling.ThrowOnError); 1061 1062 return responses.getResponseAtIndex(0).getGroupedFindResults(); 1063 } 1064 1065 /** 1066 * Obtains a grouped list of item by searching the contents of a specific 1067 * folder. Calling this method results in a call to EWS. 1068 * 1069 * @param parentFolderId the parent folder id 1070 * @param searchFilter the search filter 1071 * @param view the view 1072 * @param groupBy the group by 1073 * @return A list of item containing the contents of the specified folder. 1074 * @throws Exception the exception 1075 */ 1076 public GroupedFindItemsResults<Item> findItems(FolderId parentFolderId, 1077 SearchFilter searchFilter, ItemView view, Grouping groupBy) 1078 throws Exception { 1079 EwsUtilities.validateParam(groupBy, "groupBy"); 1080 EwsUtilities.validateParamAllowNull(searchFilter, "searchFilter"); 1081 1082 List<FolderId> folderIdArray = new ArrayList<FolderId>(); 1083 folderIdArray.add(parentFolderId); 1084 1085 ServiceResponseCollection<FindItemResponse<Item>> responses = this 1086 .findItems(folderIdArray, searchFilter, null, /* queryString */ 1087 view, groupBy, ServiceErrorHandling.ThrowOnError); 1088 1089 return responses.getResponseAtIndex(0).getGroupedFindResults(); 1090 } 1091 1092 /** 1093 * Obtains a grouped list of item by searching the contents of a specific 1094 * folder. Calling this method results in a call to EWS. 1095 * 1096 * @param parentFolderId the parent folder id 1097 * @param view the view 1098 * @param groupBy the group by 1099 * @return A list of item containing the contents of the specified folder. 1100 * @throws Exception the exception 1101 */ 1102 public GroupedFindItemsResults<Item> findItems(FolderId parentFolderId, 1103 ItemView view, Grouping groupBy) throws Exception { 1104 EwsUtilities.validateParam(groupBy, "groupBy"); 1105 1106 List<FolderId> folderIdArray = new ArrayList<FolderId>(); 1107 folderIdArray.add(parentFolderId); 1108 1109 ServiceResponseCollection<FindItemResponse<Item>> responses = this 1110 .findItems(folderIdArray, null, /* searchFilter */ 1111 null, /* queryString */ 1112 view, groupBy, ServiceErrorHandling.ThrowOnError); 1113 1114 return responses.getResponseAtIndex(0).getGroupedFindResults(); 1115 } 1116 1117 /** 1118 * Obtains a grouped list of item by searching the contents of a specific 1119 * folder. Calling this method results in a call to EWS. 1120 * 1121 * @param <TItem> the generic type 1122 * @param cls the cls 1123 * @param parentFolderId the parent folder id 1124 * @param searchFilter the search filter 1125 * @param view the view 1126 * @param groupBy the group by 1127 * @return A list of item containing the contents of the specified folder. 1128 * @throws Exception the exception 1129 */ 1130 protected <TItem extends Item> ServiceResponseCollection<FindItemResponse<TItem>> findItems( 1131 Class<TItem> cls, FolderId parentFolderId, 1132 SearchFilter searchFilter, ViewBase view, Grouping groupBy) 1133 throws Exception { 1134 List<FolderId> folderIdArray = new ArrayList<FolderId>(); 1135 folderIdArray.add(parentFolderId); 1136 1137 return this.findItems(folderIdArray, searchFilter, null, /* queryString */ 1138 view, groupBy, ServiceErrorHandling.ThrowOnError); 1139 } 1140 1141 /** 1142 * Obtains a grouped list of item by searching the contents of a specific 1143 * folder. Calling this method results in a call to EWS. 1144 * 1145 * @param parentFolderName the parent folder name 1146 * @param queryString the query string 1147 * @param view the view 1148 * @param groupBy the group by 1149 * @return A collection of grouped item containing the contents of the 1150 * specified. 1151 * @throws Exception the exception 1152 */ 1153 public GroupedFindItemsResults<Item> findItems( 1154 WellKnownFolderName parentFolderName, String queryString, 1155 ItemView view, Grouping groupBy) throws Exception { 1156 EwsUtilities.validateParam(groupBy, "groupBy"); 1157 return this.findItems(new FolderId(parentFolderName), queryString, 1158 view, groupBy); 1159 } 1160 1161 /** 1162 * Obtains a grouped list of item by searching the contents of a specific 1163 * folder. Calling this method results in a call to EWS. 1164 * 1165 * @param parentFolderName the parent folder name 1166 * @param searchFilter the search filter 1167 * @param view the view 1168 * @param groupBy the group by 1169 * @return A collection of grouped item containing the contents of the 1170 * specified. 1171 * @throws Exception the exception 1172 */ 1173 public GroupedFindItemsResults<Item> findItems( 1174 WellKnownFolderName parentFolderName, SearchFilter searchFilter, 1175 ItemView view, Grouping groupBy) throws Exception { 1176 return this.findItems(new FolderId(parentFolderName), searchFilter, view, groupBy); 1177 } 1178 1179 /** 1180 * Obtains a list of appointments by searching the contents of a specific 1181 * folder. Calling this method results in a call to EWS. 1182 * 1183 * @param parentFolderId the parent folder id 1184 * @param calendarView the calendar view 1185 * @return A collection of appointments representing the contents of the 1186 * specified folder. 1187 * @throws Exception the exception 1188 */ 1189 public FindItemsResults<Appointment> findAppointments( 1190 FolderId parentFolderId, CalendarView calendarView) 1191 throws Exception { 1192 List<FolderId> folderIdArray = new ArrayList<FolderId>(); 1193 folderIdArray.add(parentFolderId); 1194 1195 ServiceResponseCollection<FindItemResponse<Appointment>> response = this 1196 .findItems(folderIdArray, null, /* searchFilter */ 1197 null /* queryString */, calendarView, null, /* groupBy */ 1198 ServiceErrorHandling.ThrowOnError); 1199 1200 return response.getResponseAtIndex(0).getResults(); 1201 } 1202 1203 /** 1204 * Obtains a list of appointments by searching the contents of a specific 1205 * folder. Calling this method results in a call to EWS. 1206 * 1207 * @param parentFolderName the parent folder name 1208 * @param calendarView the calendar view 1209 * @return A collection of appointments representing the contents of the 1210 * specified folder. 1211 * @throws Exception the exception 1212 */ 1213 public FindItemsResults<Appointment> findAppointments( 1214 WellKnownFolderName parentFolderName, CalendarView calendarView) 1215 throws Exception { 1216 return this.findAppointments(new FolderId(parentFolderName), calendarView); 1217 } 1218 1219 /** 1220 * Loads the property of multiple item in a single call to EWS. 1221 * 1222 * @param items the item 1223 * @param propertySet the property set 1224 * @return A ServiceResponseCollection providing results for each of the 1225 * specified item. 1226 * @throws Exception the exception 1227 */ 1228 public ServiceResponseCollection<ServiceResponse> loadPropertiesForItems( 1229 Iterable<Item> items, PropertySet propertySet) throws Exception { 1230 EwsUtilities.validateParamCollection(items.iterator(), "item"); 1231 EwsUtilities.validateParam(propertySet, "propertySet"); 1232 1233 return this.internalLoadPropertiesForItems(items, propertySet, ServiceErrorHandling.ReturnErrors); 1234 } 1235 1236 /** 1237 * Loads the property of multiple item in a single call to EWS. 1238 * 1239 * @param items the item 1240 * @param propertySet the property set 1241 * @param errorHandling the error handling 1242 * @return A ServiceResponseCollection providing results for each of the 1243 * specified item. 1244 * @throws Exception the exception 1245 */ 1246 public ServiceResponseCollection<ServiceResponse> internalLoadPropertiesForItems(Iterable<Item> items, 1247 PropertySet propertySet, ServiceErrorHandling errorHandling) throws Exception { 1248 GetItemRequestForLoad request = new GetItemRequestForLoad(this, 1249 errorHandling); 1250 // return null; 1251 1252 request.getItemIds().addRangeItem(items); 1253 request.setPropertySet(propertySet); 1254 1255 return request.execute(); 1256 } 1257 1258 /** 1259 * Binds to multiple item in a single call to EWS. 1260 * 1261 * @param itemIds the item ids 1262 * @param propertySet the property set 1263 * @param errorHandling the error handling 1264 * @return A ServiceResponseCollection providing results for each of the 1265 * specified item Ids. 1266 * @throws Exception the exception 1267 */ 1268 private ServiceResponseCollection<GetItemResponse> internalBindToItems( 1269 Iterable<ItemId> itemIds, PropertySet propertySet, 1270 ServiceErrorHandling errorHandling) throws Exception { 1271 GetItemRequest request = new GetItemRequest(this, errorHandling); 1272 request.getItemIds().addRange(itemIds); 1273 request.setPropertySet(propertySet); 1274 return request.execute(); 1275 } 1276 1277 /** 1278 * Binds to multiple item in a single call to EWS. 1279 * 1280 * @param itemIds the item ids 1281 * @param propertySet the property set 1282 * @return A ServiceResponseCollection providing results for each of the 1283 * specified item Ids. 1284 * @throws Exception the exception 1285 */ 1286 public ServiceResponseCollection<GetItemResponse> bindToItems( 1287 Iterable<ItemId> itemIds, PropertySet propertySet) throws Exception { 1288 EwsUtilities.validateParamCollection(itemIds.iterator(), "itemIds"); 1289 EwsUtilities.validateParam(propertySet, "propertySet"); 1290 1291 return this.internalBindToItems(itemIds, propertySet, ServiceErrorHandling.ReturnErrors); 1292 } 1293 1294 /** 1295 * Binds to multiple item in a single call to EWS. 1296 * 1297 * @param itemId the item id 1298 * @param propertySet the property set 1299 * @return A ServiceResponseCollection providing results for each of the 1300 * specified item Ids. 1301 * @throws Exception the exception 1302 */ 1303 public Item bindToItem(ItemId itemId, PropertySet propertySet) 1304 throws Exception { 1305 EwsUtilities.validateParam(itemId, "itemId"); 1306 EwsUtilities.validateParam(propertySet, "propertySet"); 1307 List<ItemId> itmLst = new ArrayList<ItemId>(); 1308 itmLst.add(itemId); 1309 ServiceResponseCollection<GetItemResponse> responses = this 1310 .internalBindToItems(itmLst, propertySet, ServiceErrorHandling.ThrowOnError); 1311 1312 return responses.getResponseAtIndex(0).getItem(); 1313 } 1314 1315 /** 1316 * Bind to item. 1317 * 1318 * @param <TItem> The type of the item. 1319 * @param c the c 1320 * @param itemId the item id 1321 * @param propertySet the property set 1322 * @return the t item 1323 * @throws Exception the exception 1324 */ 1325 public <TItem extends Item> TItem bindToItem(Class<TItem> c, ItemId itemId, PropertySet propertySet) throws Exception { 1326 Item result = this.bindToItem(itemId, propertySet); 1327 if (c.isAssignableFrom(result.getClass())) { 1328 return (TItem) result; 1329 } else { 1330 throw new ServiceLocalException(String.format( 1331 "The item type returned by the service (%s) isn't compatible with the requested item type (%s).", result.getClass().getName(), 1332 c.getName())); 1333 } 1334 } 1335 1336 /** 1337 * Deletes multiple item in a single call to EWS. 1338 * 1339 * @param itemIds the item ids 1340 * @param deleteMode the delete mode 1341 * @param sendCancellationsMode the send cancellations mode 1342 * @param affectedTaskOccurrences the affected task occurrences 1343 * @param errorHandling the error handling 1344 * @return A ServiceResponseCollection providing deletion results for each 1345 * of the specified item Ids. 1346 * @throws Exception the exception 1347 */ 1348 private ServiceResponseCollection<ServiceResponse> internalDeleteItems( 1349 Iterable<ItemId> itemIds, DeleteMode deleteMode, 1350 SendCancellationsMode sendCancellationsMode, 1351 AffectedTaskOccurrence affectedTaskOccurrences, 1352 ServiceErrorHandling errorHandling) throws Exception { 1353 DeleteItemRequest request = new DeleteItemRequest(this, errorHandling); 1354 1355 request.getItemIds().addRange(itemIds); 1356 request.setDeleteMode(deleteMode); 1357 request.setSendCancellationsMode(sendCancellationsMode); 1358 request.setAffectedTaskOccurrences(affectedTaskOccurrences); 1359 1360 return request.execute(); 1361 } 1362 1363 /** 1364 * Deletes multiple item in a single call to EWS. 1365 * 1366 * @param itemIds the item ids 1367 * @param deleteMode the delete mode 1368 * @param sendCancellationsMode the send cancellations mode 1369 * @param affectedTaskOccurrences the affected task occurrences 1370 * @return A ServiceResponseCollection providing deletion results for each 1371 * of the specified item Ids. 1372 * @throws Exception the exception 1373 */ 1374 public ServiceResponseCollection<ServiceResponse> deleteItems( 1375 Iterable<ItemId> itemIds, DeleteMode deleteMode, 1376 SendCancellationsMode sendCancellationsMode, 1377 AffectedTaskOccurrence affectedTaskOccurrences) throws Exception { 1378 EwsUtilities.validateParamCollection(itemIds.iterator(), "itemIds"); 1379 1380 return this.internalDeleteItems(itemIds, deleteMode, 1381 sendCancellationsMode, affectedTaskOccurrences, 1382 ServiceErrorHandling.ReturnErrors); 1383 } 1384 1385 /** 1386 * Deletes an item. Calling this method results in a call to EWS. 1387 * 1388 * @param itemId the item id 1389 * @param deleteMode the delete mode 1390 * @param sendCancellationsMode the send cancellations mode 1391 * @param affectedTaskOccurrences the affected task occurrences 1392 * @throws Exception the exception 1393 */ 1394 public void deleteItem(ItemId itemId, DeleteMode deleteMode, SendCancellationsMode sendCancellationsMode, 1395 AffectedTaskOccurrence affectedTaskOccurrences) throws Exception { 1396 List<ItemId> itemIdArray = new ArrayList<ItemId>(); 1397 itemIdArray.add(itemId); 1398 1399 EwsUtilities.validateParam(itemId, "itemId"); 1400 this.internalDeleteItems(itemIdArray, deleteMode, 1401 sendCancellationsMode, affectedTaskOccurrences, 1402 ServiceErrorHandling.ThrowOnError); 1403 } 1404 1405 /** 1406 * Gets an attachment. 1407 * 1408 * @param attachments the attachments 1409 * @param bodyType the body type 1410 * @param additionalProperties the additional property 1411 * @param errorHandling the error handling 1412 * @throws Exception the exception 1413 */ 1414 private ServiceResponseCollection<GetAttachmentResponse> internalGetAttachments( 1415 Iterable<Attachment> attachments, BodyType bodyType, 1416 Iterable<PropertyDefinitionBase> additionalProperties, ServiceErrorHandling errorHandling) 1417 throws Exception { 1418 GetAttachmentRequest request = new GetAttachmentRequest(this, errorHandling); 1419 1420 Iterator<Attachment> it = attachments.iterator(); 1421 while (it.hasNext()) { 1422 request.getAttachments().add(it.next()); 1423 } 1424 request.setBodyType(bodyType); 1425 1426 if (additionalProperties != null) { 1427 List<PropertyDefinitionBase> propsArray = new ArrayList<PropertyDefinitionBase>(); 1428 for (PropertyDefinitionBase propertyDefinitionBase : additionalProperties) { 1429 propsArray.add(propertyDefinitionBase); 1430 } 1431 request.getAdditionalProperties().addAll(propsArray); 1432 } 1433 1434 return request.execute(); 1435 } 1436 1437 /** 1438 * Gets attachments. 1439 * 1440 * @param attachments the attachments 1441 * @param bodyType the body type 1442 * @param additionalProperties the additional property 1443 * @return service response collection 1444 * @throws Exception on error 1445 */ 1446 protected ServiceResponseCollection<GetAttachmentResponse> getAttachments( 1447 Attachment[] attachments, BodyType bodyType, 1448 Iterable<PropertyDefinitionBase> additionalProperties) 1449 throws Exception { 1450 return this.internalGetAttachments(Arrays.asList(attachments), bodyType, 1451 additionalProperties, ServiceErrorHandling.ReturnErrors); 1452 } 1453 1454 /** 1455 * Gets the attachment. 1456 * 1457 * @param attachment the attachment 1458 * @param bodyType the body type 1459 * @param additionalProperties the additional property 1460 * @throws Exception the exception 1461 */ 1462 public void getAttachment(Attachment attachment, BodyType bodyType, 1463 Iterable<PropertyDefinitionBase> additionalProperties) 1464 throws Exception { 1465 1466 List<Attachment> attachmentArray = new ArrayList<Attachment>(); 1467 attachmentArray.add(attachment); 1468 1469 this.internalGetAttachments(attachmentArray, bodyType, additionalProperties, 1470 ServiceErrorHandling.ThrowOnError); 1471 1472 } 1473 1474 /** 1475 * Creates attachments. 1476 * 1477 * @param parentItemId the parent item id 1478 * @param attachments the attachments 1479 * @return Service response collection. 1480 * @throws ServiceResponseException the service response exception 1481 * @throws Exception the exception 1482 */ 1483 public ServiceResponseCollection<CreateAttachmentResponse> createAttachments(String parentItemId, 1484 Iterable<Attachment> attachments) 1485 throws ServiceResponseException, Exception { 1486 CreateAttachmentRequest request = new CreateAttachmentRequest(this, 1487 ServiceErrorHandling.ReturnErrors); 1488 1489 request.setParentItemId(parentItemId); 1490 /* 1491 * if (null != attachments) { while (attachments.hasNext()) { 1492 * request.getAttachments().add(attachments.next()); } } 1493 */ 1494 request.getAttachments().addAll( 1495 (Collection<? extends Attachment>) attachments); 1496 1497 return request.execute(); 1498 } 1499 1500 /** 1501 * Deletes attachments. 1502 * 1503 * @param attachments the attachments 1504 * @return the service response collection 1505 * @throws ServiceResponseException the service response exception 1506 * @throws Exception the exception 1507 */ 1508 public ServiceResponseCollection<DeleteAttachmentResponse> deleteAttachments( 1509 Iterable<Attachment> attachments) throws ServiceResponseException, 1510 Exception { 1511 DeleteAttachmentRequest request = new DeleteAttachmentRequest(this, 1512 ServiceErrorHandling.ReturnErrors); 1513 1514 request.getAttachments().addAll( 1515 (Collection<? extends Attachment>) attachments); 1516 1517 return request.execute(); 1518 } 1519 1520 /** 1521 * Finds contacts in the user's Contacts folder and the Global Address 1522 * List (in that order) that have names that match the one passed as a 1523 * parameter. Calling this method results in a call to EWS. 1524 * 1525 * @param nameToResolve the name to resolve 1526 * @return A collection of name resolutions whose names match the one passed 1527 * as a parameter. 1528 * @throws Exception the exception 1529 */ 1530 public NameResolutionCollection resolveName(String nameToResolve) 1531 throws Exception { 1532 return this.resolveName(nameToResolve, ResolveNameSearchLocation.ContactsThenDirectory, false); 1533 } 1534 1535 /** 1536 * Finds contacts in the user's Contacts folder and the Global Address 1537 * List (in that order) that have names that match the one passed as a 1538 * parameter. Calling this method results in a call to EWS. 1539 * 1540 * @param nameToResolve the name to resolve 1541 * @param parentFolderIds the parent folder ids 1542 * @param searchScope the search scope 1543 * @param returnContactDetails the return contact details 1544 * @return A collection of name resolutions whose names match the one passed 1545 * as a parameter. 1546 * @throws Exception the exception 1547 */ 1548 public NameResolutionCollection resolveName(String nameToResolve, 1549 Iterable<FolderId> parentFolderIds, 1550 ResolveNameSearchLocation searchScope, boolean returnContactDetails) 1551 throws Exception { 1552 return resolveName(nameToResolve, parentFolderIds, searchScope, returnContactDetails, null); 1553 1554 } 1555 1556 /** 1557 * Finds contacts in the Global Address List and/or in specific contact 1558 * folder that have names that match the one passed as a parameter. Calling 1559 * this method results in a call to EWS. 1560 * 1561 * @param nameToResolve The name to resolve. 1562 * @param parentFolderIds The Ids of the contact folder in which to look for matching 1563 * contacts. 1564 * @param searchScope The scope of the search. 1565 * @param returnContactDetails Indicates whether full contact information should be returned 1566 * for each of the found contacts. 1567 * @param contactDataPropertySet The property set for the contact details 1568 * @return a collection of name resolutions whose names match the one passed as a parameter 1569 * @throws Exception on error 1570 */ 1571 public NameResolutionCollection resolveName(String nameToResolve, 1572 Iterable<FolderId> parentFolderIds, 1573 ResolveNameSearchLocation searchScope, 1574 boolean returnContactDetails, PropertySet contactDataPropertySet) 1575 throws Exception { 1576 if (contactDataPropertySet != null) { 1577 EwsUtilities.validateMethodVersion(this, 1578 ExchangeVersion.Exchange2010_SP1, "ResolveName"); 1579 } 1580 1581 EwsUtilities.validateParam(nameToResolve, "nameToResolve"); 1582 1583 if (parentFolderIds != null) { 1584 EwsUtilities.validateParamCollection(parentFolderIds.iterator(), 1585 "parentFolderIds"); 1586 } 1587 ResolveNamesRequest request = new ResolveNamesRequest(this); 1588 1589 request.setNameToResolve(nameToResolve); 1590 request.setReturnFullContactData(returnContactDetails); 1591 request.getParentFolderIds().addRangeFolderId(parentFolderIds); 1592 request.setSearchLocation(searchScope); 1593 request.setContactDataPropertySet(contactDataPropertySet); 1594 1595 return request.execute().getResponseAtIndex(0).getResolutions(); 1596 } 1597 1598 /** 1599 * Finds contacts in the Global Address List that have names that match the 1600 * one passed as a parameter. Calling this method results in a call to EWS. 1601 * 1602 * @param nameToResolve The name to resolve. 1603 * @param searchScope The scope of the search. 1604 * @param returnContactDetails Indicates whether full contact information should be returned 1605 * for each of the found contacts. 1606 * @param contactDataPropertySet The property set for the contact details 1607 * @return A collection of name resolutions whose names match the one 1608 * passed as a parameter. 1609 * @throws Exception on error 1610 */ 1611 public NameResolutionCollection resolveName(String nameToResolve, 1612 ResolveNameSearchLocation searchScope, 1613 boolean returnContactDetails, PropertySet contactDataPropertySet) 1614 throws Exception { 1615 return this.resolveName(nameToResolve, null, searchScope, 1616 returnContactDetails, contactDataPropertySet); 1617 } 1618 1619 /** 1620 * Finds contacts in the user's Contacts folder and the Global Address 1621 * List (in that order) that have names that match the one passed as a 1622 * parameter. Calling this method results in a call to EWS. 1623 * 1624 * @param nameToResolve the name to resolve 1625 * @param searchScope the search scope 1626 * @param returnContactDetails the return contact details 1627 * @return A collection of name resolutions whose names match the one passed 1628 * as a parameter. 1629 * @throws Exception the exception 1630 */ 1631 public NameResolutionCollection resolveName(String nameToResolve, 1632 ResolveNameSearchLocation searchScope, boolean returnContactDetails) 1633 throws Exception { 1634 return this.resolveName(nameToResolve, null, searchScope, returnContactDetails); 1635 } 1636 1637 /** 1638 * Expands a group by retrieving a list of its members. Calling this 1639 * method results in a call to EWS. 1640 * 1641 * @param emailAddress the email address 1642 * @return URL of the Exchange Web Services. 1643 * @throws Exception the exception 1644 */ 1645 public ExpandGroupResults expandGroup(EmailAddress emailAddress) 1646 throws Exception { 1647 EwsUtilities.validateParam(emailAddress, "emailAddress"); 1648 ExpandGroupRequest request = new ExpandGroupRequest(this); 1649 request.setEmailAddress(emailAddress); 1650 return request.execute().getResponseAtIndex(0).getMembers(); 1651 } 1652 1653 /** 1654 * Expands a group by retrieving a list of its members. Calling this 1655 * method results in a call to EWS. 1656 * 1657 * @param groupId the group id 1658 * @return An ExpandGroupResults containing the members of the group. 1659 * @throws Exception the exception 1660 */ 1661 public ExpandGroupResults expandGroup(ItemId groupId) throws Exception { 1662 EwsUtilities.validateParam(groupId, "groupId"); 1663 EmailAddress emailAddress = new EmailAddress(); 1664 emailAddress.setId(groupId); 1665 return this.expandGroup(emailAddress); 1666 } 1667 1668 /** 1669 * Expands a group by retrieving a list of its members. Calling this 1670 * method results in a call to EWS. 1671 * 1672 * @param smtpAddress the smtp address 1673 * @return An ExpandGroupResults containing the members of the group. 1674 * @throws Exception the exception 1675 */ 1676 public ExpandGroupResults expandGroup(String smtpAddress) throws Exception { 1677 EwsUtilities.validateParam(smtpAddress, "smtpAddress"); 1678 return this.expandGroup(new EmailAddress(smtpAddress)); 1679 } 1680 1681 /** 1682 * Expands a group by retrieving a list of its members. Calling this 1683 * method results in a call to EWS. 1684 * 1685 * @param address the address 1686 * @param routingType the routing type 1687 * @return An ExpandGroupResults containing the members of the group. 1688 * @throws Exception the exception 1689 */ 1690 public ExpandGroupResults expandGroup(String address, String routingType) 1691 throws Exception { 1692 EwsUtilities.validateParam(address, "address"); 1693 EwsUtilities.validateParam(routingType, "routingType"); 1694 1695 EmailAddress emailAddress = new EmailAddress(address); 1696 emailAddress.setRoutingType(routingType); 1697 return this.expandGroup(emailAddress); 1698 } 1699 1700 /** 1701 * Get the password expiration date 1702 * 1703 * @param mailboxSmtpAddress The e-mail address of the user. 1704 * @return The password expiration date 1705 * @throws Exception on error 1706 */ 1707 public Date getPasswordExpirationDate(String mailboxSmtpAddress) throws Exception { 1708 GetPasswordExpirationDateRequest request = new GetPasswordExpirationDateRequest(this); 1709 request.setMailboxSmtpAddress(mailboxSmtpAddress); 1710 1711 return request.execute().getPasswordExpirationDate(); 1712 } 1713 1714 /** 1715 * Subscribes to pull notification. Calling this method results in a call 1716 * to EWS. 1717 * 1718 * @param folderIds The Ids of the folder to subscribe to 1719 * @param timeout The timeout, in minutes, after which the subscription expires. 1720 * Timeout must be between 1 and 1440. 1721 * @param watermark An optional watermark representing a previously opened 1722 * subscription. 1723 * @param eventTypes The event types to subscribe to. 1724 * @return A PullSubscription representing the new subscription. 1725 * @throws Exception on error 1726 */ 1727 public PullSubscription subscribeToPullNotifications( 1728 Iterable<FolderId> folderIds, int timeout, String watermark, 1729 EventType... eventTypes) throws Exception { 1730 EwsUtilities.validateParamCollection(folderIds.iterator(), "folderIds"); 1731 1732 return this.buildSubscribeToPullNotificationsRequest(folderIds, 1733 timeout, watermark, eventTypes).execute().getResponseAtIndex(0) 1734 .getSubscription(); 1735 } 1736 1737 /** 1738 * Begins an asynchronous request to subscribes to pull notification. 1739 * Calling this method results in a call to EWS. 1740 * 1741 * @param callback The AsyncCallback delegate. 1742 * @param state An object that contains state information for this request. 1743 * @param folderIds The Ids of the folder to subscribe to. 1744 * @param timeout The timeout, in minutes, after which the subscription expires. 1745 * Timeout must be between 1 and 1440. 1746 * @param watermark An optional watermark representing a previously opened 1747 * subscription. 1748 * @param eventTypes The event types to subscribe to. 1749 * @return An IAsyncResult that references the asynchronous request. 1750 * @throws Exception 1751 */ 1752 public AsyncRequestResult beginSubscribeToPullNotifications( 1753 AsyncCallback callback, Object state, Iterable<FolderId> folderIds, 1754 int timeout, String watermark, EventType... eventTypes) 1755 throws Exception { 1756 EwsUtilities.validateParamCollection(folderIds.iterator(), "folderIds"); 1757 1758 return this.buildSubscribeToPullNotificationsRequest(folderIds, timeout, watermark, 1759 eventTypes).beginExecute(callback); 1760 } 1761 1762 /** 1763 * Subscribes to pull notification on all folder in the authenticated 1764 * user's mailbox. Calling this method results in a call to EWS. 1765 * 1766 * @param timeout the timeout 1767 * @param watermark the watermark 1768 * @param eventTypes the event types 1769 * @return A PullSubscription representing the new subscription. 1770 * @throws Exception the exception 1771 */ 1772 public PullSubscription subscribeToPullNotificationsOnAllFolders( 1773 int timeout, String watermark, EventType... eventTypes) 1774 throws Exception { 1775 EwsUtilities.validateMethodVersion(this, ExchangeVersion.Exchange2010, 1776 "SubscribeToPullNotificationsOnAllFolders"); 1777 1778 return this.buildSubscribeToPullNotificationsRequest(null, timeout, 1779 watermark, eventTypes).execute().getResponseAtIndex(0) 1780 .getSubscription(); 1781 } 1782 1783 /** 1784 * Begins an asynchronous request to subscribe to pull notification on all 1785 * folder in the authenticated user's mailbox. Calling this method results 1786 * in a call to EWS. 1787 * 1788 * @param callback The AsyncCallback delegate. 1789 * @param state An object that contains state information for this request. 1790 * @param timeout The timeout, in minutes, after which the subscription expires. 1791 * Timeout must be between 1 and 1440. 1792 * @param watermark An optional watermark representing a previously opened 1793 * subscription. 1794 * @param eventTypes The event types to subscribe to. 1795 * @return An IAsyncResult that references the asynchronous request. 1796 * @throws Exception 1797 */ 1798 public IAsyncResult beginSubscribeToPullNotificationsOnAllFolders(AsyncCallback callback, Object state, 1799 int timeout, 1800 String watermark, EventType... eventTypes) throws Exception { 1801 EwsUtilities.validateMethodVersion(this, ExchangeVersion.Exchange2010, 1802 "BeginSubscribeToPullNotificationsOnAllFolders"); 1803 1804 return this.buildSubscribeToPullNotificationsRequest(null, timeout, watermark, eventTypes).beginExecute( 1805 null); 1806 } 1807 1808 /** 1809 * Ends an asynchronous request to subscribe to pull notification in the 1810 * authenticated user's mailbox. 1811 * 1812 * @param asyncResult An IAsyncResult that references the asynchronous request. 1813 * @return A PullSubscription representing the new subscription. 1814 * @throws Exception 1815 */ 1816 public PullSubscription endSubscribeToPullNotifications( 1817 IAsyncResult asyncResult) throws Exception { 1818 SubscribeToPullNotificationsRequest request = AsyncRequestResult 1819 .extractServiceRequest(this, asyncResult); 1820 1821 return request.endExecute(asyncResult).getResponseAtIndex(0) 1822 .getSubscription(); 1823 } 1824 1825 /** 1826 * Builds a request to subscribe to pull notification in the 1827 * authenticated user's mailbox. 1828 * 1829 * @param folderIds The Ids of the folder to subscribe to. 1830 * @param timeout The timeout, in minutes, after which the subscription expires. 1831 * Timeout must be between 1 and 1440 1832 * @param watermark An optional watermark representing a previously opened 1833 * subscription 1834 * @param eventTypes The event types to subscribe to 1835 * @return A request to subscribe to pull notification in the authenticated 1836 * user's mailbox 1837 * @throws Exception the exception 1838 */ 1839 private SubscribeToPullNotificationsRequest buildSubscribeToPullNotificationsRequest( 1840 Iterable<FolderId> folderIds, int timeout, String watermark, 1841 EventType... eventTypes) throws Exception { 1842 if (timeout < 1 || timeout > 1440) { 1843 throw new IllegalArgumentException("timeout", new Throwable( 1844 "Timeout must be a value between 1 and 1440.")); 1845 } 1846 1847 EwsUtilities.validateParamCollection(eventTypes, "eventTypes"); 1848 1849 SubscribeToPullNotificationsRequest request = new SubscribeToPullNotificationsRequest( 1850 this); 1851 1852 if (folderIds != null) { 1853 request.getFolderIds().addRangeFolderId(folderIds); 1854 } 1855 1856 request.setTimeOut(timeout); 1857 1858 for (EventType event : eventTypes) { 1859 request.getEventTypes().add(event); 1860 } 1861 1862 request.setWatermark(watermark); 1863 1864 return request; 1865 } 1866 1867 /** 1868 * Unsubscribes from a pull subscription. Calling this method results in a 1869 * call to EWS. 1870 * 1871 * @param subscriptionId the subscription id 1872 * @throws Exception the exception 1873 */ 1874 public void unsubscribe(String subscriptionId) throws Exception { 1875 1876 this.buildUnsubscribeRequest(subscriptionId).execute(); 1877 } 1878 1879 /** 1880 * Begins an asynchronous request to unsubscribe from a subscription. 1881 * Calling this method results in a call to EWS. 1882 * 1883 * @param callback The AsyncCallback delegate. 1884 * @param state An object that contains state information for this request. 1885 * @param subscriptionId The Id of the pull subscription to unsubscribe from. 1886 * @return An IAsyncResult that references the asynchronous request. 1887 * @throws Exception 1888 */ 1889 public IAsyncResult beginUnsubscribe(AsyncCallback callback, Object state, String subscriptionId) 1890 throws Exception { 1891 return this.buildUnsubscribeRequest(subscriptionId).beginExecute(callback); 1892 } 1893 1894 /** 1895 * Ends an asynchronous request to unsubscribe from a subscription. 1896 * 1897 * @param asyncResult An IAsyncResult that references the asynchronous request. 1898 * @throws Exception 1899 */ 1900 public void endUnsubscribe(IAsyncResult asyncResult) throws Exception { 1901 UnsubscribeRequest request = AsyncRequestResult.extractServiceRequest(this, asyncResult); 1902 1903 request.endExecute(asyncResult); 1904 } 1905 1906 /** 1907 * Buids a request to unsubscribe from a subscription. 1908 * 1909 * @param subscriptionId The id of the subscription for which to get the events 1910 * @return A request to unsubscripbe from a subscription 1911 * @throws Exception 1912 */ 1913 private UnsubscribeRequest buildUnsubscribeRequest(String subscriptionId) 1914 throws Exception { 1915 EwsUtilities.validateParam(subscriptionId, "subscriptionId"); 1916 1917 UnsubscribeRequest request = new UnsubscribeRequest(this); 1918 1919 request.setSubscriptionId(subscriptionId); 1920 1921 return request; 1922 } 1923 1924 /** 1925 * Retrieves the latests events associated with a pull subscription. 1926 * Calling this method results in a call to EWS. 1927 * 1928 * @param subscriptionId the subscription id 1929 * @param waterMark the water mark 1930 * @return A GetEventsResults containing a list of events associated with 1931 * the subscription. 1932 * @throws Exception the exception 1933 */ 1934 public GetEventsResults getEvents(String subscriptionId, String waterMark) 1935 throws Exception { 1936 1937 return this.buildGetEventsRequest(subscriptionId, waterMark).execute() 1938 .getResponseAtIndex(0).getResults(); 1939 } 1940 1941 /** 1942 * Begins an asynchronous request to retrieve the latest events associated 1943 * with a pull subscription. Calling this method results in a call to EWS. 1944 * 1945 * @param callback The AsyncCallback delegate. 1946 * @param state An object that contains state information for this request. 1947 * @param subscriptionId The id of the pull subscription for which to get the events 1948 * @param watermark The watermark representing the point in time where to start 1949 * receiving events 1950 * @return An IAsynResult that references the asynchronous request 1951 * @throws Exception 1952 */ 1953 public IAsyncResult beginGetEvents(AsyncCallback callback, Object state, String subscriptionId, 1954 String watermark) throws Exception { 1955 return this.buildGetEventsRequest(subscriptionId, watermark) 1956 .beginExecute(callback); 1957 } 1958 1959 /** 1960 * Ends an asynchronous request to retrieve the latest events associated 1961 * with a pull subscription. 1962 * 1963 * @param asyncResult An IAsyncResult that references the asynchronous request. 1964 * @return A GetEventsResults containing a list of events associated with 1965 * the subscription. 1966 * @throws Exception 1967 */ 1968 public GetEventsResults endGetEvents(IAsyncResult asyncResult) throws Exception { 1969 GetEventsRequest request = AsyncRequestResult.extractServiceRequest(this, asyncResult); 1970 1971 return request.endExecute(asyncResult).getResponseAtIndex(0).getResults(); 1972 } 1973 1974 /** 1975 * Builds a request to retrieve the letest events associated with a pull 1976 * subscription 1977 * 1978 * @param subscriptionId The Id of the pull subscription for which to get the events 1979 * @param watermark The watermark representing the point in time where to start 1980 * receiving events 1981 * @return An request to retrieve the latest events associated with a pull 1982 * subscription 1983 * @throws Exception 1984 */ 1985 private GetEventsRequest buildGetEventsRequest(String subscriptionId, 1986 String watermark) throws Exception { 1987 EwsUtilities.validateParam(subscriptionId, "subscriptionId"); 1988 EwsUtilities.validateParam(watermark, "watermark"); 1989 1990 GetEventsRequest request = new GetEventsRequest(this); 1991 1992 request.setSubscriptionId(subscriptionId); 1993 request.setWatermark(watermark); 1994 1995 return request; 1996 } 1997 1998 /** 1999 * Subscribes to push notification. Calling this method results in a call 2000 * to EWS. 2001 * 2002 * @param folderIds the folder ids 2003 * @param url the url 2004 * @param frequency the frequency 2005 * @param watermark the watermark 2006 * @param eventTypes the event types 2007 * @return A PushSubscription representing the new subscription. 2008 * @throws Exception the exception 2009 */ 2010 public PushSubscription subscribeToPushNotifications( 2011 Iterable<FolderId> folderIds, URI url, int frequency, 2012 String watermark, EventType... eventTypes) throws Exception { 2013 EwsUtilities.validateParamCollection(folderIds.iterator(), "folderIds"); 2014 2015 return this.buildSubscribeToPushNotificationsRequest(folderIds, url, 2016 frequency, watermark, eventTypes).execute().getResponseAtIndex(0).getSubscription(); 2017 } 2018 2019 /** 2020 * Begins an asynchronous request to subscribe to push notification. 2021 * Calling this method results in a call to EWS. 2022 * 2023 * @param callback The asynccallback delegate 2024 * @param state An object that contains state information for this request 2025 * @param folderIds The ids of the folder to subscribe 2026 * @param url the url of web service endpoint the exchange server should 2027 * @param frequency the frequency,in minutes at which the exchange server should 2028 * contact the web Service endpoint. Frequency must be between 1 2029 * and 1440. 2030 * @param watermark An optional watermark representing a previously opened 2031 * subscription 2032 * @param eventTypes The event types to subscribe to. 2033 * @return An IAsyncResult that references the asynchronous request. 2034 * @throws Exception 2035 */ 2036 public IAsyncResult beginSubscribeToPushNotifications( 2037 AsyncCallback callback, Object state, Iterable<FolderId> folderIds, 2038 URI url, int frequency, String watermark, EventType... eventTypes) 2039 throws Exception { 2040 EwsUtilities.validateParamCollection(folderIds.iterator(), "folderIds"); 2041 2042 return this.buildSubscribeToPushNotificationsRequest(folderIds, url, frequency, watermark, 2043 eventTypes).beginExecute(callback); 2044 } 2045 2046 /** 2047 * Subscribes to push notification on all folder in the authenticated 2048 * user's mailbox. Calling this method results in a call to EWS. 2049 * 2050 * @param url the url 2051 * @param frequency the frequency 2052 * @param watermark the watermark 2053 * @param eventTypes the event types 2054 * @return A PushSubscription representing the new subscription. 2055 * @throws Exception the exception 2056 */ 2057 public PushSubscription subscribeToPushNotificationsOnAllFolders(URI url, 2058 int frequency, String watermark, EventType... eventTypes) 2059 throws Exception { 2060 EwsUtilities.validateMethodVersion(this, ExchangeVersion.Exchange2010, 2061 "SubscribeToPushNotificationsOnAllFolders"); 2062 2063 return this.buildSubscribeToPushNotificationsRequest(null, url, 2064 frequency, watermark, eventTypes).execute().getResponseAtIndex(0).getSubscription(); 2065 } 2066 2067 /** 2068 * Begins an asynchronous request to subscribe to push notification on all 2069 * folder in the authenticated user's mailbox. Calling this method results 2070 * in a call to EWS. 2071 * 2072 * @param callback The asynccallback delegate 2073 * @param state An object that contains state inforamtion for this request 2074 * @param url the url 2075 * @param frequency the frequency,in minutes at which the exchange server should 2076 * contact the web Service endpoint. Frequency must be between 1 2077 * and 1440. 2078 * @param watermark An optional watermark representing a previously opened 2079 * subscription 2080 * @param eventTypes The event types to subscribe to. 2081 * @return An IAsyncResult that references the asynchronous request. 2082 * @throws Exception 2083 */ 2084 public IAsyncResult beginSubscribeToPushNotificationsOnAllFolders( 2085 AsyncCallback callback, Object state, URI url, int frequency, 2086 String watermark, EventType... eventTypes) throws Exception { 2087 EwsUtilities.validateMethodVersion(this, ExchangeVersion.Exchange2010, 2088 "BeginSubscribeToPushNotificationsOnAllFolders"); 2089 2090 return this.buildSubscribeToPushNotificationsRequest(null, url, frequency, watermark, 2091 eventTypes).beginExecute(callback); 2092 } 2093 2094 2095 /** 2096 * Ends an asynchronous request to subscribe to push notification in the 2097 * authenticated user's mailbox. 2098 * 2099 * @param asyncResult An IAsyncResult that references the asynchronous request. 2100 * @return A PushSubscription representing the new subscription 2101 * @throws Exception 2102 */ 2103 public PushSubscription endSubscribeToPushNotifications( 2104 IAsyncResult asyncResult) throws Exception { 2105 SubscribeToPushNotificationsRequest request = AsyncRequestResult 2106 .extractServiceRequest(this, asyncResult); 2107 2108 return request.endExecute(asyncResult).getResponseAtIndex(0) 2109 .getSubscription(); 2110 } 2111 2112 /** 2113 * Builds an request to request to subscribe to push notification in the 2114 * authenticated user's mailbox. 2115 * 2116 * @param folderIds the folder ids 2117 * @param url the url 2118 * @param frequency the frequency 2119 * @param watermark the watermark 2120 * @param eventTypes the event types 2121 * @return A request to request to subscribe to push notification in the 2122 * authenticated user's mailbox. 2123 * @throws Exception the exception 2124 */ 2125 private SubscribeToPushNotificationsRequest buildSubscribeToPushNotificationsRequest( 2126 Iterable<FolderId> folderIds, URI url, int frequency, 2127 String watermark, EventType[] eventTypes) throws Exception { 2128 EwsUtilities.validateParam(url, "url"); 2129 if (frequency < 1 || frequency > 1440) { 2130 throw new ArgumentOutOfRangeException("frequency", "The frequency must be a value between 1 and 1440."); 2131 } 2132 2133 EwsUtilities.validateParamCollection(eventTypes, "eventTypes"); 2134 SubscribeToPushNotificationsRequest request = new SubscribeToPushNotificationsRequest(this); 2135 2136 if (folderIds != null) { 2137 request.getFolderIds().addRangeFolderId(folderIds); 2138 } 2139 2140 request.setUrl(url); 2141 request.setFrequency(frequency); 2142 2143 for (EventType event : eventTypes) { 2144 request.getEventTypes().add(event); 2145 } 2146 2147 request.setWatermark(watermark); 2148 2149 return request; 2150 } 2151 2152 /** 2153 * Subscribes to streaming notification. Calling this method results in a 2154 * call to EWS. 2155 * 2156 * @param folderIds The Ids of the folder to subscribe to. 2157 * @param eventTypes The event types to subscribe to. 2158 * @return A StreamingSubscription representing the new subscription 2159 * @throws Exception 2160 */ 2161 public StreamingSubscription subscribeToStreamingNotifications( 2162 Iterable<FolderId> folderIds, EventType... eventTypes) 2163 throws Exception { 2164 EwsUtilities.validateMethodVersion(this, 2165 ExchangeVersion.Exchange2010_SP1, 2166 "SubscribeToStreamingNotifications"); 2167 2168 EwsUtilities.validateParamCollection(folderIds.iterator(), "folderIds"); 2169 2170 return this.buildSubscribeToStreamingNotificationsRequest(folderIds, 2171 eventTypes).execute().getResponseAtIndex(0).getSubscription(); 2172 } 2173 2174 /** 2175 * Subscribes to streaming notification on all folder in the authenticated 2176 * user's mailbox. Calling this method results in a call to EWS. 2177 * 2178 * @param eventTypes The event types to subscribe to. 2179 * @return A StreamingSubscription representing the new subscription. 2180 * @throws Exception 2181 */ 2182 public StreamingSubscription subscribeToStreamingNotificationsOnAllFolders( 2183 EventType... eventTypes) throws Exception { 2184 EwsUtilities.validateMethodVersion(this, ExchangeVersion.Exchange2010_SP1, 2185 "SubscribeToStreamingNotificationsOnAllFolders"); 2186 2187 return this.buildSubscribeToStreamingNotificationsRequest(null, 2188 eventTypes).execute().getResponseAtIndex(0).getSubscription(); 2189 } 2190 2191 /** 2192 * Begins an asynchronous request to subscribe to streaming notification. 2193 * Calling this method results in a call to EWS. 2194 * 2195 * @param callback The AsyncCallback delegate 2196 * @param state An object that contains state information for this request. 2197 * @param folderIds The Ids of the folder to subscribe to. 2198 * @param eventTypes The event types to subscribe to. 2199 * @return An IAsyncResult that references the asynchronous request 2200 * @throws Exception 2201 */ 2202 public IAsyncResult beginSubscribeToStreamingNotifications(AsyncCallback callback, Object state, 2203 Iterable<FolderId> folderIds, 2204 EventType... eventTypes) throws Exception { 2205 EwsUtilities.validateMethodVersion(this, 2206 ExchangeVersion.Exchange2010_SP1, 2207 "BeginSubscribeToStreamingNotifications"); 2208 2209 EwsUtilities.validateParamCollection(folderIds.iterator(), "folderIds"); 2210 2211 return this.buildSubscribeToStreamingNotificationsRequest(folderIds, 2212 eventTypes).beginExecute(callback); 2213 } 2214 2215 /** 2216 * Begins an asynchronous request to subscribe to streaming notification on 2217 * all folder in the authenticated user's mailbox. Calling this method 2218 * results in a call to EWS. 2219 * 2220 * @param callback The AsyncCallback delegate 2221 * @param state An object that contains state information for this request. 2222 * @return An IAsyncResult that references the asynchronous request. 2223 * @throws Exception 2224 */ 2225 public IAsyncResult beginSubscribeToStreamingNotificationsOnAllFolders(AsyncCallback callback, Object state, 2226 EventType... eventTypes) throws Exception { 2227 EwsUtilities.validateMethodVersion(this, 2228 ExchangeVersion.Exchange2010_SP1, 2229 "BeginSubscribeToStreamingNotificationsOnAllFolders"); 2230 2231 return this.buildSubscribeToStreamingNotificationsRequest(null, 2232 eventTypes).beginExecute(callback); 2233 } 2234 2235 /** 2236 * Ends an asynchronous request to subscribe to push notification in the 2237 * authenticated user's mailbox. 2238 * 2239 * @param asyncResult An IAsyncResult that references the asynchronous request. 2240 * @return A streamingSubscription representing the new subscription 2241 * @throws Exception 2242 * @throws IndexOutOfBoundsException 2243 */ 2244 public StreamingSubscription endSubscribeToStreamingNotifications(IAsyncResult asyncResult) 2245 throws IndexOutOfBoundsException, Exception { 2246 EwsUtilities.validateMethodVersion( 2247 this, 2248 ExchangeVersion.Exchange2010_SP1, 2249 "EndSubscribeToStreamingNotifications"); 2250 2251 SubscribeToStreamingNotificationsRequest request = 2252 AsyncRequestResult.extractServiceRequest(this, asyncResult); 2253 // SubscribeToStreamingNotificationsRequest request = AsyncRequestResult.extractServiceRequest<SubscribeToStreamingNotificationsRequest>(this, asyncResult); 2254 return request.endExecute(asyncResult).getResponseAtIndex(0).getSubscription(); 2255 } 2256 2257 /** 2258 * Builds request to subscribe to streaming notification in the 2259 * authenticated user's mailbox. 2260 * 2261 * @param folderIds The Ids of the folder to subscribe to. 2262 * @param eventTypes The event types to subscribe to. 2263 * @return A request to subscribe to streaming notification in the 2264 * authenticated user's mailbox 2265 * @throws Exception 2266 */ 2267 private SubscribeToStreamingNotificationsRequest buildSubscribeToStreamingNotificationsRequest( 2268 Iterable<FolderId> folderIds, EventType[] eventTypes) throws Exception { 2269 EwsUtilities.validateParamCollection(eventTypes, "eventTypes"); 2270 2271 SubscribeToStreamingNotificationsRequest request = new SubscribeToStreamingNotificationsRequest( 2272 this); 2273 2274 if (folderIds != null) { 2275 request.getFolderIds().addRangeFolderId(folderIds); 2276 } 2277 2278 for (EventType event : eventTypes) { 2279 request.getEventTypes().add(event); 2280 } 2281 2282 return request; 2283 } 2284 2285 2286 2287 /** 2288 * Synchronizes the item of a specific folder. Calling this method 2289 * results in a call to EWS. 2290 * 2291 * @param syncFolderId The Id of the folder containing the item to synchronize with. 2292 * @param propertySet The set of property to retrieve for synchronized item. 2293 * @param ignoredItemIds The optional list of item Ids that should be ignored. 2294 * @param maxChangesReturned The maximum number of changes that should be returned. 2295 * @param syncScope The sync scope identifying item to include in the 2296 * ChangeCollection. 2297 * @param syncState The optional sync state representing the point in time when to 2298 * start the synchronization. 2299 * @return A ChangeCollection containing a list of changes that occurred in 2300 * the specified folder. 2301 * @throws Exception the exception 2302 */ 2303 public ChangeCollection<ItemChange> syncFolderItems(FolderId syncFolderId, 2304 PropertySet propertySet, Iterable<ItemId> ignoredItemIds, 2305 int maxChangesReturned, SyncFolderItemsScope syncScope, 2306 String syncState) throws Exception { 2307 return this.buildSyncFolderItemsRequest(syncFolderId, propertySet, 2308 ignoredItemIds, maxChangesReturned, syncScope, syncState) 2309 .execute().getResponseAtIndex(0).getChanges(); 2310 } 2311 2312 /** 2313 * Begins an asynchronous request to synchronize the item of a specific 2314 * folder. Calling this method results in a call to EWS. 2315 * 2316 * @param callback The AsyncCallback delegate 2317 * @param state An object that contains state information for this request 2318 * @param syncFolderId The Id of the folder containing the item to synchronize with 2319 * @param propertySet The set of property to retrieve for synchronized item. 2320 * @param ignoredItemIds The optional list of item Ids that should be ignored. 2321 * @param maxChangesReturned The maximum number of changes that should be returned. 2322 * @param syncScope The sync scope identifying item to include in the 2323 * ChangeCollection 2324 * @param syncState The optional sync state representing the point in time when to 2325 * start the synchronization 2326 * @return An IAsyncResult that references the asynchronous request. 2327 * @throws Exception 2328 */ 2329 public IAsyncResult beginSyncFolderItems(AsyncCallback callback, Object state, FolderId syncFolderId, 2330 PropertySet propertySet, 2331 Iterable<ItemId> ignoredItemIds, int maxChangesReturned, 2332 SyncFolderItemsScope syncScope, String syncState) throws Exception { 2333 return this.buildSyncFolderItemsRequest(syncFolderId, propertySet, 2334 ignoredItemIds, maxChangesReturned, syncScope, syncState) 2335 .beginExecute(callback); 2336 } 2337 2338 /** 2339 * Ends an asynchronous request to synchronize the item of a specific 2340 * folder. 2341 * 2342 * @param asyncResult An IAsyncResult that references the asynchronous request. 2343 * @return A ChangeCollection containing a list of changes that occurred in 2344 * the specified folder. 2345 * @throws Exception 2346 */ 2347 public ChangeCollection<ItemChange> endSyncFolderItems(IAsyncResult asyncResult) throws Exception { 2348 SyncFolderItemsRequest request = AsyncRequestResult.extractServiceRequest(this, asyncResult); 2349 2350 return request.endExecute(asyncResult).getResponseAtIndex(0).getChanges(); 2351 } 2352 2353 /** 2354 * Builds a request to synchronize the item of a specific folder. 2355 * 2356 * @param syncFolderId The Id of the folder containing the item to synchronize with 2357 * @param propertySet The set of property to retrieve for synchronized item. 2358 * @param ignoredItemIds The optional list of item Ids that should be ignored 2359 * @param maxChangesReturned The maximum number of changes that should be returned. 2360 * @param syncScope The sync scope identifying item to include in the 2361 * ChangeCollection. 2362 * @param syncState The optional sync state representing the point in time when to 2363 * start the synchronization. 2364 * @return A request to synchronize the item of a specific folder. 2365 * @throws Exception 2366 */ 2367 private SyncFolderItemsRequest buildSyncFolderItemsRequest( 2368 FolderId syncFolderId, PropertySet propertySet, 2369 Iterable<ItemId> ignoredItemIds, int maxChangesReturned, 2370 SyncFolderItemsScope syncScope, String syncState) throws Exception { 2371 EwsUtilities.validateParam(syncFolderId, "syncFolderId"); 2372 EwsUtilities.validateParam(propertySet, "propertySet"); 2373 2374 SyncFolderItemsRequest request = new SyncFolderItemsRequest(this); 2375 2376 request.setSyncFolderId(syncFolderId); 2377 request.setPropertySet(propertySet); 2378 if (ignoredItemIds != null) { 2379 request.getIgnoredItemIds().addRange(ignoredItemIds); 2380 } 2381 request.setMaxChangesReturned(maxChangesReturned); 2382 request.setSyncScope(syncScope); 2383 request.setSyncState(syncState); 2384 2385 return request; 2386 } 2387 2388 /** 2389 * Synchronizes the sub-folder of a specific folder. Calling this method 2390 * results in a call to EWS. 2391 * 2392 * @param syncFolderId the sync folder id 2393 * @param propertySet the property set 2394 * @param syncState the sync state 2395 * @return A ChangeCollection containing a list of changes that occurred in 2396 * the specified folder. 2397 * @throws Exception the exception 2398 */ 2399 public ChangeCollection<FolderChange> syncFolderHierarchy( 2400 FolderId syncFolderId, PropertySet propertySet, String syncState) 2401 throws Exception { 2402 return this.buildSyncFolderHierarchyRequest(syncFolderId, propertySet, 2403 syncState).execute().getResponseAtIndex(0).getChanges(); 2404 } 2405 2406 /** 2407 * Begins an asynchronous request to synchronize the sub-folder of a 2408 * specific folder. Calling this method results in a call to EWS. 2409 * 2410 * @param callback The AsyncCallback delegate 2411 * @param state An object that contains state information for this request. 2412 * @param syncFolderId The Id of the folder containing the item to synchronize with. 2413 * A null value indicates the root folder of the mailbox. 2414 * @param propertySet The set of property to retrieve for synchronized item. 2415 * @param syncState The optional sync state representing the point in time when to 2416 * start the synchronization. 2417 * @return An IAsyncResult that references the asynchronous request 2418 * @throws Exception 2419 */ 2420 public IAsyncResult beginSyncFolderHierarchy(AsyncCallback callback, Object state, FolderId syncFolderId, 2421 PropertySet propertySet, 2422 String syncState) throws Exception { 2423 return this.buildSyncFolderHierarchyRequest(syncFolderId, propertySet, 2424 syncState).beginExecute(callback); 2425 } 2426 2427 /** 2428 * Synchronizes the entire folder hierarchy of the mailbox this Service is 2429 * connected to. Calling this method results in a call to EWS. 2430 * 2431 * @param propertySet The set of property to retrieve for synchronized item. 2432 * @param syncState The optional sync state representing the point in time when to 2433 * start the synchronization. 2434 * @return A ChangeCollection containing a list of changes that occurred in 2435 * the specified folder. 2436 * @throws Exception 2437 */ 2438 public ChangeCollection<FolderChange> syncFolderHierarchy( 2439 PropertySet propertySet, String syncState) 2440 throws Exception { 2441 return this.syncFolderHierarchy(null, propertySet, syncState); 2442 } 2443 2444 /* 2445 * Begins an asynchronous request to synchronize the entire folder hierarchy 2446 * of the mailbox this Service is connected to. Calling this method results 2447 * in a call to EWS 2448 * 2449 * @param callback 2450 * The AsyncCallback delegate 2451 * @param state 2452 * An object that contains state information for this request. 2453 * @param propertySet 2454 * The set of property to retrieve for synchronized item. 2455 * @param syncState 2456 * The optional sync state representing the point in time when to 2457 * start the synchronization. 2458 * @return An IAsyncResult that references the asynchronous request 2459 * @throws Exception 2460 public IAsyncResult beginSyncFolderHierarchy(FolderId syncFolderId, PropertySet propertySet, String syncState) throws Exception { 2461 return this.beginSyncFolderHierarchy(null,null, null, 2462 propertySet, syncState); 2463 }*/ 2464 2465 /** 2466 * Ends an asynchronous request to synchronize the specified folder 2467 * hierarchy of the mailbox this Service is connected to. 2468 * 2469 * @param asyncResult An IAsyncResult that references the asynchronous request. 2470 * @return A ChangeCollection containing a list of changes that occurred in 2471 * the specified folder. 2472 * @throws Exception 2473 */ 2474 public ChangeCollection<FolderChange> endSyncFolderHierarchy(IAsyncResult asyncResult) throws Exception { 2475 SyncFolderHierarchyRequest request = AsyncRequestResult.extractServiceRequest(this, asyncResult); 2476 2477 return request.endExecute(asyncResult).getResponseAtIndex(0).getChanges(); 2478 } 2479 2480 /** 2481 * Builds a request to synchronize the specified folder hierarchy of the 2482 * mailbox this Service is connected to. 2483 * 2484 * @param syncFolderId The Id of the folder containing the item to synchronize with. 2485 * A null value indicates the root folder of the mailbox. 2486 * @param propertySet The set of property to retrieve for synchronized item. 2487 * @param syncState The optional sync state representing the point in time when to 2488 * start the synchronization. 2489 * @return A request to synchronize the specified folder hierarchy of the 2490 * mailbox this Service is connected to 2491 * @throws Exception 2492 */ 2493 private SyncFolderHierarchyRequest buildSyncFolderHierarchyRequest( 2494 FolderId syncFolderId, PropertySet propertySet, String syncState) 2495 throws Exception { 2496 EwsUtilities.validateParamAllowNull(syncFolderId, "syncFolderId"); // Null 2497 // syncFolderId 2498 // is 2499 // allowed 2500 EwsUtilities.validateParam(propertySet, "propertySet"); 2501 2502 SyncFolderHierarchyRequest request = new SyncFolderHierarchyRequest(this); 2503 2504 request.setPropertySet(propertySet); 2505 request.setSyncFolderId(syncFolderId); 2506 request.setSyncState(syncState); 2507 2508 return request; 2509 } 2510 2511 // Availability operations 2512 2513 /** 2514 * Gets Out of Office (OOF) settings for a specific user. Calling this 2515 * method results in a call to EWS. 2516 * 2517 * @param smtpAddress the smtp address 2518 * @return An OofSettings instance containing OOF information for the 2519 * specified user. 2520 * @throws Exception the exception 2521 */ 2522 public OofSettings getUserOofSettings(String smtpAddress) throws Exception { 2523 EwsUtilities.validateParam(smtpAddress, "smtpAddress"); 2524 GetUserOofSettingsRequest request = new GetUserOofSettingsRequest(this); 2525 request.setSmtpAddress(smtpAddress); 2526 2527 return request.execute().getOofSettings(); 2528 } 2529 2530 /** 2531 * Sets Out of Office (OOF) settings for a specific user. Calling this 2532 * method results in a call to EWS. 2533 * 2534 * @param smtpAddress the smtp address 2535 * @param oofSettings the oof settings 2536 * @throws Exception the exception 2537 */ 2538 public void setUserOofSettings(String smtpAddress, OofSettings oofSettings) 2539 throws Exception { 2540 EwsUtilities.validateParam(smtpAddress, "smtpAddress"); 2541 EwsUtilities.validateParam(oofSettings, "oofSettings"); 2542 2543 SetUserOofSettingsRequest request = new SetUserOofSettingsRequest(this); 2544 2545 request.setSmtpAddress(smtpAddress); 2546 request.setOofSettings(oofSettings); 2547 2548 request.execute(); 2549 } 2550 2551 /** 2552 * Gets detailed information about the availability of a set of users, 2553 * rooms, and resources within a specified time window. 2554 * 2555 * @param attendees the attendees 2556 * @param timeWindow the time window 2557 * @param requestedData the requested data 2558 * @param options the options 2559 * @return The availability information for each user appears in a unique 2560 * FreeBusyResponse object. The order of users in the request 2561 * determines the order of availability data for each user in the 2562 * response. 2563 * @throws Exception the exception 2564 */ 2565 public GetUserAvailabilityResults getUserAvailability( 2566 Iterable<AttendeeInfo> attendees, TimeWindow timeWindow, 2567 AvailabilityData requestedData, AvailabilityOptions options) 2568 throws Exception { 2569 EwsUtilities.validateParamCollection(attendees.iterator(), "attendees"); 2570 EwsUtilities.validateParam(timeWindow, "timeWindow"); 2571 EwsUtilities.validateParam(options, "options"); 2572 2573 GetUserAvailabilityRequest request = new GetUserAvailabilityRequest(this); 2574 2575 request.setAttendees(attendees); 2576 request.setTimeWindow(timeWindow); 2577 request.setRequestedData(requestedData); 2578 request.setOptions(options); 2579 2580 return request.execute(); 2581 } 2582 2583 /** 2584 * Gets detailed information about the availability of a set of users, 2585 * rooms, and resources within a specified time window. 2586 * 2587 * @param attendees the attendees 2588 * @param timeWindow the time window 2589 * @param requestedData the requested data 2590 * @return The availability information for each user appears in a unique 2591 * FreeBusyResponse object. The order of users in the request 2592 * determines the order of availability data for each user in the 2593 * response. 2594 * @throws Exception the exception 2595 */ 2596 public GetUserAvailabilityResults getUserAvailability( 2597 Iterable<AttendeeInfo> attendees, TimeWindow timeWindow, 2598 AvailabilityData requestedData) throws Exception { 2599 return this.getUserAvailability(attendees, timeWindow, requestedData, 2600 new AvailabilityOptions()); 2601 } 2602 2603 /** 2604 * Retrieves a collection of all room lists in the organization. 2605 * 2606 * @return An EmailAddressCollection containing all the room lists in the 2607 * organization 2608 * @throws Exception the exception 2609 */ 2610 public EmailAddressCollection getRoomLists() throws Exception { 2611 GetRoomListsRequest request = new GetRoomListsRequest(this); 2612 return request.execute().getRoomLists(); 2613 } 2614 2615 /** 2616 * Retrieves a collection of all room lists in the specified room list in 2617 * the organization. 2618 * 2619 * @param emailAddress the email address 2620 * @return A collection of EmailAddress objects representing all the rooms 2621 * within the specifed room list. 2622 * @throws Exception the exception 2623 */ 2624 public Collection<EmailAddress> getRooms(EmailAddress emailAddress) 2625 throws Exception { 2626 EwsUtilities.validateParam(emailAddress, "emailAddress"); 2627 GetRoomsRequest request = new GetRoomsRequest(this); 2628 request.setRoomList(emailAddress); 2629 2630 return request.execute().getRooms(); 2631 } 2632 2633 // region Conversation 2634 2635 /** 2636 * Retrieves a collection of all Conversations in the specified Folder. 2637 * 2638 * @param view The view controlling the number of conversations returned. 2639 * @param filter The search filter. Only search filter class supported 2640 * SearchFilter.IsEqualTo 2641 * @param folderId The Id of the folder in which to search for conversations. 2642 * @throws Exception 2643 */ 2644 private Collection<Conversation> findConversation( 2645 ConversationIndexedItemView view, SearchFilter.IsEqualTo filter, 2646 FolderId folderId) throws Exception { 2647 EwsUtilities.validateParam(view, "view"); 2648 EwsUtilities.validateParamAllowNull(filter, "filter"); 2649 EwsUtilities.validateParam(folderId, "folderId"); 2650 EwsUtilities.validateMethodVersion(this, 2651 ExchangeVersion.Exchange2010_SP1, "FindConversation"); 2652 2653 FindConversationRequest request = new FindConversationRequest(this); 2654 request.setIndexedItemView(view); 2655 request.setConversationViewFilter(filter); 2656 request.setFolderId(new FolderIdWrapper(folderId)); 2657 2658 return request.execute().getConversations(); 2659 } 2660 2661 /** 2662 * Retrieves a collection of all Conversations in the specified Folder. 2663 * 2664 * @param view The view controlling the number of conversations returned. 2665 * @param folderId The Id of the folder in which to search for conversations. 2666 * @throws Exception 2667 */ 2668 public Collection<Conversation> findConversation( 2669 ConversationIndexedItemView view, FolderId folderId) 2670 throws Exception { 2671 return this.findConversation(view, null, folderId); 2672 } 2673 2674 /** 2675 * Applies ConversationAction on the specified conversation. 2676 * 2677 * @param actionType ConversationAction 2678 * @param conversationIds The conversation ids. 2679 * @param processRightAway True to process at once . This is blocking and false to let 2680 * the Assitant process it in the back ground 2681 * @param categories Catgories that need to be stamped can be null or empty 2682 * @param enableAlwaysDelete True moves every current and future messages in the 2683 * conversation to deleted item folder. False stops the alwasy 2684 * delete action. This is applicable only if the action is 2685 * AlwaysDelete 2686 * @param destinationFolderId Applicable if the action is AlwaysMove. This moves every 2687 * current message and future message in the conversation to the 2688 * specified folder. Can be null if tis is then it stops the 2689 * always move action 2690 * @param errorHandlingMode The error handling mode. 2691 * @throws Exception 2692 */ 2693 private ServiceResponseCollection<ServiceResponse> applyConversationAction( 2694 ConversationActionType actionType, 2695 Iterable<ConversationId> conversationIds, boolean processRightAway, 2696 StringList categories, boolean enableAlwaysDelete, 2697 FolderId destinationFolderId, ServiceErrorHandling errorHandlingMode) 2698 throws Exception { 2699 EwsUtilities.ewsAssert(actionType == ConversationActionType.AlwaysCategorize 2700 || actionType == ConversationActionType.AlwaysMove 2701 || actionType == ConversationActionType.AlwaysDelete, "ApplyConversationAction", 2702 "Invalic actionType"); 2703 2704 EwsUtilities.validateParam(conversationIds, "conversationId"); 2705 EwsUtilities.validateMethodVersion(this, 2706 ExchangeVersion.Exchange2010_SP1, "ApplyConversationAction"); 2707 2708 ApplyConversationActionRequest request = new ApplyConversationActionRequest( 2709 this, errorHandlingMode); 2710 ConversationAction action = new ConversationAction(); 2711 2712 for (ConversationId conversationId : conversationIds) { 2713 action.setAction(actionType); 2714 action.setConversationId(conversationId); 2715 action.setProcessRightAway(processRightAway); 2716 action.setCategories(categories); 2717 action.setEnableAlwaysDelete(enableAlwaysDelete); 2718 action 2719 .setDestinationFolderId(destinationFolderId != null ? new FolderIdWrapper( 2720 destinationFolderId) 2721 : null); 2722 request.getConversationActions().add(action); 2723 } 2724 2725 return request.execute(); 2726 } 2727 2728 /** 2729 * Applies one time conversation action on item in specified folder inside 2730 * the conversation. 2731 * 2732 * @param actionType The action 2733 * @param idTimePairs The id time pairs. 2734 * @param contextFolderId The context folder id. 2735 * @param destinationFolderId The destination folder id. 2736 * @param deleteType Type of the delete. 2737 * @param isRead The is read. 2738 * @param errorHandlingMode The error handling mode. 2739 * @throws Exception 2740 */ 2741 private ServiceResponseCollection<ServiceResponse> applyConversationOneTimeAction( 2742 ConversationActionType actionType, 2743 Iterable<HashMap<ConversationId, Date>> idTimePairs, 2744 FolderId contextFolderId, FolderId destinationFolderId, 2745 DeleteMode deleteType, Boolean isRead, 2746 ServiceErrorHandling errorHandlingMode) throws Exception { 2747 EwsUtilities.ewsAssert( 2748 actionType == ConversationActionType.Move || actionType == ConversationActionType.Delete 2749 || actionType == ConversationActionType.SetReadState || actionType == ConversationActionType.Copy, 2750 "ApplyConversationOneTimeAction", "Invalid actionType"); 2751 2752 EwsUtilities.validateParamCollection(idTimePairs.iterator(), 2753 "idTimePairs"); 2754 EwsUtilities.validateMethodVersion(this, 2755 ExchangeVersion.Exchange2010_SP1, "ApplyConversationAction"); 2756 2757 ApplyConversationActionRequest request = new ApplyConversationActionRequest( 2758 this, errorHandlingMode); 2759 2760 for (HashMap<ConversationId, Date> idTimePair : idTimePairs) { 2761 ConversationAction action = new ConversationAction(); 2762 2763 action.setAction(actionType); 2764 action.setConversationId(idTimePair.keySet().iterator().next()); 2765 action 2766 .setContextFolderId(contextFolderId != null ? new FolderIdWrapper( 2767 contextFolderId) 2768 : null); 2769 action 2770 .setDestinationFolderId(destinationFolderId != null ? new FolderIdWrapper( 2771 destinationFolderId) 2772 : null); 2773 action.setConversationLastSyncTime(idTimePair.values().iterator() 2774 .next()); 2775 action.setIsRead(isRead); 2776 action.setDeleteType(deleteType); 2777 2778 request.getConversationActions().add(action); 2779 } 2780 2781 return request.execute(); 2782 } 2783 2784 /** 2785 * Sets up a conversation so that any item received within that conversation 2786 * is always categorized. Calling this method results in a call to EWS. 2787 * 2788 * @param conversationId The id of the conversation. 2789 * @param categories The categories that should be stamped on item in the 2790 * conversation. 2791 * @param processSynchronously Indicates whether the method should return only once enabling 2792 * this rule and stamping existing item in the conversation is 2793 * completely done. If processSynchronously is false, the method 2794 * returns immediately. 2795 * @throws Exception 2796 */ 2797 public ServiceResponseCollection<ServiceResponse> enableAlwaysCategorizeItemsInConversations( 2798 Iterable<ConversationId> conversationId, 2799 Iterable<String> categories, boolean processSynchronously) 2800 throws Exception { 2801 EwsUtilities.validateParamCollection(categories.iterator(), 2802 "categories"); 2803 return this.applyConversationAction( 2804 ConversationActionType.AlwaysCategorize, conversationId, 2805 processSynchronously, new StringList(categories), false, null, 2806 ServiceErrorHandling.ReturnErrors); 2807 } 2808 2809 /** 2810 * Sets up a conversation so that any item received within that conversation 2811 * is no longer categorized. Calling this method results in a call to EWS. 2812 * 2813 * @param conversationId The id of the conversation. 2814 * @param processSynchronously Indicates whether the method should return only once enabling 2815 * this rule and stamping existing item in the conversation is 2816 * completely done. If processSynchronously is false, the method 2817 * returns immediately. 2818 * @throws Exception 2819 */ 2820 public ServiceResponseCollection<ServiceResponse> disableAlwaysCategorizeItemsInConversations( 2821 Iterable<ConversationId> conversationId, 2822 boolean processSynchronously) throws Exception { 2823 return this.applyConversationAction( 2824 ConversationActionType.AlwaysCategorize, conversationId, 2825 processSynchronously, null, false, null, 2826 ServiceErrorHandling.ReturnErrors); 2827 } 2828 2829 /** 2830 * Sets up a conversation so that any item received within that conversation 2831 * is always moved to Deleted Items folder. Calling this method results in a 2832 * call to EWS. 2833 * 2834 * @param conversationId The id of the conversation. 2835 * @param processSynchronously Indicates whether the method should return only once enabling 2836 * this rule and stamping existing item in the conversation is 2837 * completely done. If processSynchronously is false, the method 2838 * returns immediately. 2839 * @throws Exception 2840 */ 2841 public ServiceResponseCollection<ServiceResponse> enableAlwaysDeleteItemsInConversations( 2842 Iterable<ConversationId> conversationId, 2843 boolean processSynchronously) throws Exception { 2844 return this.applyConversationAction( 2845 ConversationActionType.AlwaysDelete, conversationId, 2846 processSynchronously, null, true, null, 2847 ServiceErrorHandling.ReturnErrors); 2848 } 2849 2850 /** 2851 * Sets up a conversation so that any item received within that conversation 2852 * is no longer moved to Deleted Items folder. Calling this method results 2853 * in a call to EWS. 2854 * 2855 * @param conversationId The id of the conversation. 2856 * @param processSynchronously Indicates whether the method should return only once enabling 2857 * this rule and stamping existing item in the conversation is 2858 * completely done. If processSynchronously is false, the method 2859 * returns immediately. 2860 * @throws Exception 2861 */ 2862 public ServiceResponseCollection<ServiceResponse> disableAlwaysDeleteItemsInConversations( 2863 Iterable<ConversationId> conversationId, 2864 boolean processSynchronously) throws Exception { 2865 return this.applyConversationAction( 2866 ConversationActionType.AlwaysDelete, conversationId, 2867 processSynchronously, null, false, null, 2868 ServiceErrorHandling.ReturnErrors); 2869 } 2870 2871 /** 2872 * Sets up a conversation so that any item received within that conversation 2873 * is always moved to a specific folder. Calling this method results in a 2874 * call to EWS. 2875 * 2876 * @param conversationId The Id of the folder to which conversation item should be 2877 * moved. 2878 * @param destinationFolderId The Id of the destination folder. 2879 * @param processSynchronously Indicates whether the method should return only once enabling 2880 * this rule and stamping existing item in the conversation is 2881 * completely done. If processSynchronously is false, the method 2882 * returns immediately. 2883 * @throws Exception 2884 */ 2885 public ServiceResponseCollection<ServiceResponse> enableAlwaysMoveItemsInConversations( 2886 Iterable<ConversationId> conversationId, 2887 FolderId destinationFolderId, boolean processSynchronously) 2888 throws Exception { 2889 EwsUtilities.validateParam(destinationFolderId, "destinationFolderId"); 2890 return this.applyConversationAction(ConversationActionType.AlwaysMove, 2891 conversationId, processSynchronously, null, false, 2892 destinationFolderId, ServiceErrorHandling.ReturnErrors); 2893 } 2894 2895 /** 2896 * Sets up a conversation so that any item received within that conversation 2897 * is no longer moved to a specific folder. Calling this method results in a 2898 * call to EWS. 2899 * 2900 * @param conversationIds The conversation ids. 2901 * @param processSynchronously Indicates whether the method should return only once disabling 2902 * this rule is completely done. If processSynchronously is 2903 * false, the method returns immediately. 2904 * @throws Exception 2905 */ 2906 public ServiceResponseCollection<ServiceResponse> disableAlwaysMoveItemsInConversations( 2907 Iterable<ConversationId> conversationIds, 2908 boolean processSynchronously) throws Exception { 2909 return this.applyConversationAction(ConversationActionType.AlwaysMove, 2910 conversationIds, processSynchronously, null, false, null, 2911 ServiceErrorHandling.ReturnErrors); 2912 } 2913 2914 /** 2915 * Moves the item in the specified conversation to the specified 2916 * destination folder. Calling this method results in a call to EWS. 2917 * 2918 * @param idLastSyncTimePairs The pairs of Id of conversation whose item should be moved 2919 * and the dateTime conversation was last synced (Items received 2920 * after that dateTime will not be moved). 2921 * @param contextFolderId The Id of the folder that contains the conversation. 2922 * @param destinationFolderId The Id of the destination folder. 2923 * @throws Exception 2924 */ 2925 public ServiceResponseCollection<ServiceResponse> moveItemsInConversations( 2926 Iterable<HashMap<ConversationId, Date>> idLastSyncTimePairs, 2927 FolderId contextFolderId, FolderId destinationFolderId) 2928 throws Exception { 2929 EwsUtilities.validateParam(destinationFolderId, "destinationFolderId"); 2930 return this.applyConversationOneTimeAction(ConversationActionType.Move, 2931 idLastSyncTimePairs, contextFolderId, destinationFolderId, 2932 null, null, ServiceErrorHandling.ReturnErrors); 2933 } 2934 2935 /** 2936 * Copies the item in the specified conversation to the specified 2937 * destination folder. Calling this method results in a call to EWS. 2938 * 2939 * @param idLastSyncTimePairs The pairs of Id of conversation whose item should be copied 2940 * and the dateTime conversation was last synced (Items received 2941 * after that dateTime will not be copied). 2942 * @param contextFolderId The context folder id. 2943 * @param destinationFolderId The destination folder id. 2944 * @throws Exception 2945 */ 2946 public ServiceResponseCollection<ServiceResponse> copyItemsInConversations( 2947 Iterable<HashMap<ConversationId, Date>> idLastSyncTimePairs, 2948 FolderId contextFolderId, FolderId destinationFolderId) 2949 throws Exception { 2950 EwsUtilities.validateParam(destinationFolderId, "destinationFolderId"); 2951 return this.applyConversationOneTimeAction(ConversationActionType.Copy, 2952 idLastSyncTimePairs, contextFolderId, destinationFolderId, 2953 null, null, ServiceErrorHandling.ReturnErrors); 2954 } 2955 2956 /** 2957 * Deletes the item in the specified conversation. Calling this method 2958 * results in a call to EWS. 2959 * 2960 * @param idLastSyncTimePairs The pairs of Id of conversation whose item should be deleted 2961 * and the date and time conversation was last synced (Items 2962 * received after that date will not be deleted). conversation 2963 * was last synced (Items received after that dateTime will not 2964 * be copied). 2965 * @param contextFolderId The Id of the folder that contains the conversation. 2966 * @param deleteMode The deletion mode 2967 * @throws Exception 2968 */ 2969 public ServiceResponseCollection<ServiceResponse> deleteItemsInConversations( 2970 Iterable<HashMap<ConversationId, Date>> idLastSyncTimePairs, 2971 FolderId contextFolderId, DeleteMode deleteMode) throws Exception { 2972 return this.applyConversationOneTimeAction( 2973 ConversationActionType.Delete, idLastSyncTimePairs, 2974 contextFolderId, null, deleteMode, null, 2975 ServiceErrorHandling.ReturnErrors); 2976 } 2977 2978 /** 2979 * Sets the read state for item in conversation. Calling this mehtod would 2980 * result in call to EWS. 2981 * 2982 * @param idLastSyncTimePairs The pairs of Id of conversation whose item should read state 2983 * set and the date and time conversation was last synced (Items 2984 * received after that date will not have their read state set). 2985 * was last synced (Items received after that date will not be 2986 * deleted). conversation was last synced (Items received after 2987 * that dateTime will not be copied). 2988 * @param contextFolderId The Id of the folder that contains the conversation. 2989 * @param isRead if set to <em>true</em>, conversation item are marked as read; 2990 * otherwise they are marked as unread. 2991 * @throws Exception 2992 */ 2993 public ServiceResponseCollection<ServiceResponse> setReadStateForItemsInConversations( 2994 Iterable<HashMap<ConversationId, Date>> idLastSyncTimePairs, 2995 FolderId contextFolderId, boolean isRead) throws Exception { 2996 return this.applyConversationOneTimeAction( 2997 ConversationActionType.SetReadState, idLastSyncTimePairs, 2998 contextFolderId, null, null, isRead, 2999 ServiceErrorHandling.ReturnErrors); 3000 } 3001 3002 private ServiceResponseCollection<ExportItemsResponse> internalExportItems( 3003 Iterable<ItemId> itemIds, ServiceErrorHandling errorHandling) throws Exception { 3004 ExportItemsRequest request = new ExportItemsRequest(this, errorHandling); 3005 request.getItemIds().addRange(itemIds); 3006 return request.execute(); 3007 } 3008 3009 public ExportItemsResponse exportItem(ItemId itemId) throws Exception { 3010 EwsUtilities.validateParam(itemId, "itemId"); 3011 ServiceResponseCollection<ExportItemsResponse> responses = internalExportItems(Arrays.asList(itemId), 3012 ServiceErrorHandling.ThrowOnError); 3013 ExportItemsResponse response = responses.getResponseAtIndex(0); 3014 response.throwIfNecessary(); 3015 return response; 3016 } 3017 3018 public ServiceResponseCollection<ExportItemsResponse> exportItems( 3019 Iterable<ItemId> itemIds) throws Exception { 3020 EwsUtilities.validateParamCollection(itemIds.iterator(), "itemIds"); 3021 return this.internalExportItems(itemIds, 3022 ServiceErrorHandling.ReturnErrors); 3023 } 3024 3025 private ServiceResponseCollection<UploadItemsResponse> internalUploadItems( 3026 List<UploadItem> items, ServiceErrorHandling errorHandling) throws Exception { 3027 UploadItemsRequest request = new UploadItemsRequest(this, errorHandling); 3028 request.setItems(items); 3029 return request.execute(); 3030 } 3031 3032 public UploadItemsResponse uploadItem(UploadItem item) throws Exception { 3033 EwsUtilities.validateParam(item, "item"); 3034 ServiceResponseCollection<UploadItemsResponse> responses = internalUploadItems(Arrays.asList(item), 3035 ServiceErrorHandling.ThrowOnError); 3036 UploadItemsResponse response = responses.getResponseAtIndex(0); 3037 response.throwIfNecessary(); 3038 return response; 3039 } 3040 3041 public ServiceResponseCollection<UploadItemsResponse> uploadItems( 3042 List<UploadItem> items) throws Exception { 3043 return this.internalUploadItems(items, 3044 ServiceErrorHandling.ReturnErrors); 3045 } 3046 // Id conversion operations 3047 3048 /** 3049 * Converts multiple Ids from one format to another in a single call to 3050 * EWS. 3051 * 3052 * @param ids the ids 3053 * @param destinationFormat the destination format 3054 * @param errorHandling the error handling 3055 * @return A ServiceResponseCollection providing conversion results for each 3056 * specified Ids. 3057 * @throws Exception the exception 3058 */ 3059 private ServiceResponseCollection<ConvertIdResponse> internalConvertIds( 3060 Iterable<AlternateIdBase> ids, IdFormat destinationFormat, 3061 ServiceErrorHandling errorHandling) throws Exception { 3062 EwsUtilities.validateParamCollection(ids.iterator(), "ids"); 3063 3064 ConvertIdRequest request = new ConvertIdRequest(this, errorHandling); 3065 3066 request.getIds().addAll((Collection<? extends AlternateIdBase>) ids); 3067 request.setDestinationFormat(destinationFormat); 3068 3069 return request.execute(); 3070 } 3071 3072 /** 3073 * Converts multiple Ids from one format to another in a single call to 3074 * EWS. 3075 * 3076 * @param ids the ids 3077 * @param destinationFormat the destination format 3078 * @return A ServiceResponseCollection providing conversion results for each 3079 * specified Ids. 3080 * @throws Exception the exception 3081 */ 3082 public ServiceResponseCollection<ConvertIdResponse> convertIds( 3083 Iterable<AlternateIdBase> ids, IdFormat destinationFormat) 3084 throws Exception { 3085 EwsUtilities.validateParamCollection(ids.iterator(), "ids"); 3086 3087 return this.internalConvertIds(ids, destinationFormat, 3088 ServiceErrorHandling.ReturnErrors); 3089 } 3090 3091 /** 3092 * Converts Id from one format to another in a single call to EWS. 3093 * 3094 * @param id the id 3095 * @param destinationFormat the destination format 3096 * @return The converted Id. 3097 * @throws Exception the exception 3098 */ 3099 public AlternateIdBase convertId(AlternateIdBase id, 3100 IdFormat destinationFormat) throws Exception { 3101 EwsUtilities.validateParam(id, "id"); 3102 3103 List<AlternateIdBase> alternateIdBaseArray = new ArrayList<AlternateIdBase>(); 3104 alternateIdBaseArray.add(id); 3105 3106 ServiceResponseCollection<ConvertIdResponse> responses = this 3107 .internalConvertIds(alternateIdBaseArray, destinationFormat, 3108 ServiceErrorHandling.ThrowOnError); 3109 3110 return responses.getResponseAtIndex(0).getConvertedId(); 3111 } 3112 3113 /** 3114 * Adds delegates to a specific mailbox. Calling this method results in a 3115 * call to EWS. 3116 * 3117 * @param mailbox the mailbox 3118 * @param meetingRequestsDeliveryScope the meeting request delivery scope 3119 * @param delegateUsers the delegate users 3120 * @return A collection of DelegateUserResponse objects providing the 3121 * results of the operation. 3122 * @throws Exception the exception 3123 */ 3124 public Collection<DelegateUserResponse> addDelegates(Mailbox mailbox, 3125 MeetingRequestsDeliveryScope meetingRequestsDeliveryScope, 3126 DelegateUser... delegateUsers) throws Exception { 3127 return addDelegates(mailbox, meetingRequestsDeliveryScope, 3128 Arrays.asList(delegateUsers)); 3129 } 3130 3131 /** 3132 * Adds delegates to a specific mailbox. Calling this method results in a 3133 * call to EWS. 3134 * 3135 * @param mailbox the mailbox 3136 * @param meetingRequestsDeliveryScope the meeting request delivery scope 3137 * @param delegateUsers the delegate users 3138 * @return A collection of DelegateUserResponse objects providing the 3139 * results of the operation. 3140 * @throws Exception the exception 3141 */ 3142 public Collection<DelegateUserResponse> addDelegates(Mailbox mailbox, 3143 MeetingRequestsDeliveryScope meetingRequestsDeliveryScope, 3144 Iterable<DelegateUser> delegateUsers) throws Exception { 3145 EwsUtilities.validateParam(mailbox, "mailbox"); 3146 EwsUtilities.validateParamCollection(delegateUsers.iterator(), 3147 "delegateUsers"); 3148 3149 AddDelegateRequest request = new AddDelegateRequest(this); 3150 request.setMailbox(mailbox); 3151 3152 for (DelegateUser user : delegateUsers) { 3153 request.getDelegateUsers().add(user); 3154 } 3155 3156 request.setMeetingRequestsDeliveryScope(meetingRequestsDeliveryScope); 3157 3158 DelegateManagementResponse response = request.execute(); 3159 return response.getDelegateUserResponses(); 3160 } 3161 3162 /** 3163 * Updates delegates on a specific mailbox. Calling this method results in 3164 * a call to EWS. 3165 * 3166 * @param mailbox the mailbox 3167 * @param meetingRequestsDeliveryScope the meeting request delivery scope 3168 * @param delegateUsers the delegate users 3169 * @return A collection of DelegateUserResponse objects providing the 3170 * results of the operation. 3171 * @throws Exception the exception 3172 */ 3173 public Collection<DelegateUserResponse> updateDelegates(Mailbox mailbox, 3174 MeetingRequestsDeliveryScope meetingRequestsDeliveryScope, 3175 DelegateUser... delegateUsers) throws Exception { 3176 return this.updateDelegates(mailbox, meetingRequestsDeliveryScope, 3177 Arrays.asList(delegateUsers)); 3178 } 3179 3180 /** 3181 * Updates delegates on a specific mailbox. Calling this method results in 3182 * a call to EWS. 3183 * 3184 * @param mailbox the mailbox 3185 * @param meetingRequestsDeliveryScope the meeting request delivery scope 3186 * @param delegateUsers the delegate users 3187 * @return A collection of DelegateUserResponse objects providing the 3188 * results of the operation. 3189 * @throws Exception the exception 3190 */ 3191 public Collection<DelegateUserResponse> updateDelegates(Mailbox mailbox, 3192 MeetingRequestsDeliveryScope meetingRequestsDeliveryScope, 3193 Iterable<DelegateUser> delegateUsers) throws Exception { 3194 EwsUtilities.validateParam(mailbox, "mailbox"); 3195 EwsUtilities.validateParamCollection(delegateUsers.iterator(), 3196 "delegateUsers"); 3197 3198 UpdateDelegateRequest request = new UpdateDelegateRequest(this); 3199 3200 request.setMailbox(mailbox); 3201 3202 ArrayList<DelegateUser> delUser = new ArrayList<DelegateUser>(); 3203 for (DelegateUser user : delegateUsers) { 3204 delUser.add(user); 3205 } 3206 request.getDelegateUsers().addAll(delUser); 3207 request.setMeetingRequestsDeliveryScope(meetingRequestsDeliveryScope); 3208 3209 DelegateManagementResponse response = request.execute(); 3210 return response.getDelegateUserResponses(); 3211 } 3212 3213 /** 3214 * Removes delegates on a specific mailbox. Calling this method results in 3215 * a call to EWS. 3216 * 3217 * @param mailbox the mailbox 3218 * @param userIds the user ids 3219 * @return A collection of DelegateUserResponse objects providing the 3220 * results of the operation. 3221 * @throws Exception the exception 3222 */ 3223 public Collection<DelegateUserResponse> removeDelegates(Mailbox mailbox, 3224 UserId... userIds) throws Exception { 3225 return removeDelegates(mailbox, Arrays.asList(userIds)); 3226 } 3227 3228 /** 3229 * Removes delegates on a specific mailbox. Calling this method results in 3230 * a call to EWS. 3231 * 3232 * @param mailbox the mailbox 3233 * @param userIds the user ids 3234 * @return A collection of DelegateUserResponse objects providing the 3235 * results of the operation. 3236 * @throws Exception the exception 3237 */ 3238 public Collection<DelegateUserResponse> removeDelegates(Mailbox mailbox, 3239 Iterable<UserId> userIds) throws Exception { 3240 EwsUtilities.validateParam(mailbox, "mailbox"); 3241 EwsUtilities.validateParamCollection(userIds.iterator(), "userIds"); 3242 3243 RemoveDelegateRequest request = new RemoveDelegateRequest(this); 3244 request.setMailbox(mailbox); 3245 3246 ArrayList<UserId> delUser = new ArrayList<UserId>(); 3247 for (UserId user : userIds) { 3248 delUser.add(user); 3249 } 3250 request.getUserIds().addAll(delUser); 3251 3252 DelegateManagementResponse response = request.execute(); 3253 return response.getDelegateUserResponses(); 3254 } 3255 3256 /** 3257 * Retrieves the delegates of a specific mailbox. Calling this method 3258 * results in a call to EWS. 3259 * 3260 * @param mailbox the mailbox 3261 * @param includePermissions the include permissions 3262 * @param userIds the user ids 3263 * @return A GetDelegateResponse providing the results of the operation. 3264 * @throws Exception the exception 3265 */ 3266 public DelegateInformation getDelegates(Mailbox mailbox, 3267 boolean includePermissions, UserId... userIds) throws Exception { 3268 return this.getDelegates(mailbox, includePermissions, Arrays.asList(userIds)); 3269 } 3270 3271 /** 3272 * Retrieves the delegates of a specific mailbox. Calling this method 3273 * results in a call to EWS. 3274 * 3275 * @param mailbox the mailbox 3276 * @param includePermissions the include permissions 3277 * @param userIds the user ids 3278 * @return A GetDelegateResponse providing the results of the operation. 3279 * @throws Exception the exception 3280 */ 3281 public DelegateInformation getDelegates(Mailbox mailbox, 3282 boolean includePermissions, Iterable<UserId> userIds) 3283 throws Exception { 3284 EwsUtilities.validateParam(mailbox, "mailbox"); 3285 3286 GetDelegateRequest request = new GetDelegateRequest(this); 3287 3288 request.setMailbox(mailbox); 3289 3290 ArrayList<UserId> delUser = new ArrayList<UserId>(); 3291 for (UserId user : userIds) { 3292 delUser.add(user); 3293 } 3294 request.getUserIds().addAll(delUser); 3295 request.setIncludePermissions(includePermissions); 3296 3297 GetDelegateResponse response = request.execute(); 3298 DelegateInformation delegateInformation = new DelegateInformation( 3299 (List<DelegateUserResponse>) response 3300 .getDelegateUserResponses(), response 3301 .getMeetingRequestsDeliveryScope()); 3302 3303 return delegateInformation; 3304 } 3305 3306 /** 3307 * Creates the user configuration. 3308 * 3309 * @param userConfiguration the user configuration 3310 * @throws Exception the exception 3311 */ 3312 public void createUserConfiguration(UserConfiguration userConfiguration) 3313 throws Exception { 3314 EwsUtilities.validateParam(userConfiguration, "userConfiguration"); 3315 3316 CreateUserConfigurationRequest request = new CreateUserConfigurationRequest( 3317 this); 3318 3319 request.setUserConfiguration(userConfiguration); 3320 3321 request.execute(); 3322 } 3323 3324 /** 3325 * Creates a UserConfiguration. 3326 * 3327 * @param name the name 3328 * @param parentFolderId the parent folder id 3329 * @throws Exception the exception 3330 */ 3331 public void deleteUserConfiguration(String name, FolderId parentFolderId) 3332 throws Exception { 3333 EwsUtilities.validateParam(name, "name"); 3334 EwsUtilities.validateParam(parentFolderId, "parentFolderId"); 3335 3336 DeleteUserConfigurationRequest request = new DeleteUserConfigurationRequest( 3337 this); 3338 3339 request.setName(name); 3340 request.setParentFolderId(parentFolderId); 3341 request.execute(); 3342 } 3343 3344 /** 3345 * Creates a UserConfiguration. 3346 * 3347 * @param name the name 3348 * @param parentFolderId the parent folder id 3349 * @param properties the property 3350 * @return the user configuration 3351 * @throws Exception the exception 3352 */ 3353 public UserConfiguration getUserConfiguration(String name, FolderId parentFolderId, 3354 UserConfigurationProperties properties) 3355 throws Exception { 3356 EwsUtilities.validateParam(name, "name"); 3357 EwsUtilities.validateParam(parentFolderId, "parentFolderId"); 3358 3359 GetUserConfigurationRequest request = new GetUserConfigurationRequest(this); 3360 3361 request.setName(name); 3362 request.setParentFolderId(parentFolderId); 3363 request.setProperties(EnumSet.of(properties)); 3364 3365 return request.execute().getResponseAtIndex(0).getUserConfiguration(); 3366 } 3367 3368 /** 3369 * Loads the property of the specified userConfiguration. 3370 * 3371 * @param userConfiguration the user configuration 3372 * @param properties the property 3373 * @throws Exception the exception 3374 */ 3375 public void loadPropertiesForUserConfiguration(UserConfiguration userConfiguration, 3376 UserConfigurationProperties properties) throws Exception { 3377 EwsUtilities.ewsAssert(userConfiguration != null, "ExchangeService.LoadPropertiesForUserConfiguration", 3378 "userConfiguration is null"); 3379 3380 GetUserConfigurationRequest request = new GetUserConfigurationRequest( 3381 this); 3382 3383 request.setUserConfiguration(userConfiguration); 3384 request.setProperties(EnumSet.of(properties)); 3385 3386 request.execute(); 3387 } 3388 3389 /** 3390 * Updates a UserConfiguration. 3391 * 3392 * @param userConfiguration the user configuration 3393 * @throws Exception the exception 3394 */ 3395 public void updateUserConfiguration(UserConfiguration userConfiguration) 3396 throws Exception { 3397 EwsUtilities.validateParam(userConfiguration, "userConfiguration"); 3398 UpdateUserConfigurationRequest request = new UpdateUserConfigurationRequest(this); 3399 3400 request.setUserConfiguration(userConfiguration); 3401 3402 request.execute(); 3403 } 3404 3405 // region InboxRule operations 3406 3407 /** 3408 * Retrieves inbox rules of the authenticated user. 3409 * 3410 * @return A RuleCollection object containing the authenticated users inbox 3411 * rules. 3412 * @throws Exception 3413 */ 3414 public RuleCollection getInboxRules() throws Exception { 3415 GetInboxRulesRequest request = new GetInboxRulesRequest(this); 3416 return request.execute().getRules(); 3417 } 3418 3419 /** 3420 * Retrieves the inbox rules of the specified user. 3421 * 3422 * @param mailboxSmtpAddress The SMTP address of the user whose inbox rules should be 3423 * retrieved 3424 * @return A RuleCollection object containing the inbox rules of the 3425 * specified user. 3426 * @throws Exception 3427 */ 3428 public RuleCollection getInboxRules(String mailboxSmtpAddress) 3429 throws Exception { 3430 EwsUtilities.validateParam(mailboxSmtpAddress, "MailboxSmtpAddress"); 3431 3432 GetInboxRulesRequest request = new GetInboxRulesRequest(this); 3433 request.setmailboxSmtpAddress(mailboxSmtpAddress); 3434 return request.execute().getRules(); 3435 } 3436 3437 /** 3438 * Updates the authenticated user's inbox rules by applying the specified 3439 * operations. 3440 * 3441 * @param operations The operations that should be applied to the user's inbox 3442 * rules. 3443 * @param removeOutlookRuleBlob Indicate whether or not to remove Outlook Rule Blob. 3444 * @throws Exception 3445 */ 3446 public void updateInboxRules(Iterable<RuleOperation> operations, 3447 boolean removeOutlookRuleBlob) throws Exception { 3448 UpdateInboxRulesRequest request = new UpdateInboxRulesRequest(this); 3449 request.setInboxRuleOperations(operations); 3450 request.setRemoveOutlookRuleBlob(removeOutlookRuleBlob); 3451 request.execute(); 3452 } 3453 3454 /** 3455 * Updates the authenticated user's inbox rules by applying the specified 3456 * operations. 3457 * 3458 * @param operations The operations that should be applied to the user's inbox 3459 * rules. 3460 * @param removeOutlookRuleBlob Indicate whether or not to remove Outlook Rule Blob. 3461 * @param mailboxSmtpAddress The SMTP address of the user whose inbox rules should be 3462 * retrieved 3463 * @throws Exception 3464 */ 3465 public void updateInboxRules(Iterable<RuleOperation> operations, 3466 boolean removeOutlookRuleBlob, String mailboxSmtpAddress) 3467 throws Exception { 3468 UpdateInboxRulesRequest request = new UpdateInboxRulesRequest(this); 3469 request.setInboxRuleOperations(operations); 3470 request.setRemoveOutlookRuleBlob(removeOutlookRuleBlob); 3471 request.setMailboxSmtpAddress(mailboxSmtpAddress); 3472 request.execute(); 3473 } 3474 3475 /** 3476 * Default implementation of AutodiscoverRedirectionUrlValidationCallback. 3477 * Always returns true indicating that the URL can be used. 3478 * 3479 * @param redirectionUrl the redirection url 3480 * @return Returns true. 3481 * @throws AutodiscoverLocalException the autodiscover local exception 3482 */ 3483 private boolean defaultAutodiscoverRedirectionUrlValidationCallback( 3484 String redirectionUrl) throws AutodiscoverLocalException { 3485 throw new AutodiscoverLocalException(String.format( 3486 "Autodiscover blocked a potentially insecure redirection to %s. To allow Autodiscover to follow the redirection, use the AutodiscoverUrl(string, AutodiscoverRedirectionUrlValidationCallback) overload.", redirectionUrl)); 3487 } 3488 3489 /** 3490 * Initializes the Url property to the Exchange Web Services URL for the 3491 * specified e-mail address by calling the Autodiscover service. 3492 * 3493 * @param emailAddress the email address 3494 * @throws Exception the exception 3495 */ 3496 public void autodiscoverUrl(String emailAddress) throws Exception { 3497 this.autodiscoverUrl(emailAddress, this); 3498 } 3499 3500 /** 3501 * Initializes the Url property to the Exchange Web Services URL for the 3502 * specified e-mail address by calling the Autodiscover service. 3503 * 3504 * @param emailAddress the email address to use. 3505 * @param validateRedirectionUrlCallback The callback used to validate redirection URL 3506 * @throws Exception the exception 3507 */ 3508 public void autodiscoverUrl(String emailAddress, 3509 IAutodiscoverRedirectionUrl validateRedirectionUrlCallback) 3510 throws Exception { 3511 URI exchangeServiceUrl = null; 3512 3513 if (this.getRequestedServerVersion().ordinal() > ExchangeVersion.Exchange2007_SP1 3514 .ordinal()) { 3515 try { 3516 exchangeServiceUrl = this.getAutodiscoverUrl(emailAddress, this 3517 .getRequestedServerVersion(), 3518 validateRedirectionUrlCallback); 3519 this.setUrl(this 3520 .adjustServiceUriFromCredentials(exchangeServiceUrl)); 3521 return; 3522 } catch (AutodiscoverLocalException ex) { 3523 3524 this.traceMessage(TraceFlags.AutodiscoverResponse, String 3525 .format("Autodiscover service call " 3526 + "failed with error '%s'. " 3527 + "Will try legacy service", ex.getMessage())); 3528 3529 } catch (ServiceRemoteException ex) { 3530 // E14:321785 -- Special case: if 3531 // the caller's account is locked 3532 // we want to return this exception, not continue. 3533 if (ex instanceof AccountIsLockedException) { 3534 throw new AccountIsLockedException(ex.getMessage(), 3535 exchangeServiceUrl, ex); 3536 } 3537 3538 this.traceMessage(TraceFlags.AutodiscoverResponse, String 3539 .format("Autodiscover service call " 3540 + "failed with error '%s'. " 3541 + "Will try legacy service", ex.getMessage())); 3542 } 3543 } 3544 3545 // Try legacy Autodiscover provider 3546 3547 exchangeServiceUrl = this.getAutodiscoverUrl(emailAddress, 3548 ExchangeVersion.Exchange2007_SP1, 3549 validateRedirectionUrlCallback); 3550 3551 this.setUrl(this.adjustServiceUriFromCredentials(exchangeServiceUrl)); 3552 } 3553 3554 /** 3555 * Autodiscover will always return the "plain" EWS endpoint URL but if the 3556 * client is using WindowsLive credential, ExchangeService needs to use the 3557 * WS-Security endpoint. 3558 * 3559 * @param uri the uri 3560 * @return Adjusted URL. 3561 * @throws Exception 3562 */ 3563 private URI adjustServiceUriFromCredentials(URI uri) 3564 throws Exception { 3565 return (this.getCredentials() != null) ? this.getCredentials() 3566 .adjustUrl(uri) : uri; 3567 } 3568 3569 /** 3570 * Gets the autodiscover url. 3571 * 3572 * @param emailAddress the email address 3573 * @param requestedServerVersion the Exchange version 3574 * @param validateRedirectionUrlCallback the validate redirection url callback 3575 * @return the autodiscover url 3576 * @throws Exception the exception 3577 */ 3578 private URI getAutodiscoverUrl(String emailAddress, 3579 ExchangeVersion requestedServerVersion, 3580 IAutodiscoverRedirectionUrl validateRedirectionUrlCallback) 3581 throws Exception { 3582 3583 AutodiscoverService autodiscoverService = new AutodiscoverService(this, requestedServerVersion); 3584 autodiscoverService.setWebProxy(getWebProxy()); 3585 autodiscoverService.setTimeout(getTimeout()); 3586 3587 autodiscoverService 3588 .setRedirectionUrlValidationCallback(validateRedirectionUrlCallback); 3589 autodiscoverService.setEnableScpLookup(this.getEnableScpLookup()); 3590 3591 GetUserSettingsResponse response = autodiscoverService.getUserSettings( 3592 emailAddress, UserSettingName.InternalEwsUrl, 3593 UserSettingName.ExternalEwsUrl); 3594 3595 switch (response.getErrorCode()) { 3596 case NoError: 3597 return this.getEwsUrlFromResponse(response, autodiscoverService 3598 .isExternal().TRUE); 3599 3600 case InvalidUser: 3601 throw new ServiceRemoteException(String.format("Invalid user: '%s'", 3602 emailAddress)); 3603 3604 case InvalidRequest: 3605 throw new ServiceRemoteException(String.format("Invalid Autodiscover request: '%s'", response 3606 .getErrorMessage())); 3607 3608 default: 3609 this.traceMessage(TraceFlags.AutodiscoverConfiguration, String 3610 .format("No EWS Url returned for user %s, " 3611 + "error code is %s", emailAddress, response 3612 .getErrorCode())); 3613 3614 throw new ServiceRemoteException(response.getErrorMessage()); 3615 } 3616 } 3617 3618 private URI getEwsUrlFromResponse(GetUserSettingsResponse response, 3619 boolean isExternal) throws URISyntaxException, AutodiscoverLocalException { 3620 String uriString; 3621 3622 // Bug E14:59063 -- Figure out which URL to use: Internal or External. 3623 // Bug E14:67646 -- AutoDiscover may not return an external protocol. 3624 // First try external, then internal. 3625 // Bug E14:82650 -- Either protocol 3626 // may be returned without a configured URL. 3627 OutParam<String> outParam = new OutParam<String>(); 3628 if ((isExternal && response.tryGetSettingValue(String.class, 3629 UserSettingName.ExternalEwsUrl, outParam))) { 3630 uriString = outParam.getParam(); 3631 if (!(uriString == null || uriString.isEmpty())) { 3632 return new URI(uriString); 3633 } 3634 } 3635 if ((response.tryGetSettingValue(String.class, 3636 UserSettingName.InternalEwsUrl, outParam) || response 3637 .tryGetSettingValue(String.class, 3638 UserSettingName.ExternalEwsUrl, outParam))) { 3639 uriString = outParam.getParam(); 3640 if (!(uriString == null || uriString.isEmpty())) { 3641 return new URI(uriString); 3642 } 3643 } 3644 3645 // If Autodiscover doesn't return an 3646 // internal or external EWS URL, throw an exception. 3647 throw new AutodiscoverLocalException( 3648 "The Autodiscover service didn't return an appropriate URL that can be used for the ExchangeService Autodiscover URL."); 3649 } 3650 3651 // region Diagnostic Method -- Only used by test 3652 3653 /** 3654 * Executes the diagnostic method. 3655 * 3656 * @param verb The verb. 3657 * @param parameter The parameter. 3658 * @throws Exception 3659 */ 3660 protected Document executeDiagnosticMethod(String verb, Node parameter) 3661 throws Exception { 3662 ExecuteDiagnosticMethodRequest request = new ExecuteDiagnosticMethodRequest(this); 3663 request.setVerb(verb); 3664 request.setParameter(parameter); 3665 3666 return request.execute().getResponseAtIndex(0).getReturnValue(); 3667 3668 } 3669 3670 // endregion 3671 3672 // region Validation 3673 3674 /** 3675 * Validates this instance. 3676 * 3677 * @throws ServiceLocalException the service local exception 3678 */ 3679 @Override public void validate() throws ServiceLocalException { 3680 super.validate(); 3681 if (this.getUrl() == null) { 3682 throw new ServiceLocalException("The Url property on the ExchangeService object must be set."); 3683 } 3684 } 3685 3686 // region Constructors 3687 3688 /** 3689 * Initializes a new instance of the {@link ExchangeService} class, 3690 * targeting the specified version of EWS and scoped to the to the system's 3691 * current time zone. 3692 */ 3693 public ExchangeService() { 3694 super(); 3695 } 3696 3697 /** 3698 * Initializes a new instance of the {@link ExchangeService} class, 3699 * targeting the specified version of EWS and scoped to the system's current 3700 * time zone. 3701 * 3702 * @param requestedServerVersion the requested server version 3703 */ 3704 public ExchangeService(ExchangeVersion requestedServerVersion) { 3705 super(requestedServerVersion); 3706 } 3707 3708 /** 3709 * Initializes a new instance of the {@link ExchangeService} class, 3710 * targeting the specified version of EWS and scoped to the system's current 3711 * time zone. 3712 * 3713 * Additionally specifies an external HttpClient to use, e.g. one wired up 3714 * with a thread-safe pooling http connection factory. It is perfectly 3715 * acceptable for both arguments to use the same HttpClient. 3716 * 3717 * @param requestedServerVersion the requested server version 3718 * @param httpClient external HttpClient instance to use 3719 * @param httpPoolingClient external HttpClient instance to use for pooling 3720 */ 3721 public ExchangeService(ExchangeVersion requestedServerVersion, CloseableHttpClient httpClient, 3722 CloseableHttpClient httpPoolingClient) { 3723 super(requestedServerVersion, httpClient, httpPoolingClient); 3724 } 3725 3726 // Utilities 3727 3728 /** 3729 * Prepare http web request. 3730 * 3731 * @return the http web request 3732 * @throws ServiceLocalException the service local exception 3733 * @throws java.net.URISyntaxException the uRI syntax exception 3734 */ 3735 public HttpWebRequest prepareHttpWebRequest() 3736 throws ServiceLocalException, URISyntaxException { 3737 try { 3738 this.url = this.adjustServiceUriFromCredentials(this.getUrl()); 3739 } catch (Exception e) { 3740 LOG.error(e); 3741 } 3742 return this.prepareHttpWebRequestForUrl(url, this 3743 .getAcceptGzipEncoding(), true); 3744 } 3745 3746 /** 3747 * Prepares a http web request from a pooling connection manager, used for subscriptions. 3748 * 3749 * @return A http web request 3750 * @throws ServiceLocalException The service local exception 3751 * @throws java.net.URISyntaxException the uRI syntax exception 3752 */ 3753 public HttpWebRequest prepareHttpPoolingWebRequest() 3754 throws ServiceLocalException, URISyntaxException { 3755 try { 3756 this.url = this.adjustServiceUriFromCredentials(this.getUrl()); 3757 } catch (Exception e) { 3758 LOG.error(e); 3759 } 3760 return this.prepareHttpPoolingWebRequestForUrl(url, this 3761 .getAcceptGzipEncoding(), true); 3762 } 3763 3764 /** 3765 * Processes an HTTP error response. 3766 * 3767 * @param httpWebResponse The HTTP web response. 3768 * @param webException The web exception 3769 * @throws Exception 3770 */ 3771 @Override public void processHttpErrorResponse(HttpWebRequest httpWebResponse, Exception webException) throws Exception { 3772 this.internalProcessHttpErrorResponse(httpWebResponse, webException, 3773 TraceFlags.EwsResponseHttpHeaders, TraceFlags.EwsResponse); 3774 } 3775 3776 // Properties 3777 3778 /** 3779 * Gets the URL of the Exchange Web Services. 3780 * 3781 * @return URL of the Exchange Web Services. 3782 */ 3783 public URI getUrl() { 3784 return url; 3785 } 3786 3787 /** 3788 * Sets the URL of the Exchange Web Services. 3789 * 3790 * @param url URL of the Exchange Web Services. 3791 */ 3792 public void setUrl(URI url) { 3793 this.url = url; 3794 } 3795 3796 /** 3797 * Gets the impersonated user id. 3798 * 3799 * @return the impersonated user id 3800 */ 3801 public ImpersonatedUserId getImpersonatedUserId() { 3802 return impersonatedUserId; 3803 } 3804 3805 /** 3806 * Sets the impersonated user id. 3807 * 3808 * @param impersonatedUserId the new impersonated user id 3809 */ 3810 public void setImpersonatedUserId(ImpersonatedUserId impersonatedUserId) { 3811 this.impersonatedUserId = impersonatedUserId; 3812 } 3813 3814 /** 3815 * Gets the preferred culture. 3816 * 3817 * @return the preferred culture 3818 */ 3819 public Locale getPreferredCulture() { 3820 return preferredCulture; 3821 } 3822 3823 /** 3824 * Sets the preferred culture. 3825 * 3826 * @param preferredCulture the new preferred culture 3827 */ 3828 public void setPreferredCulture(Locale preferredCulture) { 3829 this.preferredCulture = preferredCulture; 3830 } 3831 3832 /** 3833 * Gets the DateTime precision for DateTime values returned from Exchange 3834 * Web Services. 3835 * 3836 * @return the DateTimePrecision 3837 */ 3838 public DateTimePrecision getDateTimePrecision() { 3839 return this.dateTimePrecision; 3840 } 3841 3842 /** 3843 * Sets the DateTime precision for DateTime values Web Services. 3844 * @param d date time precision 3845 */ 3846 public void setDateTimePrecision(DateTimePrecision d) { 3847 this.dateTimePrecision = d; 3848 } 3849 3850 /** 3851 * Sets the DateTime precision for DateTime values returned from Exchange 3852 * Web Services. 3853 * 3854 * @param dateTimePrecision the new DateTimePrecision 3855 */ 3856 public void setPreferredCulture(DateTimePrecision dateTimePrecision) { 3857 this.dateTimePrecision = dateTimePrecision; 3858 } 3859 3860 /** 3861 * Gets the file attachment content handler. 3862 * 3863 * @return the file attachment content handler 3864 */ 3865 public IFileAttachmentContentHandler getFileAttachmentContentHandler() { 3866 return this.fileAttachmentContentHandler; 3867 } 3868 3869 /** 3870 * Sets the file attachment content handler. 3871 * 3872 * @param fileAttachmentContentHandler the new file attachment content handler 3873 */ 3874 public void setFileAttachmentContentHandler( 3875 IFileAttachmentContentHandler fileAttachmentContentHandler) { 3876 this.fileAttachmentContentHandler = fileAttachmentContentHandler; 3877 } 3878 3879 /** 3880 * Provides access to the Unified Messaging functionalities. 3881 * 3882 * @return the unified messaging 3883 */ 3884 public UnifiedMessaging getUnifiedMessaging() { 3885 if (this.unifiedMessaging == null) { 3886 this.unifiedMessaging = new UnifiedMessaging(this); 3887 } 3888 3889 return this.unifiedMessaging; 3890 } 3891 3892 /** 3893 * Gets or sets a value indicating whether the AutodiscoverUrl method should 3894 * perform SCP (Service Connection Point) record lookup when determining the 3895 * Autodiscover service URL. 3896 * 3897 * @return enable scp lookup flag. 3898 */ 3899 public boolean getEnableScpLookup() { 3900 return this.enableScpLookup; 3901 } 3902 3903 3904 public void setEnableScpLookup(boolean value) { 3905 this.enableScpLookup = value; 3906 } 3907 3908 /** 3909 * Returns true whether Exchange2007 compatibility mode is enabled, false otherwise. 3910 */ 3911 public boolean getExchange2007CompatibilityMode() { 3912 return this.exchange2007CompatibilityMode; 3913 } 3914 3915 /** 3916 * Set the flag indicating if the Exchange2007 compatibility mode is enabled. 3917 * 3918 * <p> 3919 * In order to support E12 servers, the <code>exchange2007CompatibilityMode</code> property, 3920 * set to true, can be used to indicate that we should use "Exchange2007" as the server version String 3921 * rather than Exchange2007_SP1. 3922 * </p> 3923 * 3924 * @param value true if the Exchange2007 compatibility mode is enabled. 3925 */ 3926 public void setExchange2007CompatibilityMode(boolean value) { 3927 this.exchange2007CompatibilityMode = value; 3928 } 3929 3930 /** 3931 * Retrieves the definitions of the specified server-side time zones. 3932 * 3933 * @param timeZoneIds the time zone ids 3934 * @return A Collection containing the definitions of the specified time 3935 * zones. 3936 * @throws Exception 3937 */ 3938 public Collection<TimeZoneDefinition> getServerTimeZones( 3939 Iterable<String> timeZoneIds) throws Exception { 3940 Map<String, TimeZoneDefinition> timeZoneMap = new HashMap<String, TimeZoneDefinition>(); 3941 3942 GetServerTimeZonesRequest request = new GetServerTimeZonesRequest(this); 3943 ServiceResponseCollection<GetServerTimeZonesResponse> responses = request.execute(); 3944 for (GetServerTimeZonesResponse response : responses) { 3945 for (TimeZoneDefinition tzd : response.getTimeZones()) { 3946 timeZoneMap.put(tzd.getId(), tzd); 3947 } 3948 } 3949 3950 Collection<TimeZoneDefinition> timeZoneList = new ArrayList<TimeZoneDefinition>(); 3951 3952 for (String timeZoneId : timeZoneIds) { 3953 timeZoneList.add(timeZoneMap.get(timeZoneId)); 3954 } 3955 3956 return timeZoneList; 3957 } 3958 3959 /** 3960 * Retrieves the definitions of all server-side time zones. 3961 * 3962 * @return A Collection containing the definitions of the specified time 3963 * zones. 3964 * @throws Exception 3965 */ 3966 public Collection<TimeZoneDefinition> getServerTimeZones() throws Exception { 3967 GetServerTimeZonesRequest request = new GetServerTimeZonesRequest(this); 3968 Collection<TimeZoneDefinition> timeZoneList = new ArrayList<TimeZoneDefinition>(); 3969 ServiceResponseCollection<GetServerTimeZonesResponse> responses = request.execute(); 3970 for (GetServerTimeZonesResponse response : responses) { 3971 timeZoneList.addAll(response.getTimeZones()); 3972 } 3973 3974 return timeZoneList; 3975 } 3976 3977 /* 3978 * (non-Javadoc) 3979 * 3980 * @seemicrosoft.exchange.webservices.AutodiscoverRedirectionUrlInterface# 3981 * autodiscoverRedirectionUrlValidationCallback(java.lang.String) 3982 */ 3983 public boolean autodiscoverRedirectionUrlValidationCallback( 3984 String redirectionUrl) throws AutodiscoverLocalException { 3985 return defaultAutodiscoverRedirectionUrlValidationCallback(redirectionUrl); 3986 3987 } 3988 3989}