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