Description of ExchangeUtility.
Exemplo n.º 1
0
        /// <summary>
        /// Gets the Exchange user using powershell Get-User command
        /// </summary>
        /// <param name="cmdInfo">command info to get the user</param>
        /// <param name="attributes">attributes containing the Name</param>
        /// <returns><see cref="PSObject"/> with user info</returns>
        private PSObject GetUser(ExchangeConnector connector, PSExchangeConnector.CommandInfo cmdInfo, Name nameAttribute)
        {
            ExchangeConfiguration configuration = connector.Configuration;
            // assert we have user name
            string name = nameAttribute.GetNameValue();

            ExchangeUtility.NullCheck(name, "User name", configuration);

            ICollection <ConnectorAttribute> attributes = new List <ConnectorAttribute>();

            attributes.Add(nameAttribute);
            Command cmdUser = ExchangeUtility.GetCommand(cmdInfo, attributes, configuration);
            ICollection <PSObject> users = _helper.InvokePipeline(connector, cmdUser);

            if (users.Count == 1)
            {
                foreach (PSObject obj in users)
                {
                    return(obj);
                }
            }

            throw new ArgumentException(
                      configuration.ConnectorMessages.Format(
                          "ex_bad_username", "Provided User name is not unique or not existing"));
        }
Exemplo n.º 2
0
        // TODO move to appropriate place
        /// <summary>
        /// helper method for searching object in AD by UID
        /// </summary>
        /// <param name="uid">Uid of the searched </param>
        /// <param name="oclass">Object class</param>
        /// <param name="options">Operation options</param>
        /// <returns>Connector object found by the Uid</returns>
        internal ConnectorObject ADSearchByUid(ExchangeConnector connector, Uid uid, ObjectClass oclass, OperationOptions options)
        {
            ExchangeConfiguration configuration = connector.Configuration;

            ExchangeUtility.NullCheck(uid, "uid", configuration);
            ExchangeUtility.NullCheck(oclass, "oclass", configuration);
            if (options == null)
            {
                options = new OperationOptionsBuilder().Build();
            }

            ConnectorObject ret        = null;
            Filter          filter     = FilterBuilder.EqualTo(uid);
            var             translator = connector.ActiveDirectoryConnector.CreateFilterTranslator(oclass, options);
            IList <string>  queries    = translator.Translate(filter);

            if (queries.Count == 1)
            {
                ResultsHandler handler = new ResultsHandler()
                {
                    Handle = cobject =>
                    {
                        ret = cobject;
                        return(false);
                    }
                };
                connector.ActiveDirectoryConnector.ExecuteQuery(oclass, queries[0], handler, options);
            }

            return(ret);
        }
        /// <summary>
        /// helper method for searching object in AD by UID
        /// </summary>
        /// <param name="uid">Uid of the searched </param>
        /// <param name="oclass">Object class</param>
        /// <param name="options">Operation options</param>
        /// <returns>Connector object found by the Uid</returns>
        private ConnectorObject ADSearchByUid(Uid uid, ObjectClass oclass, OperationOptions options)
        {
            ExchangeUtility.NullCheck(uid, "uid", this.configuration);
            ExchangeUtility.NullCheck(oclass, "oclass", this.configuration);
            if (options == null)
            {
                options = new OperationOptionsBuilder().Build();
            }

            ConnectorObject ret        = null;
            Filter          filter     = FilterBuilder.EqualTo(uid);
            var             translator = base.CreateFilterTranslator(oclass, options);
            IList <string>  queries    = translator.Translate(filter);

            if (queries.Count == 1)
            {
                ResultsHandler handler = delegate(ConnectorObject cobject)
                {
                    ret = cobject;
                    return(false);
                };
                base.ExecuteQuery(oclass, queries[0], handler, options);
            }

            return(ret);
        }
        public void ExecuteQuery(ExecuteQueryContext context)
        {
            ExchangeConnector exconn = (ExchangeConnector)context.Connector;

            LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "SimplePowerShellObjectHandler: Executing query: query={0}", context.Query);

            Command cmdGet = ExchangeUtility.GetCommand(
                new PSExchangeConnector.CommandInfo(GetGetCommandName()), exconn.Configuration);

            if (context.Query != null)
            {
                cmdGet.Parameters.Add("Identity", context.Query);
            }
            ICollection <PSObject> objects;

            try {
                objects = _helper.InvokePipeline(exconn, cmdGet);
            } catch (ObjectNotFoundException e) {
                LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "SimplePowerShellObjectHandler: Executing query: got 'ObjectNotFound' exception ({0}), assuming suitable objects do not exist", e);
                return;
            }
            LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "SimplePowerShellObjectHandler: Executing query: got {0} objects", objects.Count);
            foreach (PSObject psobject in objects)
            {
                if (psobject != null)
                {
                    context.ResultsHandler.Handle(_helper.CreateConnectorObject(exconn, psobject, context.ObjectClass));
                }
            }
        }
        /// <summary>
        /// Implementation of SynOp.Sync
        /// </summary>
        /// <param name="objClass">Object class</param>
        /// <param name="token">Sync token</param>
        /// <param name="handler">Sync results handler</param>
        /// <param name="options">Operation options</param>
        public void Sync(
            ObjectClass oclass, SyncToken token, SyncResultsHandler handler, OperationOptions options)
        {
            const string operation = "Sync";

            ExchangeUtility.NullCheck(oclass, "oclass", this._configuration);

            LOG.Info("Exchange.Sync method; oclass = {0}, token = {1}", oclass, token);

            SyncOpContext context = new SyncOpContext()
            {
                Connector = this,
                ConnectorConfiguration = _configuration,
                ObjectClass            = oclass,
                OperationName          = operation,
                Options            = options,
                SyncToken          = token,
                SyncResultsHandler = handler
            };

            try {
                _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain);
                if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain))
                {
                    SyncMain(context);
                }
                _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain);
            } catch (Exception e) {
                LOG.Error(e, "Exception while executing Sync operation: {0}");
                throw;
            }

            // TODO what about executing a script on each returned item?
        }
        public void Delete(ObjectClass objClass, Uid uid, OperationOptions options)
        {
            const string operation = "Delete";

            plugins.OnBeforeDelete(objClass, uid, options, _configuration);

            ExchangeUtility.NullCheck(objClass, "objClass", this._configuration);
            ExchangeUtility.NullCheck(uid, "uid", this._configuration);

            LOG.Info("Exchange.Delete method; uid:\n{0}", uid.GetUidValue());

            DeleteOpContext context = new DeleteOpContext()
            {
                Connector = this,
                ConnectorConfiguration = _configuration,
                ObjectClass            = objClass,
                OperationName          = operation,
                Uid     = uid,
                Options = options
            };

            try {
                _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain);

                if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain))
                {
                    DeleteMain(context);
                }

                _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain);
            } catch (Exception e) {
                LOG.Error(e, "Exception while executing Delete operation: {0}");
                throw;
            }
        }
        public void Create(CreateOpContext context)
        {
            ExchangeConnector exconn = (ExchangeConnector)context.Connector;

            Command cmdNew = ExchangeUtility.GetCommand(
                new PSExchangeConnector.CommandInfo(GetNewCommandName()),
                context.Attributes, exconn.Configuration);

            try {
                context.Uid = _helper.InvokePipelineAndGetGuid(exconn, cmdNew);
            } catch (ProxyAddressExistsException e) {
                // This is a tricky exception. Sometimes when creating an object that is already there (e.g. DistributionGroup),
                // PowerShell reports "ProxyAddressExists" instead of something like "ObjectExists" :(
                // So we have to distinguish these situations somehow...
                Name nameAttribute = ConnectorAttributeUtil.GetNameFromAttributes(context.Attributes);
                if (nameAttribute == null || nameAttribute.Value == null || nameAttribute.Value.Count() != 1)
                {
                    LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "ProxyAddressExistsException reported; but no single-valued NAME attribute present -- reporting as is");
                    throw new ConnectorException(e.Message, e);
                }
                String name = (String)nameAttribute.Value[0];
                LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "ProxyAddressExistsException reported; trying to see if object named " + name + " exists");
                Command cmdGet = ExchangeUtility.GetCommand(
                    new PSExchangeConnector.CommandInfo(GetGetCommandName()), exconn.Configuration);
                cmdGet.Parameters.Add("Identity", name);
                ICollection <PSObject> objects;
                try {
                    objects = _helper.InvokePipeline(exconn, cmdGet);
                } catch (ObjectNotFoundException e1) {
                    objects = null;
                }
                if (objects == null || objects.Count == 0)
                {
                    LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "...it does not -- reporting as is");
                    throw new ConnectorException(e.Message, e);
                }
                else
                {
                    LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "...it exists -- reporting as AlreadyExistsException");
                    throw new AlreadyExistsException(e.Message, e);
                }
            }

            if (ExecuteSetAfterNew())
            {
                Command cmdSet = ExchangeUtility.GetCommand(
                    new PSExchangeConnector.CommandInfo(GetSetCommandName()),
                    context.Attributes, context.Uid, exconn.Configuration);
                try {
                    _helper.InvokePipeline(exconn, cmdSet);
                } catch {
                    // TODO rollback
                    // rethrow original exception
                    throw;
                }
            }
        }
        /// <summary>
        /// Inits the connector with configuration injected
        /// </summary>
        /// <param name="configuration">Initialized Exchange configuration</param>
        public override void Init(Configuration configuration)
        {
            base.Init(configuration);
            this.configuration = (ExchangeConfiguration)configuration;

            // create runspace instance, will be alive as long as the connector instance is alive
            this.runspace = new RunSpaceInstance(RunSpaceInstance.SnapIn.Exchange, configuration.ConnectorMessages);

            // read the object class info definitions
            this.mapOcInfo = ExchangeUtility.GetOCInfo();
        }
        /// <summary>
        /// Implementation of SearchOp.ExecuteQuery
        /// </summary>
        /// <param name="oclass">Object class</param>
        /// <param name="query">Query to execute</param>
        /// <param name="handler">Results handler</param>
        /// <param name="options">Operation options</param>
        public override void ExecuteQuery(
            ObjectClass oclass, string query, ResultsHandler handler, OperationOptions options)
        {
            ExchangeUtility.NullCheck(oclass, "oclass", this.configuration);

            // we handle accounts only
            if (!oclass.Is(ObjectClass.ACCOUNT_NAME))
            {
                base.ExecuteQuery(oclass, query, handler, options);
                return;
            }

            ICollection <string> attsToGet = null;

            if (options != null && options.AttributesToGet != null)
            {
                attsToGet = CollectionUtil.NewList(options.AttributesToGet);
            }

            // delegate to get the exchange attributes if requested
            ResultsHandler filter = delegate(ConnectorObject cobject)
            {
                ConnectorObject filtered = ExchangeUtility.ReplaceAttributes(
                    cobject, attsToGet, AttMapFromAD);
                filtered = this.AddExchangeAttributes(oclass, filtered, attsToGet);
                return(handler(filtered));
            };

            ResultsHandler   handler2use = handler;
            OperationOptions options2use = options;

            if (options != null && options.AttributesToGet != null)
            {
                if (attsToGet.Contains(AttDatabase) || attsToGet.Contains(AttExternalMail) ||
                    attsToGet.Contains(AttRecipientType))
                {
                    // replace Exchange attributes with AD names
                    var newAttsToGet = ExchangeUtility.FilterReplace(attsToGet, AttMap2AD);

                    // we have to remove recipient type, as it is unknown to AD
                    newAttsToGet.Remove(AttRecipientType);

                    // build new op options
                    var      builder         = new OperationOptionsBuilder(options);
                    string[] attributesToGet = new string[newAttsToGet.Count];
                    newAttsToGet.CopyTo(attributesToGet, 0);
                    builder.AttributesToGet = attributesToGet;
                    options2use             = builder.Build();
                    handler2use             = filter;
                }
            }

            base.ExecuteQuery(oclass, query, handler2use, options2use);
        }
        public Uid Update(UpdateType updateType, ObjectClass oclass, Uid uid, ICollection <ConnectorAttribute> attributes, OperationOptions options)
        {
            const string operation = "Update";

            ExchangeUtility.NullCheck(updateType, "updateType", this._configuration);
            ExchangeUtility.NullCheck(oclass, "oclass", this._configuration);
            ExchangeUtility.NullCheck(uid, "uid", this._configuration);
            ExchangeUtility.NullCheck(attributes, "attributes", this._configuration);

            LOG.Info("Exchange.Update method; oclass = {0}, uid = {1}, type = {2}, attributes:\n{3}", oclass, uid, updateType, CommonUtils.DumpConnectorAttributes(attributes));

            if (attributes == null || attributes.Count == 0)
            {
                LOG.Info("Returning immediately, as there are no attributes to modify.");
                return(uid);
            }

            String database = (String)ExchangeUtility.GetAttValue("Database", attributes);

            LOG.Info("Database attribute before plugins call: " + database);
            plugins.OnBeforeUpdate(oclass, uid, attributes, options, _configuration);
            database = (String)ExchangeUtility.GetAttValue("Database", attributes);
            LOG.Info("Database attribute after plugins call: " + database);

            UpdateOpContext context = new UpdateOpContext()
            {
                UpdateType             = updateType,
                Attributes             = attributes,
                Connector              = this,
                ConnectorConfiguration = this._configuration,
                ObjectClass            = oclass,
                OperationName          = operation,
                Options = options,
                Uid     = uid
            };

            try {
                _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain);

                if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain))
                {
                    UpdateMain(context);
                }

                _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain);

                return(context.Uid);
            } catch (Exception e) {
                LOG.Error(e, "Exception while executing Update operation: {0}");
                throw;
            }
        }
        public void Delete(DeleteOpContext context)
        {
            ExchangeConnector exconn = (ExchangeConnector)context.Connector;

            Command cmdRemove = ExchangeUtility.GetCommand(
                new PSExchangeConnector.CommandInfo(GetRemoveCommandName()),
                context.Uid, exconn.Configuration);

            try {
                _helper.InvokePipeline(exconn, cmdRemove);
            } catch (ObjectNotFoundException e) {
                throw new UnknownUidException("Object with UID " + context.Uid.GetUidValue() + " couldn't be deleted", e);
            }
        }
        /// <summary>
        /// Implementation of SynOp.Sync
        /// </summary>
        /// <param name="objClass">Object class</param>
        /// <param name="token">Sync token</param>
        /// <param name="handler">Sync results handler</param>
        /// <param name="options">Operation options</param>
        public override void Sync(
            ObjectClass objClass, SyncToken token, SyncResultsHandler handler, OperationOptions options)
        {
            ExchangeUtility.NullCheck(objClass, "oclass", this.configuration);

            // we handle accounts only
            if (!objClass.Is(ObjectClass.ACCOUNT_NAME))
            {
                base.Sync(objClass, token, handler, options);
                return;
            }

            ICollection <string> attsToGet = null;

            if (options != null && options.AttributesToGet != null)
            {
                attsToGet = CollectionUtil.NewSet(options.AttributesToGet);
            }

            // delegate to get the exchange attributes if requested
            SyncResultsHandler xchangeHandler = delegate(SyncDelta delta)
            {
                if (delta.DeltaType == SyncDeltaType.DELETE)
                {
                    return(handler(delta));
                }

                // replace the ad attributes with exchange one and add recipient type
                ConnectorObject updated = ExchangeUtility.ReplaceAttributes(delta.Object, attsToGet, AttMapFromAD);
                updated = this.AddExchangeAttributes(objClass, updated, attsToGet);
                if (updated != delta.Object)
                {
                    // build new sync delta, cause we changed the object
                    SyncDeltaBuilder deltaBuilder = new SyncDeltaBuilder
                    {
                        DeltaType = delta.DeltaType,
                        Token     = delta.Token,
                        Uid       = delta.Uid,
                        Object    = updated
                    };
                    delta = deltaBuilder.Build();
                }

                return(handler(delta));
            };

            // call AD sync, use xchangeHandler
            base.Sync(objClass, token, xchangeHandler, options);
        }
        public void Update(UpdateOpContext context)
        {
            ExchangeConnector exconn = (ExchangeConnector)context.Connector;

            ICollection <ConnectorAttribute> attributesForReplace = _helper.DetermineNewAttributeValues(context, context.Uid.GetUidValue()); // query string is the UID value!

            Command cmdSet = ExchangeUtility.GetCommand(
                new PSExchangeConnector.CommandInfo(GetSetCommandName()),
                attributesForReplace, context.Uid, exconn.Configuration);

            try {
                _helper.InvokePipeline(exconn, cmdSet);
            } catch (ObjectNotFoundException e) {
                throw new UnknownUidException("Object with UID " + context.Uid.GetUidValue() + " couldn't be modified", e);
            }
        }
Exemplo n.º 14
0
        public void Sync(SyncOpContext context)
        {
            ExchangeConnector        exconn = (ExchangeConnector)context.Connector;
            ActiveDirectoryConnector adconn = exconn.ActiveDirectoryConnector;

            ICollection <string> attsToGet = null;

            if (context.Options != null && context.Options.AttributesToGet != null)
            {
                attsToGet = CollectionUtil.NewSet(context.Options.AttributesToGet);
            }

            // delegate to get the exchange attributes if requested
            SyncResultsHandler xchangeHandler = new SyncResultsHandler()
            {
                Handle = delta =>
                {
                    if (delta.DeltaType == SyncDeltaType.DELETE)
                    {
                        return(context.SyncResultsHandler.Handle(delta));
                    }

                    // replace the ad attributes with exchange ones and add recipient type and database (if requested)
                    ConnectorObject updated = ExchangeUtility.ConvertAdAttributesToExchange(delta.Object);
                    //updated = this.AddExchangeAttributes(exconn, context.ObjectClass, updated, attsToGet);
                    if (updated != delta.Object)
                    {
                        // build new sync delta, cause we changed the object
                        SyncDeltaBuilder deltaBuilder = new SyncDeltaBuilder
                        {
                            DeltaType = delta.DeltaType,
                            Token     = delta.Token,
                            Uid       = delta.Uid,
                            Object    = updated
                        };
                        delta = deltaBuilder.Build();
                    }

                    return(context.SyncResultsHandler.Handle(delta));
                }
            };

            // call AD sync, use xchangeHandler
            adconn.SyncInternal(context.ObjectClass,
                                context.SyncToken, xchangeHandler, context.Options,
                                GetAdAttributesToReturn(adconn, context.ObjectClass, context.Options));
        }
Exemplo n.º 15
0
        public Uid Update(UpdateType updateType, ObjectClass oclass, Uid uid, ICollection <ConnectorAttribute> attributes, OperationOptions options)
        {
            const string operation = "Update";

            ExchangeUtility.NullCheck(updateType, "updateType", this._configuration);
            ExchangeUtility.NullCheck(oclass, "oclass", this._configuration);
            ExchangeUtility.NullCheck(uid, "uid", this._configuration);
            ExchangeUtility.NullCheck(attributes, "attributes", this._configuration);

            LOGGER_API.TraceEvent(TraceEventType.Information, CAT_DEFAULT,
                                  "Exchange.Update method; oclass = {0}, uid = {1}, type = {2}, attributes:\n{3}", oclass, uid, updateType, CommonUtils.DumpConnectorAttributes(attributes));

            if (attributes == null || attributes.Count == 0)
            {
                LOGGER_API.TraceEvent(TraceEventType.Information, CAT_DEFAULT,
                                      "Returning immediately, as there are no attributes to modify.");
                return(uid);
            }

            UpdateOpContext context = new UpdateOpContext()
            {
                UpdateType             = updateType,
                Attributes             = attributes,
                Connector              = this,
                ConnectorConfiguration = this._configuration,
                ObjectClass            = oclass,
                OperationName          = operation,
                Options = options,
                Uid     = uid
            };

            try {
                _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain);

                if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain))
                {
                    UpdateMain(context);
                }

                _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain);

                return(context.Uid);
            } catch (Exception e) {
                LOGGER.TraceEvent(TraceEventType.Error, CAT_DEFAULT, "Exception while executing Update operation: {0}", e);
                throw;
            }
        }
        /// <summary>
        /// helper method to filter out all attributes used in ExchangeConnector only
        /// </summary>
        /// <param name="attributes">Connector attributes</param>
        /// <param name="cmdInfos">CommandInfo whose parameters will be used and filtered out from attributes</param>
        /// <returns>
        /// Filtered connector attributes
        /// </returns>
        private static ICollection <ConnectorAttribute> FilterOut(ICollection <ConnectorAttribute> attributes, params PSExchangeConnector.CommandInfo[] cmdInfos)
        {
            IList <string> attsToRemove = new List <string> {
                AttRecipientType, AttDatabase, AttExternalMail
            };

            if (cmdInfos != null)
            {
                foreach (PSExchangeConnector.CommandInfo cmdInfo in cmdInfos)
                {
                    if (cmdInfo != null)
                    {
                        CollectionUtil.AddAll(attsToRemove, cmdInfo.Parameters);
                    }
                }
            }

            return(ExchangeUtility.FilterOut(attributes, attsToRemove));
        }
Exemplo n.º 17
0
        /// <summary>
        /// helper method to filter out all attributes used in ExchangeConnector only
        /// </summary>
        /// <param name="attributes">Connector attributes</param>
        /// <param name="cmdInfos">CommandInfo whose parameters will be used and filtered out from attributes</param>
        /// <returns>
        /// Filtered connector attributes
        /// </returns>
        internal static ICollection <ConnectorAttribute> FilterOut(ICollection <ConnectorAttribute> attributes, params PSExchangeConnector.CommandInfo[] cmdInfos)
        {
            IList <string> attsToRemove = new List <string> {
                ExchangeConnectorAttributes.AttRecipientType
            };

            CollectionUtil.AddAll(attsToRemove, ExchangeConnectorAttributes.AttMap2AD.Keys);
            if (cmdInfos != null)
            {
                foreach (PSExchangeConnector.CommandInfo cmdInfo in cmdInfos)
                {
                    if (cmdInfo != null)
                    {
                        CollectionUtil.AddAll(attsToRemove, cmdInfo.Parameters);
                    }
                }
            }
            return(ExchangeUtility.FilterOut(attributes, attsToRemove));
        }
        /// <summary>
        /// Implementation of CreateOp.Create
        /// </summary>
        /// <param name="oclass">Object class</param>
        /// <param name="attributes">Object attributes</param>
        /// <param name="options">Operation options</param>
        /// <returns>Uid of the created object</returns>
        public Uid Create(ObjectClass oclass, ICollection <ConnectorAttribute> attributes, OperationOptions options)
        {
            const string operation = "Create";

            ExchangeUtility.NullCheck(oclass, "oclass", this._configuration);
            ExchangeUtility.NullCheck(attributes, "attributes", this._configuration);

            LOG.Info("Exchange.Create method for {0}; attributes:\n{1}", oclass.GetObjectClassValue(), CommonUtils.DumpConnectorAttributes(attributes));

            String database = (String)ExchangeUtility.GetAttValue("Database", attributes);

            LOG.Info("Database attribute before plugins call: " + database);
            plugins.OnBeforeCreate(oclass, attributes, options, _configuration);
            database = (String)ExchangeUtility.GetAttValue("Database", attributes);
            LOG.Info("Database attribute after plugins call: " + database);

            CreateOpContext context = new CreateOpContext()
            {
                Attributes             = attributes,
                Connector              = this,
                ConnectorConfiguration = this._configuration,
                ObjectClass            = oclass,
                OperationName          = operation,
                Options = options
            };

            try {
                _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain);

                if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain))
                {
                    CreateMain(context);
                }

                _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain);

                return(context.Uid);
            } catch (Exception e) {
                LOG.Error(e, "Exception while executing Create operation: {0}");
                throw;
            }
        }
Exemplo n.º 19
0
        public static string GetRecipientType(ConnectorObject cobject)
        {
            long?recipientTypeDetails =
                ExchangeUtility.GetAttValue(ExchangeConnectorAttributes.AttMsExchRecipientTypeDetailsADName, cobject.GetAttributes()) as long?;

            switch (recipientTypeDetails)   // see http://blogs.technet.com/b/benw/archive/2007/04/05/exchange-2007-and-recipient-type-details.aspx

            {
            case 1: return(ExchangeConnectorAttributes.RcptTypeMailBox);

            case 128: return(ExchangeConnectorAttributes.RcptTypeMailUser);

            case null:              // we are dealing with user accounts, so we can assume that an account without Exchange information is an ordinary User
            case 65536: return(ExchangeConnectorAttributes.RcptTypeUser);

            default:
                LOG.Warn("Unknown recipientTypeDetails: {0} ({1})", recipientTypeDetails,
                         ExchangeUtility.GetAttValue(ExchangeConnectorAttributes.AttMsExchRecipientTypeDetailsADName, cobject.GetAttributes()));
                return(null);
            }
        }
        /// <summary>
        /// Implementation of CreateOp.Create
        /// </summary>
        /// <param name="oclass">Object class</param>(oc
        /// <param name="attributes">Object attributes</param>
        /// <param name="options">Operation options</param>
        /// <returns><see cref="Uid"/> of the created object</returns>
        public override Uid Create(
            ObjectClass oclass,
            ICollection <ConnectorAttribute> attributes,
            OperationOptions options)
        {
            const string METHOD = "Create";

            Debug.WriteLine(METHOD + ":entry", ClassName);

            // first create the object in AD
            Uid uid = base.Create(oclass, attributes, options);

            try
            {
                if (oclass.Is(MailboxName))
                {
                    // enable mailbox for person
                    Command cmd = ExchangeUtility.GetCommand(CommandInfo.EnableMailbox, attributes, this.configuration);
                    this.runspace.InvokePipeline(cmd);
                }
                else if (oclass.Is(MailUserName))
                {
                    // enable mailuser
                    Command cmd = ExchangeUtility.GetCommand(CommandInfo.EnableMailUser, attributes, this.configuration);
                    this.runspace.InvokePipeline(cmd);
                }

                Debug.WriteLine(METHOD + ":exit", ClassName);
            }
            catch
            {
                // do the rollback - delete the object by uid
                // no need to check the uid is null, ensured by the create contract
                this.Delete(oclass, uid, options);
                throw;
            }

            return(uid);
        }
        /// <summary>
        /// Gets the Exchange user using powershell Get-User command
        /// </summary>
        /// <param name="cmdInfo">command info to get the user</param>
        /// <param name="attributes">attributes containing the Name</param>
        /// <returns><see cref="PSObject"/> with user info</returns>
        private PSObject GetUser(PSExchangeConnector.CommandInfo cmdInfo, ICollection <ConnectorAttribute> attributes)
        {
            // assert we have user name
            string name = ExchangeUtility.GetAttValue(Name.NAME, attributes) as string;

            ExchangeUtility.NullCheck(name, "User name", this.configuration);

            Command cmdUser = ExchangeUtility.GetCommand(cmdInfo, attributes, this.configuration);
            ICollection <PSObject> users = this.InvokePipeline(cmdUser);

            if (users.Count == 1)
            {
                foreach (PSObject obj in users)
                {
                    return(obj);
                }
            }

            throw new ArgumentException(
                      this.configuration.ConnectorMessages.Format(
                          "ex_bad_username", "Provided User name is not unique or not existing"));
        }
Exemplo n.º 22
0
        /// <summary>
        /// Implementation of SearchOp.ExecuteQuery
        /// </summary>
        /// <param name="oclass">Object class</param>
        /// <param name="query">Query to execute</param>
        /// <param name="handler">Results handler</param>
        /// <param name="options">Operation options</param>
        public void ExecuteQuery(ObjectClass oclass, string query, ResultsHandler handler, OperationOptions options)
        {
            const string operation = "ExecuteQuery";

            ExchangeUtility.NullCheck(oclass, "oclass", this._configuration);
            if (options == null)
            {
                options = new OperationOptions(new Dictionary <string, object>());
            }

            LOGGER_API.TraceEvent(TraceEventType.Information, CAT_DEFAULT,
                                  "Exchange.ExecuteQuery method; oclass = {0}, query = {1}", oclass, query);

            ExecuteQueryContext context = new ExecuteQueryContext()
            {
                Connector = this,
                ConnectorConfiguration = _configuration,
                ObjectClass            = oclass,
                OperationName          = operation,
                Options        = options,
                Query          = query,
                ResultsHandler = handler
            };

            try {
                _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain);
                if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain))
                {
                    ExecuteQueryMain(context);
                }
                _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain);
            } catch (Exception e) {
                LOGGER.TraceEvent(TraceEventType.Error, CAT_DEFAULT, "Exception while executing ExecuteQuery operation: {0}", e);
                throw;
            }

            // TODO what about executing a script on each returned item?
        }
Exemplo n.º 23
0
        /// <summary>
        /// Implementation of CreateOp.Create
        /// </summary>
        /// <param name="oclass">Object class</param>
        /// <param name="attributes">Object attributes</param>
        /// <param name="options">Operation options</param>
        /// <returns>Uid of the created object</returns>
        public Uid Create(ObjectClass oclass, ICollection <ConnectorAttribute> attributes, OperationOptions options)
        {
            const string operation = "Create";

            ExchangeUtility.NullCheck(oclass, "oclass", this._configuration);
            ExchangeUtility.NullCheck(attributes, "attributes", this._configuration);

            LOGGER_API.TraceEvent(TraceEventType.Information, CAT_DEFAULT,
                                  "Exchange.Create method for {0}; attributes:\n{1}", oclass.GetObjectClassValue(), CommonUtils.DumpConnectorAttributes(attributes));

            CreateOpContext context = new CreateOpContext()
            {
                Attributes             = attributes,
                Connector              = this,
                ConnectorConfiguration = this._configuration,
                ObjectClass            = oclass,
                OperationName          = operation,
                Options = options
            };

            try {
                _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain);

                if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain))
                {
                    CreateMain(context);
                }

                _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain);

                return(context.Uid);
            } catch (Exception e) {
                LOGGER.TraceEvent(TraceEventType.Error, CAT_DEFAULT, "Exception while executing Create operation: {0}", e);
                throw;
            }
        }
        /// <summary>
        /// Gets Recipient Type/Database from Exchange database, this method can be more general, but it is ok
        /// for out needs
        /// </summary>
        /// <param name="oc">object class, currently the moethod works for <see cref="ObjectClass.ACCOUNT"/> only</param>
        /// <param name="cobject">connector object to get the recipient type/database for</param>
        /// <param name="attToGet">attributes to get</param>
        /// <returns>Connector Object with recipient type added</returns>
        /// <exception cref="ConnectorException">In case of some troubles in powershell (if the
        /// user is not found we get this exception too)</exception>
        private ConnectorObject AddExchangeAttributes(ObjectClass oc, ConnectorObject cobject, IEnumerable <string> attToGet)
        {
            ExchangeUtility.NullCheck(oc, "name", this.configuration);
            ExchangeUtility.NullCheck(oc, "cobject", this.configuration);

            // we support ACCOUNT only or there is nothing to add
            if (!oc.Is(ObjectClass.ACCOUNT_NAME) || attToGet == null)
            {
                return(cobject);
            }

            // check it is not deleted object
            bool?deleted = ExchangeUtility.GetAttValue(AttIsDeleted, cobject.GetAttributes()) as bool?;

            if (deleted != null && deleted == true)
            {
                // do nothing, it is deleted object
                return(cobject);
            }

            ICollection <string> lattToGet = CollectionUtil.NewCaseInsensitiveSet();

            CollectionUtil.AddAll(lattToGet, attToGet);
            foreach (string att in attToGet)
            {
                if (cobject.GetAttributeByName(att) != null && att != AttDatabase)
                {
                    lattToGet.Remove(att);
                }
            }

            if (lattToGet.Count == 0)
            {
                return(cobject);
            }

            ConnectorObjectBuilder cobjBuilder = new ConnectorObjectBuilder();

            cobjBuilder.AddAttributes(cobject.GetAttributes());

            PSExchangeConnector.CommandInfo cmdInfo = PSExchangeConnector.CommandInfo.GetUser;

            // prepare the connector attribute list to get the command
            ICollection <ConnectorAttribute> attributes = new Collection <ConnectorAttribute> {
                cobject.Name
            };

            // get the command
            Command cmd = ExchangeUtility.GetCommand(cmdInfo, attributes, this.configuration);
            ICollection <PSObject> foundObjects = this.InvokePipeline(cmd);
            PSObject user = null;

            if (foundObjects != null && foundObjects.Count == 1)
            {
                user = GetFirstElement(foundObjects);
                foreach (var info in user.Properties)
                {
                    ConnectorAttribute att = GetAsAttribute(info);
                    if (att != null && lattToGet.Contains(att.Name))
                    {
                        cobjBuilder.AddAttribute(att);
                        lattToGet.Remove(att.Name);
                    }
                }

                if (lattToGet.Count == 0)
                {
                    return(cobjBuilder.Build());
                }
            }

            if (user == null)
            {
                // nothing to do
                return(cobject);
            }

            string rcptType = user.Members[AttRecipientType].Value.ToString();

            foundObjects = null;

            // get detailed information
            if (rcptType == RcptTypeMailBox)
            {
                foundObjects = this.InvokePipeline(ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.GetMailbox, attributes, this.configuration));
            }
            else if (rcptType == RcptTypeMailUser)
            {
                foundObjects = this.InvokePipeline(ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.GetMailUser, attributes, this.configuration));
            }

            if (foundObjects != null && foundObjects.Count == 1)
            {
                PSObject userDetails = GetFirstElement(foundObjects);
                foreach (var info in userDetails.Properties)
                {
                    ConnectorAttribute att = GetAsAttribute(info);
                    if (att != null && lattToGet.Contains(att.Name))
                    {
                        cobjBuilder.AddAttribute(att);
                        lattToGet.Remove(att.Name);
                    }
                }
            }

            return(cobjBuilder.Build());
        }
Exemplo n.º 25
0
        public void Update(UpdateOpContext context)
        {
            ExchangeConnector        exconn = (ExchangeConnector)context.Connector;
            ActiveDirectoryConnector adconn = exconn.ActiveDirectoryConnector;

            // update in AD first
            var filtered = ExchangeUtility.FilterOut(
                context.Attributes,
                PSExchangeConnector.CommandInfo.EnableMailbox,
                PSExchangeConnector.CommandInfo.EnableMailUser,
                PSExchangeConnector.CommandInfo.SetMailbox,
                PSExchangeConnector.CommandInfo.SetMailUser);

            adconn.Update(context.UpdateType, context.ObjectClass, context.Uid, filtered, context.Options);

            // retrieve Exchange-related information about the user
            string          query         = "(objectGUID=" + ActiveDirectoryUtils.ConvertUIDToSearchString(context.Uid) + ")";
            ConnectorObject currentObject = _helper.GetCurrentObject(context, query);
            ICollection <ConnectorAttribute> attributesForReplace = _helper.DetermineNewAttributeValues(context, currentObject);

            attributesForReplace = DeduplicateEmailAddresses(context, attributesForReplace);

            string origRcptType;
            var    newRcptType = _helper.DetermineOrigAndNewAttributeValue(context, currentObject, attributesForReplace, ExchangeConnectorAttributes.AttRecipientType, out origRcptType);

            if (newRcptType == null)
            {
                newRcptType = ExchangeConnectorAttributes.RcptTypeUser;
            }

            string origDatabase;
            var    newDatabase = _helper.DetermineOrigAndNewAttributeValue(context, currentObject, attributesForReplace, ExchangeConnectorAttributes.AttDatabase, out origDatabase);

            // PART 1 - DEALING WITH MailUser CASE

            if (ExchangeConnectorAttributes.RcptTypeMailUser.Equals(newRcptType))
            {
                // disabling Mailbox if needed
                if (ExchangeConnectorAttributes.RcptTypeMailBox.Equals(origRcptType))
                {
                    Command cmdDisable = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.DisableMailbox, attributesForReplace, context.Uid, exconn.Configuration);
                    cmdDisable.Parameters.Add("Confirm", false);
                    _helper.InvokePipeline(exconn, cmdDisable);
                }

                // enabling MailUser if needed
                if (!ExchangeConnectorAttributes.RcptTypeMailUser.Equals(origRcptType))
                {
                    // Enable-MailUser needs the value of ExternalEmailAddress, so we have to get it
                    string origExternalEmailAddress;
                    var    newExternalEmailAddress = _helper.DetermineOrigAndNewAttributeValue(context, currentObject, attributesForReplace, ExchangeConnectorAttributes.AttExternalEmailAddress, out origExternalEmailAddress);

                    if (String.IsNullOrEmpty(newExternalEmailAddress))
                    {
                        throw new InvalidOperationException("Missing ExternalEmailAddress value, which is required for a MailUser");
                    }
                    ExchangeUtility.SetAttValue(ExchangeConnectorAttributes.AttExternalEmailAddress, newExternalEmailAddress, attributesForReplace);

                    // now execute the Enable-MailUser command
                    Command cmdEnable = ExchangeUtility.GetCommand(
                        PSExchangeConnector.CommandInfo.EnableMailUser, attributesForReplace, context.Uid, exconn.Configuration);
                    _helper.InvokePipeline(exconn, cmdEnable);
                }

                // setting MailUser attributes
                Command cmdSet = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.SetMailUser, attributesForReplace, context.Uid, exconn.Configuration);
                _helper.InvokePipeline(exconn, cmdSet);
            }

            // PART 2 - DEALING WITH UserMailbox CASE

            else if (ExchangeConnectorAttributes.RcptTypeMailBox.Equals(newRcptType))
            {
                // enable mailbox if necessary

                // we should execute something like this here:
                // get-user -identity id|?{$_.RecipientType -eq "User"}|enable-mailbox -database "db"
                // unfortunately I was not able to get it working with the pipeline... that's why there are two commands
                // executed :-(
                // alternatively there can be something like:
                // get-user -identity id -RecipientTypeDetails User|enable-mailbox -database "db", but we have then trouble
                // with detecting attempt to change the database attribute
                if (!ExchangeConnectorAttributes.RcptTypeMailBox.Equals(origRcptType))
                {
                    Command cmdEnable = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.EnableMailbox, attributesForReplace, context.Uid, exconn.Configuration);
                    _helper.InvokePipeline(exconn, cmdEnable);
                }
                else
                {
                    // are we trying to update the database?
                    if (newDatabase != null && origDatabase != null && !newDatabase.Equals(origDatabase))
                    {
                        throw new ArgumentException(
                                  context.ConnectorConfiguration.ConnectorMessages.Format(
                                      "ex_not_updatable", "Update of [{0}] attribute is not supported", ExchangeConnectorAttributes.AttDatabase));
                    }
                }

                Command cmdSet = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.SetMailbox, attributesForReplace, context.Uid, exconn.Configuration);
                _helper.InvokePipeline(exconn, cmdSet);
            }

            // PART 3 - DEALING WITH User CASE

            else if (ExchangeConnectorAttributes.RcptTypeUser.Equals(newRcptType))
            {
                if (ExchangeConnectorAttributes.RcptTypeMailBox.Equals(origRcptType))
                {
                    Command cmdDisable = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.DisableMailbox, attributesForReplace, context.Uid, exconn.Configuration);
                    cmdDisable.Parameters.Add("Confirm", false);
                    _helper.InvokePipeline(exconn, cmdDisable);
                }
                else if (ExchangeConnectorAttributes.RcptTypeMailUser.Equals(origRcptType))
                {
                    Command cmdDisable = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.DisableMailUser, attributesForReplace, context.Uid, exconn.Configuration);
                    cmdDisable.Parameters.Add("Confirm", false);
                    _helper.InvokePipeline(exconn, cmdDisable);
                }
                else if (ExchangeConnectorAttributes.RcptTypeUser.Equals(origRcptType))
                {
                    // if orig is User, there is no need to disable anything
                }
                else
                {
                    throw new InvalidOperationException("Invalid original recipient type: " + origRcptType);
                }

                Command cmdSet = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.SetUser, attributesForReplace, context.Uid, exconn.Configuration);
                _helper.InvokePipeline(exconn, cmdSet);
            }
            else
            {
                // unsupported rcpt type
                throw new ArgumentException(
                          context.ConnectorConfiguration.ConnectorMessages.Format(
                              "ex_bad_rcpt", "Recipient type [{0}] is not supported", newRcptType));
            }
        }
Exemplo n.º 26
0
        public void Create(CreateOpContext context)
        {
            context.Attributes = DeduplicateEmailAddresses(context, context.Attributes);

            // get recipient type
            string rcptType = ExchangeUtility.GetAttValue(ExchangeConnectorAttributes.AttRecipientType, context.Attributes) as string;

            if (rcptType == null || rcptType.Equals(""))
            {
                rcptType = ExchangeConnectorAttributes.RcptTypeUser;
            }

            ExchangeConnector        exconn = (ExchangeConnector)context.Connector;
            ActiveDirectoryConnector adconn = exconn.ActiveDirectoryConnector;

            PSExchangeConnector.CommandInfo cmdInfoEnable = null;
            PSExchangeConnector.CommandInfo cmdInfoSet    = null;
            switch (rcptType)
            {
            case ExchangeConnectorAttributes.RcptTypeMailBox:
                cmdInfoEnable = PSExchangeConnector.CommandInfo.EnableMailbox;
                cmdInfoSet    = PSExchangeConnector.CommandInfo.SetMailbox;
                break;

            case ExchangeConnectorAttributes.RcptTypeMailUser:
                cmdInfoEnable = PSExchangeConnector.CommandInfo.EnableMailUser;
                cmdInfoSet    = PSExchangeConnector.CommandInfo.SetMailUser;
                break;

            case ExchangeConnectorAttributes.RcptTypeUser:
                break;

            default:
                throw new ArgumentException(
                          context.ConnectorConfiguration.ConnectorMessages.Format(
                              "ex_bad_rcpt", "Recipient type [{0}] is not supported", rcptType));
            }

            // first create the object in AD
            ICollection <ConnectorAttribute> adAttributes = ExchangeUtility.FilterOut(context.Attributes,
                                                                                      PSExchangeConnector.CommandInfo.EnableMailbox,
                                                                                      PSExchangeConnector.CommandInfo.SetMailbox,
                                                                                      PSExchangeConnector.CommandInfo.EnableMailUser,
                                                                                      PSExchangeConnector.CommandInfo.SetMailUser);
            Uid uid = adconn.Create(context.ObjectClass, adAttributes, context.Options);

            if (rcptType == ExchangeConnectorAttributes.RcptTypeUser)
            {
                // AD account only, we do nothing
                context.Uid = uid;
                return;
            }

            // add a empty "EmailAddresses" attribute if needed (address policy is disabled and no addresses are provided)
            ICollection <ConnectorAttribute> enhancedAttributes;
            ConnectorAttribute policyEnabledAttribute = ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttEmailAddressPolicyEnabled, context.Attributes);

            if (policyEnabledAttribute != null &&
                ConnectorAttributeUtil.GetBooleanValue(policyEnabledAttribute).HasValue&&
                ConnectorAttributeUtil.GetBooleanValue(policyEnabledAttribute).Value == false &&
                ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttPrimarySmtpAddress, context.Attributes) == null &&
                ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttEmailAddresses, context.Attributes) == null)
            {
                enhancedAttributes = new HashSet <ConnectorAttribute>(context.Attributes);
                enhancedAttributes.Add(ConnectorAttributeBuilder.Build(ExchangeConnectorAttributes.AttEmailAddresses));
                LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Added empty EmailAddresses attribute because address policy use is disabled and no addresses were provided");
            }
            else
            {
                enhancedAttributes = context.Attributes;        // no change
            }

            // prepare the command
            Command cmdEnable = ExchangeUtility.GetCommand(cmdInfoEnable, enhancedAttributes, uid, (ExchangeConfiguration)context.ConnectorConfiguration);
            Command cmdSet    = ExchangeUtility.GetCommand(cmdInfoSet, enhancedAttributes, uid, (ExchangeConfiguration)context.ConnectorConfiguration);

            try {
                _helper.InvokePipeline(exconn, cmdEnable);
                _helper.InvokePipeline(exconn, cmdSet);
            }
            catch {
                LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Rolling back AD create for UID: " + uid.GetUidValue());

                // rollback AD create
                try {
                    adconn.Delete(context.ObjectClass, uid, context.Options);
                } catch {
                    LOGGER.TraceEvent(TraceEventType.Warning, CAT_DEFAULT, "Not able to rollback AD create for UID: " + uid.GetUidValue());
                    // note: this is not perfect, we hide the original exception
                    throw;
                }

                // rethrow original exception
                throw;
            }

            context.Uid = uid;
        }
Exemplo n.º 27
0
        public void ExecuteQuery(ExecuteQueryContext context)
        {
            ExchangeConnector        exconn = (ExchangeConnector)context.Connector;
            ActiveDirectoryConnector adconn = exconn.ActiveDirectoryConnector;

            ICollection <string> attsToGet = null;

            if (context.Options != null && context.Options.AttributesToGet != null)
            {
                attsToGet = CollectionUtil.NewList(context.Options.AttributesToGet);
            }

            // delegate to get the exchange attributes if requested
            ResultsHandler filter = new SearchResultsHandler()
            {
                Handle = cobject =>
                {
                    LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Object returned from AD connector: {0}", CommonUtils.DumpConnectorAttributes(cobject.GetAttributes()));
                    ConnectorObject filtered = ExchangeUtility.ConvertAdAttributesToExchange(cobject);
                    //filtered = AddExchangeAttributes(exconn, context.ObjectClass, filtered, attsToGet);
                    LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Object as passed from Exchange connector: {0}", CommonUtils.DumpConnectorAttributes(filtered.GetAttributes()));
                    return(context.ResultsHandler.Handle(filtered));
                },

                HandleResult = result =>
                {
                    if (context.ResultsHandler is SearchResultsHandler)
                    {
                        ((SearchResultsHandler)context.ResultsHandler).HandleResult(result);
                    }
                }
            };

            ResultsHandler   handler2use = filter;
            OperationOptions options2use = context.Options;

            // mapping AttributesToGet from Exchange to AD "language"
            // actually, we don't need this code any more, because there are no attribute that are not retrieved by default
            // Uncomment this code if necessary in the future.
            if (context.Options != null && context.Options.AttributesToGet != null)
            {
                /*
                 * ISet<string> mappedExchangeAttributesToGet = new HashSet<string>(AttMap2AD.Keys);
                 * mappedExchangeAttributesToGet.IntersectWith(options.AttributesToGet);
                 * if (mappedExchangeAttributesToGet.Count > 0 || attsToGet.Contains(AttRecipientType))
                 * {
                 *  // replace Exchange attributes with AD names
                 *  var newAttsToGet = ExchangeUtility.FilterReplace(attsToGet, AttMap2AD);
                 *
                 *  // we have to remove recipient type, as it is unknown to AD
                 *  newAttsToGet.Remove(AttRecipientType);
                 *
                 *  // build new op options
                 *  var builder = new OperationOptionsBuilder(options);
                 *  string[] attributesToGet = new string[newAttsToGet.Count];
                 *  newAttsToGet.CopyTo(attributesToGet, 0);
                 *  builder.AttributesToGet = attributesToGet;
                 *  options2use = builder.Build();
                 * } */

                /*
                 * if (attsToGet.Contains(ExchangeConnectorAttributes.AttDatabase))
                 * {
                 *  attsToGet.Remove(ExchangeConnectorAttributes.AttDatabase);
                 *
                 *  // build new op options
                 *  var builder = new OperationOptionsBuilder(context.Options);
                 *  string[] attributesToGet = new string[attsToGet.Count];
                 *  attsToGet.CopyTo(attributesToGet, 0);
                 *  builder.AttributesToGet = attributesToGet;
                 *  options2use = builder.Build();
                 * }
                 */
            }

            adconn.ExecuteQueryInternal(context.ObjectClass,
                                        context.Query, handler2use, options2use,
                                        GetAdAttributesToReturn(adconn, context.ObjectClass, context.Options));
        }
        /// <summary>
        /// Implementation of UpdateOp.Update
        /// </summary>
        /// <param name="type">Update type</param>
        /// <param name="oclass">Object class</param>
        /// <param name="attributes">Object attributes</param>
        /// <param name="options">Operation options</param>
        /// <returns>Uid of the updated object</returns>
        public override Uid Update(
            UpdateType type,
            ObjectClass oclass,
            ICollection <ConnectorAttribute> attributes,
            OperationOptions options)
        {
            const string METHOD = "Update";

            Debug.WriteLine(METHOD + ":entry", ClassName);

            ExchangeUtility.NullCheck(type, "updatetype", this.configuration);
            ExchangeUtility.NullCheck(oclass, "oclass", this.configuration);
            ExchangeUtility.NullCheck(attributes, "attributes", this.configuration);

            // we handle accounts only
            if (!oclass.Is(ObjectClass.ACCOUNT_NAME))
            {
                return(base.Update(type, oclass, attributes, options));
            }

            // get recipient type and database
            string rcptType = ExchangeUtility.GetAttValue(AttRecipientType, attributes) as string;
            string database = ExchangeUtility.GetAttValue(AttDatabase, attributes) as string;

            // update in AD first
            var filtered = FilterOut(
                attributes,
                PSExchangeConnector.CommandInfo.EnableMailbox,
                PSExchangeConnector.CommandInfo.EnableMailUser,
                PSExchangeConnector.CommandInfo.SetMailbox,
                PSExchangeConnector.CommandInfo.SetMailUser);
            Uid uid = base.Update(type, oclass, filtered, options);

            ConnectorObject aduser = this.ADSearchByUid(uid, oclass, ExchangeUtility.AddAttributeToOptions(options, AttDatabaseADName));

            attributes.Add(aduser.Name);
            PSExchangeConnector.CommandInfo cmdInfo = PSExchangeConnector.CommandInfo.GetUser;
            if (aduser.GetAttributeByName(AttDatabaseADName) != null)
            {
                // we can be sure it is user mailbox type
                cmdInfo = PSExchangeConnector.CommandInfo.GetMailbox;
            }

            PSObject psuser       = this.GetUser(cmdInfo, attributes);
            string   origRcptType = psuser.Members[AttRecipientType].Value.ToString();

            if (String.IsNullOrEmpty(rcptType))
            {
                rcptType = origRcptType;
            }

            if (rcptType == RcptTypeMailUser)
            {
                if (type == UpdateType.REPLACE)
                {
                    if (origRcptType != rcptType)
                    {
                        Command cmdEnable = ExchangeUtility.GetCommand(
                            PSExchangeConnector.CommandInfo.EnableMailUser, attributes, this.configuration);
                        this.InvokePipeline(cmdEnable);
                    }

                    Command cmdSet = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.SetMailUser, attributes, this.configuration);
                    this.InvokePipeline(cmdSet);
                }
                else
                {
                    throw new ConnectorException(this.configuration.ConnectorMessages.Format(
                                                     "ex_wrong_update_type", "Update type [{0}] not supported", type));
                }
            }
            else if (rcptType == RcptTypeMailBox)
            {
                // we should execute something like this here:
                // get-user -identity id|?{$_.RecipientType -eq "User"}|enable-mailbox -database "db"
                // unfortunately I was not able to get it working with the pipeline... that's why there are two commands
                // executed :-(
                // alternatively there can be something like:
                // get-user -identity id -RecipientTypeDetails User|enable-mailbox -database "db", but we have then trouble
                // with detecting attempt to change the database attribute
                string origDatabase = psuser.Members[AttDatabase] != null ? psuser.Members[AttDatabase].Value.ToString() : null;
                if (origRcptType != rcptType)
                {
                    Command cmdEnable = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.EnableMailbox, attributes, this.configuration);
                    this.InvokePipeline(cmdEnable);
                }
                else
                {
                    // trying to update the database?
                    if (database != null && database != origDatabase)
                    {
                        throw new ArgumentException(
                                  this.configuration.ConnectorMessages.Format(
                                      "ex_not_updatable", "Update of [{0}] attribute is not supported", AttDatabase));
                    }
                }

                Command cmdSet = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.SetMailbox, attributes, this.configuration);
                this.InvokePipeline(cmdSet);
            }
            else if (rcptType == RcptTypeUser && origRcptType != rcptType)
            {
                throw new ArgumentException(
                          this.configuration.ConnectorMessages.Format(
                              "ex_update_notsupported", "Update of [{0}] to [{1}] is not supported", AttRecipientType, rcptType));
            }
            else if (rcptType != RcptTypeUser)
            {
                // unsupported rcpt type
                throw new ArgumentException(
                          this.configuration.ConnectorMessages.Format(
                              "ex_bad_rcpt", "Recipient type [{0}] is not supported", rcptType));
            }

            Debug.WriteLine(METHOD + ":exit", ClassName);
            return(uid);
        }
        /// <summary>
        /// Implementation of CreateOp.Create
        /// </summary>
        /// <param name="oclass">Object class</param>(oc
        /// <param name="attributes">Object attributes</param>
        /// <param name="options">Operation options</param>
        /// <returns>Uid of the created object</returns>
        public override Uid Create(
            ObjectClass oclass, ICollection <ConnectorAttribute> attributes, OperationOptions options)
        {
            ExchangeUtility.NullCheck(oclass, "oclass", this.configuration);
            ExchangeUtility.NullCheck(attributes, "attributes", this.configuration);

            // we handle accounts only
            if (!oclass.Is(ObjectClass.ACCOUNT_NAME))
            {
                return(base.Create(oclass, attributes, options));
            }

            const string METHOD = "Create";

            Debug.WriteLine(METHOD + ":entry", ClassName);

            // get recipient type
            string rcptType = ExchangeUtility.GetAttValue(AttRecipientType, attributes) as string;

            PSExchangeConnector.CommandInfo cmdInfoEnable = null;
            PSExchangeConnector.CommandInfo cmdInfoSet    = null;
            switch (rcptType)
            {
            case RcptTypeMailBox:
                cmdInfoEnable = PSExchangeConnector.CommandInfo.EnableMailbox;
                cmdInfoSet    = PSExchangeConnector.CommandInfo.SetMailbox;
                break;

            case RcptTypeMailUser:
                cmdInfoEnable = PSExchangeConnector.CommandInfo.EnableMailUser;
                cmdInfoSet    = PSExchangeConnector.CommandInfo.SetMailUser;
                break;

            case RcptTypeUser:
                break;

            default:
                throw new ArgumentException(
                          this.configuration.ConnectorMessages.Format(
                              "ex_bad_rcpt", "Recipient type [{0}] is not supported", rcptType));
            }

            // first create the object in AD
            Uid uid = base.Create(oclass, FilterOut(attributes, cmdInfoEnable, cmdInfoSet), options);

            if (rcptType == RcptTypeUser)
            {
                // AD account only, we do nothing
                return(uid);
            }

            // prepare the command
            Command cmdEnable = ExchangeUtility.GetCommand(cmdInfoEnable, attributes, this.configuration);
            Command cmdSet    = ExchangeUtility.GetCommand(cmdInfoSet, attributes, this.configuration);

            try
            {
                this.InvokePipeline(cmdEnable);
                this.InvokePipeline(cmdSet);
            }
            catch
            {
                Trace.TraceWarning("Rolling back AD create for UID: " + uid.GetUidValue());

                // rollback AD create
                try
                {
                    Delete(oclass, uid, options);
                }
                catch
                {
                    Trace.TraceWarning("Not able to rollback AD create for UID: " + uid.GetUidValue());

                    // note: this is not perfect, we hide the original exception
                    throw;
                }

                // rethrow original exception
                throw;
            }

            Debug.WriteLine(METHOD + ":exit", ClassName);
            return(uid);
        }