PageRenderTime 267ms CodeModel.GetById 226ms app.highlight 34ms RepoModel.GetById 1ms app.codeStats 1ms

/Source/FIMPSClient.cs

#
C# | 341 lines | 234 code | 39 blank | 68 comment | 11 complexity | fdeb18c361c36223b3494bf38a0ee7d6 MD5 | raw file
  1using System;
  2using System.Collections.Generic;
  3using System.Linq;
  4using System.Text;
  5
  6using System.ServiceModel;
  7using System.Security.Principal;
  8using System.Xml.Schema;
  9using Microsoft.ResourceManagement.Client;
 10using Microsoft.ResourceManagement.ObjectModel;
 11using Microsoft.ResourceManagement.ObjectModel.ResourceTypes;
 12using Microsoft.ResourceManagement.Client.WsTransfer;
 13using Microsoft.ResourceManagement.Client.WsEnumeration;
 14using System.ServiceModel.Channels;
 15using System.Net;
 16using System.Management.Automation;
 17using System.Management.Automation.Host;
 18using System.Globalization;
 19
 20namespace Quest.FIMPowerShellSnapin
 21{
 22    public class FIMPSClient
 23    {
 24        private const String _defaultResourceManagementPort = "5725";
 25        private const String _defaultSTSPort = "5726";
 26
 27        private MexClient _mexClient;
 28        private WsTransferClient _wsTransferClient;
 29        private WsTransferFactoryClient _wsTransferFactoryClient;
 30        private WsEnumerationClient _wsEnumerationClient;
 31        private RmResourceFactory _resourceFactory;
 32        private RmRequestFactory _requestFactory;
 33        private PSHost _pSHost;
 34        private PSCredential _pSCreds;
 35        private string _fIMServer;
 36        private string _fIMPort;
 37        private string[] _defaultAttrNames;
 38        private bool _schemaCached;
 39        private SchemaCache _schemaCache;
 40
 41        /// <summary>
 42        /// This class contains the names of the FIM web service endpoints. They are copied from 
 43        /// Microsoft.ResourceManagement.Client.Constants.Endpoint, which is unfortunately marked internal, which makes
 44        /// them inaccessible.
 45        /// </summary>
 46        internal class EndpointNames
 47        {
 48            private EndpointNames() { }
 49            public const String MEX = "ResourceManagementService/MEX";
 50            public const String Resource = "ResourceManagementService/Resource";
 51            public const String ResourceFactory = "ResourceManagementService/ResourceFactory";
 52            public const String Enumeration = "ResourceManagementService/Enumeration";
 53            public const String Alternate = "ResourceManagementService/Alternate";
 54        }
 55
 56        public FIMPSClient(string fIMserverParam, PSCredential creds, PSHost pSHost)
 57        {
 58            // Save reference to PS host environment
 59            _pSHost = pSHost;
 60            _pSCreds = creds;
 61
 62            // Separate FIM server name and port if any, and save
 63            int colonPosition = fIMserverParam.IndexOf(':');
 64            if (colonPosition < 0)
 65            {
 66                _fIMServer = fIMserverParam.ToLower();
 67                _fIMPort = _defaultResourceManagementPort;
 68            }
 69            else
 70            {
 71                _fIMServer = fIMserverParam.Substring(0, colonPosition);
 72                _fIMPort = fIMserverParam.Substring(colonPosition + 1);
 73                /*!!! check _fIMPort for numeric value*/
 74            }
 75
 76            _mexClient = CreateMexClient();
 77            _wsTransferClient = CreateTransferClient();
 78            _wsTransferFactoryClient = CreateTransferFactoryClient();
 79            _wsEnumerationClient = CreateEnumerationClient();
 80
 81            _resourceFactory = new RmResourceFactory();
 82            _requestFactory = new RmRequestFactory();
 83            _schemaCache = new SchemaCache();
 84        }
 85
 86        /// <summary>
 87        /// Refreshes the metadata from the service.
 88        /// </summary>
 89        public XmlSchemaSet RefreshSchema()
 90        {
 91            XmlSchemaSet metadata = _mexClient.Get();
 92
 93            lock (_requestFactory)
 94            {
 95                _requestFactory = new RmRequestFactory(metadata);
 96            }
 97            lock (_resourceFactory)
 98            {
 99                _resourceFactory = new RmResourceFactory(metadata);
100            }
101            lock (_schemaCache)
102            {
103                _schemaCache = new SchemaCache(metadata);
104            }
105            
106            _schemaCached = true;
107
108            return metadata;
109        }
110
111        public SchemaCache Schema
112        {
113            get
114            {
115                if(!_schemaCached)
116                {
117                    RefreshSchema();
118                }
119                return _schemaCache;
120            }
121        }
122
123        #region ResourceTransfer
124        /// <summary>
125        /// Retrieves the object with the given ObjectId
126        /// </summary>
127        /// <param name="objectId">The ObjectId of the requested object.</param>
128        /// <returns>The object or null if not found</returns>
129        /// <exception cref="System.ServiceModel.FaultException">System.ServiceModel.FaultException thrown when failures occur.</exception>
130        public RmResource Get(RmReference objectId)
131        {
132            return Get(objectId, null, null);
133        }
134
135        /// <summary>
136        /// Retrieves the representation of an object with the given ObjectId in the given culture.
137        /// </summary>
138        /// <param name="objectId">The ObjectId of the requested object.</param>
139        /// <param name="culture">The requested culture representation of the object.</param>
140        /// <returns>The object or null if not found.</returns>
141        public RmResource Get(RmReference objectId, CultureInfo culture)
142        {
143            return Get(objectId, culture, null);
144        }
145
146        /// <summary>
147        /// Retrieves the object and the specified attributes with the given ObjectId.
148        /// </summary>
149        /// <param name="objectId">The ObjectId of the requested object.</param>
150        /// <param name="attributes">The list of attributes on the object to return.</param>
151        /// <returns></returns>
152        public RmResource Get(RmReference objectId, String[] attributes)
153        {
154            return Get(objectId, null, attributes);
155        }
156
157        /// <summary>
158        /// Retrieves the object and the specified attributes with the given ObjectId and in the specified culture.
159        /// </summary>
160        /// <param name="objectId">The ObjectId of the requested object.</param>
161        /// <param name="culture">The requested culture representation of the object.</param>
162        /// <param name="attributes">The list of attributes on the object to return.</param>
163        /// <returns>The requested object, or null if it is not found.</returns>
164        public RmResource Get(RmReference objectId, CultureInfo culture, String[] attributes)
165        {
166            GetRequest request = _requestFactory.CreateGetRequest(objectId, culture, attributes);
167            GetResponse response = _wsTransferClient.Get(request);
168            return _resourceFactory.CreateResource(response);
169        }
170
171        #endregion
172
173        #region Enumeration
174        /// <summary>
175        /// Returns an enumerator that can traverse all objects matching the given filter.
176        /// </summary>
177        /// <param name="filter">The XPath filter of which objects to select.</param>
178        /// <returns>An enumerator object which can be consumed in foreach statements.</returns>
179        public IEnumerable<RmResource> Enumerate(String filter)
180        {
181            return this.Enumerate(filter, new string[] { });
182        }
183
184        /// <summary>
185        /// Returns an enumerator that can traverse all objects matching the given filter.
186        /// 
187        /// Each object only contains the specified attributes.
188        /// </summary>
189        /// <param name="filter">The XPath filter of which objects to select.</param>
190        /// <param name="attributes">A list of attribute names to include in returned objects.</param>
191        /// <returns>An enumerator object which can be consumed in foreach statements.</returns>
192        public IEnumerable<RmResource> Enumerate(String filter, String[] attributes)
193        {
194            if (String.IsNullOrEmpty(filter))
195            {
196                throw new ArgumentNullException("filter");
197            }
198
199            return _requestFactory.CreateEnumeration(_wsEnumerationClient, _resourceFactory, filter, attributes);
200        }
201        #endregion
202
203        #region Create
204        /// <summary>
205        /// Creates the given resource and returns its ObjectId.
206        /// This method does not set the ObjectId of newResource.
207        /// </summary>
208        /// <param name="newResource">The resource to create.</param>
209        /// <returns>The ObjectId of the resource.</returns>
210        public RmReference Create(RmResource newResource)
211        {
212            if (newResource == null)
213                throw new ArgumentNullException("newResource");
214            CreateRequest request = _requestFactory.CreateCreateRequest(newResource);
215            CreateResponse response = _wsTransferFactoryClient.Create(request);
216            try
217            {
218                RmReference reference = new RmReference(response.ResourceCreated.EndpointReference.ReferenceProperties.ResourceReferenceProperty.Value);
219                newResource.ObjectID = reference;
220                return reference;
221            }
222            catch (NullReferenceException)
223            {
224                return new RmReference();
225            }
226            catch (FormatException)
227            {
228                return new RmReference();
229            }
230        }
231        #endregion
232
233        #region Put
234        /// <summary>
235        /// Saves changes made to an object recorded by the transaction to the service.
236        /// </summary>
237        /// <param name="transaction">The transaction object which recorded changes made to a Resource object.</param>
238        /// <returns>True upon successful operation.</returns>
239        public bool Put(RmResourceChanges transaction)
240        {
241            if (transaction == null)
242            {
243                throw new ArgumentNullException("transaction");
244            }
245
246            PutRequest request = _requestFactory.CreatePutRequest(transaction);
247            PutResponse response = _wsTransferClient.Put(request);
248            if (response == null)
249                return false;
250            else
251                return true;
252        }        
253        #endregion
254
255        #region Delete
256        /// <summary>
257        /// Deletes the object with the given ObjectId.
258        /// </summary>
259        /// <param name="objectId">The ObjectId of the object to delete.</param>
260        /// <returns>True upon successful deletion.</returns>
261        public bool Delete(RmReference objectId)
262        {
263            DeleteRequest request = _requestFactory.CreateDeleteRequest(objectId);
264            DeleteResponse response = _wsTransferClient.Delete(request);
265            if (response == null)
266                return false;
267            else
268                return true;
269        }
270        #endregion
271
272        /// <summary>
273        /// Returns true if the schema has been cached for this client.
274        /// </summary>
275        public bool SchemaCached
276        {
277            get
278            {
279                return _schemaCached;
280            }
281        }
282
283        private MexClient CreateMexClient()
284        {
285            EndpointAddress remoteAddress = new EndpointAddress(CreateServiceEndpointURI(EndpointNames.MEX), CreateFIMSPNIdentity());
286            WSHttpBinding binding = new WSHttpBinding(SecurityMode.None);
287            binding.MaxReceivedMessageSize = Int32.MaxValue;
288
289            return new MexClient(binding, remoteAddress);
290        }
291
292        private WsTransferClient CreateTransferClient()
293        {
294            EndpointAddress remoteAddress = new EndpointAddress(CreateServiceEndpointURI(EndpointNames.Resource), CreateFIMSPNIdentity());
295
296            System.ServiceModel.WSHttpBinding binding = new WSHttpBinding(SecurityMode.Message);
297            binding.Security.Message.EstablishSecurityContext = false;
298            binding.MaxReceivedMessageSize = Int32.MaxValue;
299
300            WsTransferClient client = new WsTransferClient(binding, remoteAddress);
301            client.ClientCredentials.Windows.ClientCredential = _pSCreds.GetNetworkCredential();
302            return client;
303        }
304
305        private WsTransferFactoryClient CreateTransferFactoryClient()
306        {
307            EndpointAddress remoteAddress = new EndpointAddress(CreateServiceEndpointURI(EndpointNames.ResourceFactory), CreateFIMSPNIdentity());
308
309            System.ServiceModel.WSHttpBinding binding = new WSHttpBinding(SecurityMode.Message);
310            binding.Security.Message.EstablishSecurityContext = false;
311            binding.MaxReceivedMessageSize = Int32.MaxValue;
312
313            WsTransferFactoryClient client = new WsTransferFactoryClient(binding, remoteAddress);
314            client.ClientCredentials.Windows.ClientCredential = _pSCreds.GetNetworkCredential();
315            return client;
316        }
317
318        private WsEnumerationClient CreateEnumerationClient()
319        {
320            EndpointAddress remoteAddress = new EndpointAddress(CreateServiceEndpointURI(EndpointNames.Enumeration), CreateFIMSPNIdentity());
321
322            System.ServiceModel.WSHttpBinding binding = new WSHttpBinding(SecurityMode.Message);
323            binding.Security.Message.EstablishSecurityContext = false;
324            binding.MaxReceivedMessageSize = Int32.MaxValue;
325
326            WsEnumerationClient client = new WsEnumerationClient(binding, remoteAddress);
327            client.ClientCredentials.Windows.ClientCredential = _pSCreds.GetNetworkCredential();
328            return client;
329        }
330
331        private Uri CreateServiceEndpointURI(string serviceEndpointName)
332        {
333            return new Uri(String.Format("http://{0}:{1}/{2}", _fIMServer, _fIMPort, serviceEndpointName));
334        }
335
336        EndpointIdentity CreateFIMSPNIdentity()
337        {
338            return EndpointIdentity.CreateSpnIdentity("IdentityManagementService/" + _fIMServer);
339        }
340    }
341}