/// <summary> /// Generates a response from a GCalRequest /// </summary> /// <returns></returns> public string GenerateResponse() { /* Create a string builder to hold the text for the response */ StringBuilder result = new StringBuilder(4096); /* Create an exchange provider */ ExchangeService gateway = new ExchangeService( ConfigCache.ExchangeServerUrl, ConfigCache.ExchangeUserLogin, ConfigCache.ExchangeUserPassword); /* Return the exchangers from the GCal Request that was passed in */ DateTimeRange range = new DateTimeRange(request.UTCStartDate, request.UTCEndDate); ExchangeUserDict exchangeUsers = gateway.SearchByEmail(range, request.ExchangeUsers); /* Create the header of the request */ result.AppendFormat("['{0}','{1}',", request.VersionNumber, request.MessageId); result.AppendFormat("['_ME_AddData','{0}/{1}','{2}'", DateUtil.FormatDateForGoogle(request.StartDate), DateUtil.FormatDateForGoogle(request.EndDate), DateUtil.FormatDateTimeForGoogle(request.Since)); /* Flag for inserting commas */ bool firstUser = true; result.Append(",["); foreach (ExchangeUser user in exchangeUsers.Values) { /* Don't add a comma if this is the first user */ if (!firstUser) { result.Append(","); } /* Add the user's credentials */ string email = ConfigCache.MapToExternalDomain(user.Email); result.AppendFormat("'{0}','{1}','{2}',[", user.DisplayName, email, (int)user.AccessLevel); GenerateResponseForTimeBlocks(user, result); result.Append("]"); firstUser = false; } result.Append("]"); result.Append("]"); result.Append("]"); log.Info("GCal Free/Busy response successfully generated."); log.DebugFormat("Response = {0}", result); return result.ToString(); }
public static ExchangeUserDict QueryActiveDirectory(string ldapFilter) { ExchangeService gw = new ExchangeService( ConfigCache.ExchangeServerUrl, ConfigCache.ExchangeUserLogin, ConfigCache.ExchangeUserPassword ); return gw.QueryActiveDirectory( ldapFilter ); }
public static ExchangeUserDict QueryFreeBusy(string email) { ExchangeService gw = new ExchangeService( ConfigCache.ExchangeServerUrl, ConfigCache.ExchangeUserLogin, ConfigCache.ExchangeUserPassword ); DateTimeRange range = new DateTimeRange( DateUtil.NowUtc.AddDays(-7), DateUtil.NowUtc.AddDays(+7)); return gw.SearchByEmail( range, email ); }
public AppointmentLookupFuture( ExchangeService exchange, ExchangeUserDict users, DateTimeRange window) { this.exchange = exchange; this.users = users; this.syncWindow = window; // Only do this if appointment // lookup is enabled if (ConfigCache.EnableAppointmentLookup) { this.start(); } }
/// <summary> /// Sync a users free busy information between Google Calendar and the /// SchedulePlus Public Folder store /// </summary> /// <param name="user">The user to synchronize</param> /// <param name="googleAppsFeed">The Google Calendar events for the user</param> /// <param name="exchangeGateway">The Exchange Gateway to use</param> /// <param name="window">The DateTimeRange to synchronize for</param> public void SyncUser( ExchangeUser user, EventFeed googleAppsFeed, ExchangeService exchangeGateway, DateTimeRange window) { if (_log.IsInfoEnabled) { _log.InfoFormat("Creating F/B message. [User={0}]", user.Email); _log.DebugFormat("The feed time zone is {0}", googleAppsFeed.TimeZone.Value); } string userFreeBusyUrl = FreeBusyUrl.GenerateUrlFromDN(_exchangeServerUrl, user.LegacyExchangeDN); List<string> busyMonthValues = new List<string>(); List<string> busyBase64Data = new List<string>(); List<string> tentativeMonthValues = new List<string>(); List<string> tentativeBase64Data = new List<string>(); ConvertEventsToFreeBusy(user, googleAppsFeed.Entries, window, busyMonthValues, busyBase64Data, tentativeMonthValues, tentativeBase64Data); string startDate = FreeBusyConverter.ConvertToSysTime(window.Start).ToString(); string endDate = FreeBusyConverter.ConvertToSysTime(window.End).ToString(); exchangeGateway.FreeBusy.CreateFreeBusyMessage(userFreeBusyUrl, user.FreeBusyCommonName, busyMonthValues, busyBase64Data, tentativeMonthValues, tentativeBase64Data, startDate, endDate); if ( _log.IsInfoEnabled ) { _log.Info( "Free/Busy message with the right properties created successfully." ); } }
public static void WriteAppointment( string email, DateTime appointmentStart ) { DateTime appointmentEnd = appointmentStart.AddHours( 1 ); ExchangeService gw = new ExchangeService( ConfigCache.ExchangeServerUrl, ConfigCache.ExchangeAdminLogin, ConfigCache.ExchangeAdminPassword ); ExchangeUserDict users = gw.QueryActiveDirectory( string.Format("mail={0}", email )); if (users.Count != 0) { foreach (ExchangeUser user in users.Values) { Appointment appt = new Appointment(); appt.Subject = "GCalExchangeSync test appt"; appt.Location = "test"; appt.StartDate = appointmentStart; appt.EndDate = appointmentEnd; appt.MeetingStatus = MeetingStatus.Confirmed; appt.Created = DateUtil.NowUtc; appt.InstanceType = InstanceType.Single; List<Appointment> list = new List<Appointment>(); list.Add(appt); gw.Appointments.WriteAppointments(user, list); } } else { string msg = string.Format("User {0} not found", email); throw new Exception(msg); } }
public static void WriteFreeBusyMessage( string commonName ) { ExchangeService gw = new ExchangeService( ConfigCache.ExchangeFreeBusyServerUrl, ConfigCache.ExchangeUserLogin, ConfigCache.ExchangeUserPassword ); SchedulePlusFreeBusyWriter writer = new SchedulePlusFreeBusyWriter(); ExchangeUserDict users = QueryFreeBusy(commonName); if (users.Count < 1) { string msg = string.Format("User {0} not found", commonName); throw new Exception(msg); } if (users.Count > 1) { string msg = string.Format("More than one user matches {0}", commonName); throw new Exception(msg); } string userFreeBusyUrl = FreeBusyUrl.GenerateUrlFromDN( ConfigCache.ExchangeFreeBusyServerUrl, users[commonName].LegacyExchangeDN); List<string> emtpyList = new List<string>(); string nowMinus30Days = FreeBusyConverter.ConvertToSysTime(DateUtil.NowUtc.AddDays(-30)).ToString(); string nowPlus60Days = FreeBusyConverter.ConvertToSysTime(DateUtil.NowUtc.AddDays(60)).ToString(); gw.FreeBusy.CreateFreeBusyMessage(userFreeBusyUrl, commonName, emtpyList, emtpyList, emtpyList, emtpyList, nowMinus30Days, nowPlus60Days); }
/// <summary> /// Merges a users appointment schedule from with appointments generated from a /// GoogleApps feed /// </summary> /// <param name="user">User to update with Google Apps information</param> /// <param name="googleAppsFeed">Source feed to generate appointment information</param> /// <param name="exchangeGateway">Gateway to sync Appointments with</param> /// <param name="window">DateRange to sync for</param> public void SyncUser( ExchangeUser user, EventFeed googleAppsFeed, ExchangeService exchangeGateway, DateTimeRange window) { exchangeGateway.GetCalendarInfoForUser(user, window); if (!user.HaveAppointmentDetail) { // Cannot sync if there is no appointment detail log.InfoFormat("Skipped Sync of {0} due to missing appointment lookup failure", user.Email); return; } List<Appointment> toUpdate = new List<Appointment>(); List<Appointment> toDelete = new List<Appointment>(); List<Appointment> toCreate = new List<Appointment>(); OlsonTimeZone feedTimeZone = OlsonUtil.GetTimeZone(googleAppsFeed.TimeZone.Value); IntervalTree<Appointment> gcalApptTree = CreateAppointments(user, feedTimeZone, googleAppsFeed); /* Iterate through each Free/Busy time block for the user */ foreach (FreeBusyTimeBlock fbtb in user.BusyTimes.Values) { /* Iterate through each appointment for the Free/Busy time block */ foreach (Appointment appt in fbtb.Appointments) { log.Debug(String.Format("Exchange @ '{0} {1}'", appt.Range, ValidateOwnership(appt))); /* Validate that this is a GCalender appoint */ if ( ValidateOwnership( appt ) ) { /* If the GCalender appointments do not contain an * appointment for this period, add it for deletion */ if (gcalApptTree.FindExact(appt.Range) == null) { toDelete.Add( appt ); } } } } /* Iterate through each Google Apps appointment */ AppointmentCollection appointments = user.BusyTimes.Appointments; List<Appointment> gcalApptList = gcalApptTree.GetNodeList(); foreach (Appointment newAppt in gcalApptList) { // If the meeting was cancelled log.DebugFormat("Looking @ {0} {1}", newAppt.Range, newAppt.Range.Start.Kind); if ( newAppt.MeetingStatus == MeetingStatus.Cancelled ) { // Check if there is an existing appointment that matches List<Appointment> matches = appointments.Get(newAppt.Range); foreach (Appointment a in matches) { if (ValidateOwnership(a)) { toDelete.Add(a); } } // Work is done for this appointment, continue to next entry continue; } bool updatedAppointment = false; List<Appointment> apptList = appointments.Get(newAppt.Range); log.DebugFormat("Looking up preexisting event: {0} {1}", newAppt.Range, newAppt.Range.Start.Kind); log.DebugFormat("Found {0} matching items", apptList.Count); // Check that there is a free busy block that correlates with this appointment foreach ( Appointment existingAppt in apptList ) { if (ValidateOwnership(existingAppt) && !updatedAppointment) { UpdateAppointmentInfo(existingAppt, newAppt); toUpdate.Add( existingAppt ); updatedAppointment = true; } } if (!updatedAppointment) { toCreate.Add( newAppt ); log.DebugFormat("ADDING '{0}' - Not an update", newAppt.Range); } } if (log.IsInfoEnabled) { log.InfoFormat( "AppointmentWriter for '{0}'. [{1} deleted, {2} updated, {3} new]", user.Email, toDelete.Count, toUpdate.Count, toCreate.Count); } exchangeGateway.Appointments.DeleteAppointments(user, toDelete); // TODO: Updates are not currently published // exchangeGateway.Appointments.UpdateAppointments( user, updateAppointments ); exchangeGateway.Appointments.WriteAppointments(user, toCreate); }
/// <summary> /// Merges a users appointment schedule from with appointments generated from a /// GoogleApps feed /// </summary> /// <param name="user">User to update with Google Apps information</param> /// <param name="googleAppsFeed">Source feed to generate appointment information</param> /// <param name="exchangeGateway">Gateway to sync Appointments with</param> /// <param name="window">DateRange to sync for</param> public void SyncUser( ExchangeUser user, EventFeed googleAppsFeed, ExchangeService exchangeGateway, DateTimeRange window) { exchangeGateway.GetCalendarInfoForUser(user, window); if (!user.HaveAppointmentDetail) { // Cannot sync if there is no appointment detail log.InfoFormat("Skipped Sync of {0} due to missing appointment lookup failure", user.Email); return; } List <Appointment> toUpdate = new List <Appointment>(); List <Appointment> toDelete = new List <Appointment>(); List <Appointment> toCreate = new List <Appointment>(); OlsonTimeZone feedTimeZone = OlsonUtil.GetTimeZone(googleAppsFeed.TimeZone.Value); IntervalTree <Appointment> gcalApptTree = CreateAppointments(user, feedTimeZone, googleAppsFeed); /* Iterate through each Free/Busy time block for the user */ foreach (FreeBusyTimeBlock fbtb in user.BusyTimes.Values) { /* Iterate through each appointment for the Free/Busy time block */ foreach (Appointment appt in fbtb.Appointments) { log.Debug(String.Format("Exchange @ '{0} {1}'", appt.Range, ValidateOwnership(appt))); /* Validate that this is a GCalender appoint */ if (ValidateOwnership(appt)) { /* If the GCalender appointments do not contain an * appointment for this period, add it for deletion */ if (gcalApptTree.FindExact(appt.Range) == null) { toDelete.Add(appt); } } } } /* Iterate through each Google Apps appointment */ AppointmentCollection appointments = user.BusyTimes.Appointments; List <Appointment> gcalApptList = gcalApptTree.GetNodeList(); foreach (Appointment newAppt in gcalApptList) { // If the meeting was cancelled log.DebugFormat("Looking @ {0} {1}", newAppt.Range, newAppt.Range.Start.Kind); if (newAppt.MeetingStatus == MeetingStatus.Cancelled) { // Check if there is an existing appointment that matches List <Appointment> matches = appointments.Get(newAppt.Range); foreach (Appointment a in matches) { if (ValidateOwnership(a)) { toDelete.Add(a); } } // Work is done for this appointment, continue to next entry continue; } bool updatedAppointment = false; List <Appointment> apptList = appointments.Get(newAppt.Range); log.DebugFormat("Looking up preexisting event: {0} {1}", newAppt.Range, newAppt.Range.Start.Kind); log.DebugFormat("Found {0} matching items", apptList.Count); // Check that there is a free busy block that correlates with this appointment foreach (Appointment existingAppt in apptList) { if (ValidateOwnership(existingAppt) && !updatedAppointment) { UpdateAppointmentInfo(existingAppt, newAppt); toUpdate.Add(existingAppt); updatedAppointment = true; } } if (!updatedAppointment) { toCreate.Add(newAppt); log.DebugFormat("ADDING '{0}' - Not an update", newAppt.Range); } } if (log.IsInfoEnabled) { log.InfoFormat( "AppointmentWriter for '{0}'. [{1} deleted, {2} updated, {3} new]", user.Email, toDelete.Count, toUpdate.Count, toCreate.Count); } exchangeGateway.Appointments.DeleteAppointments(user, toDelete); // TODO: Updates are not currently published // exchangeGateway.Appointments.UpdateAppointments( user, updateAppointments ); exchangeGateway.Appointments.WriteAppointments(user, toCreate); }
/// <summary> /// Run the sync process from Google Calendar to Exchange /// </summary> /// <param name="threadCount">Number of threads to use to sync</param> public void RunSyncProcess( int threadCount ) { log.Info( "Exchange synchronization process started." ); using ( BlockTimer bt = new BlockTimer( "RunSyncProcess" ) ) { gcalGateway = new GCalGateway(googleAppsLogin, googleAppsPassword, googleAppsDomain, null); exchangeGateway = new ExchangeService(exchangeServer, networkLogin, networkPassword); ExchangeUserDict users; using ( BlockTimer loadUserTimer = new BlockTimer( "LoadUserList" ) ) { users = QueryExchangeForValidUsers(); } exchangeUsers = new List<ExchangeUser>(); freeBusyWriter = FreeBusyWriterFactory.GetWriter( exchangeUsers ); foreach ( ExchangeUser user in users.Values ) { exchangeUsers.Add( user ); } if ( exchangeUsers.Count == 0 ) { log.Warn( "No eligible users found for synchronization. Aborting sync process." ); return; } if ( threadCount < 1 ) threadCount = 1; modifiedDateUtil = new ModifiedDateUtil( ConfigCache.ServiceModifiedXmlFileName ); modifiedDateUtil.LoadModifiedTimes(); if ( threadCount == 1 ) { SyncUsers(); } else { StartSyncUserThreads( threadCount ); } modifiedDateUtil.PersistModifiedTimes(); gcalGateway = null; exchangeGateway = null; freeBusyWriter = null; modifiedDateUtil = null; exchangeUsers = null; System.GC.Collect(); log.DebugFormat("Memory after sync: {0}", System.GC.GetTotalMemory(false)); } }