/// <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);
        }
示例#9
0
        /// <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));
            }
        }