Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

366 lines
11 KiB

  1. using System;
  2. using System.DirectoryServices;
  3. namespace UDDI.ActiveDirectory
  4. {
  5. /// <summary>
  6. /// This class manages the ServiceConnectionPoint publication into the AD
  7. /// </summary>
  8. public class UDDIServiceConnPoint
  9. {
  10. //------------------------- PUBLIC KEYWORDS -----------------------------
  11. //
  12. public const string kwdVendor = "Microsoft Corporation";
  13. public const string kwdVendorGuid = "83C29870-1DFC-11D3-A193-0000F87A9099";
  14. public const string kwdTechnology = "UDDI";
  15. public const string kwdTechnologyVer = "2.0";
  16. public const string kwdProduct = "UDDI Services";
  17. public const string kwdProductGuid = "09A92664-D144-49DB-A600-2B3ED04BF639";
  18. public const string kwdInquireAPI = "Inquire API";
  19. public const string kwdInquireAPIGuid = "4CD7E4BC-648B-426D-9936-443EAAC8AE23";
  20. public const string kwdInquireSvcClass = "UddiInquireUrl";
  21. public const string kwdPublishAPI = "Publish API";
  22. public const string kwdPublishAPIGuid = "64C756D1-3374-4E00-AE83-EE12E38FAE63";
  23. public const string kwdPublishSvcClass = "UddiPublishUrl";
  24. public const string kwdWebSiteSignature = "Web Site";
  25. public const string kwdWebSiteGuid = "316F991C-2591-4F1A-8FF1-352A76669E37";
  26. public const string kwdWebSiteSvcClass = "UddiWebSiteUrl";
  27. public const string kwdDiscovery = "DiscoveryUrl";
  28. public const string kwdDiscoveryGuid = "1276768A-1488-4C6F-A8D8-19556C6BE583";
  29. public const string kwdDiscoverySvcClass= "UddiDiscoveryUrl";
  30. public const string kwdAddWebRef = "Add Web Reference";
  31. public const string kwdAddWebRefGuid = "CE653789-F6D4-41B7-B7F4-31501831897D";
  32. public const string kwdAddWebRefSvcClass= "UddiAddWebReferenceUrl";
  33. //-------------------------- PRIVATE DEFINITIONS --------------------------
  34. //
  35. // default keywords for the site node
  36. // comma separates keywords
  37. //
  38. private const string szDefSiteKeywords = kwdTechnology + "," + kwdTechnologyVer + "," +
  39. kwdVendor + "," + kwdVendorGuid + "," +
  40. kwdProduct + "," + kwdProductGuid;
  41. // INTERNAL representation of the path. Slashes will be replaced with CN's
  42. // Do not remove or change the separators
  43. private const char cADPathSeparator = '/';
  44. private const string szADUDDIRootPath = "System/Microsoft/UDDI/Sites";
  45. //-------------------------------------------------------------------------
  46. // Creates a new entry for the site, right under the root path
  47. // above
  48. //
  49. static public DirectoryEntry CreateSiteEntry( string siteCN )
  50. {
  51. if ( siteCN == null )
  52. throw new ArgumentNullException( "Site CN cannot be null" );
  53. if ( siteCN.Length == 0 )
  54. throw new ArgumentException( "Site CN cannot be empty" );
  55. string[] ADPath = szADUDDIRootPath.Split( cADPathSeparator );
  56. string nodeCN = NormalizeCN( siteCN );
  57. DirectoryEntry adRootNode = CreateFullADPath (ADPath);
  58. DirectoryEntry adSiteNode = null;
  59. try
  60. {
  61. adSiteNode = adRootNode.Children.Find( nodeCN, "container" );
  62. }
  63. catch (Exception)
  64. {
  65. adSiteNode = null;
  66. }
  67. if ( adSiteNode == null )
  68. {
  69. adSiteNode = adRootNode.Children.Add( nodeCN, "container" );
  70. adSiteNode.CommitChanges();
  71. }
  72. try
  73. {
  74. AddNodeKeywords( adSiteNode );
  75. }
  76. catch (Exception)
  77. {
  78. }
  79. return adSiteNode;
  80. }
  81. //
  82. // Removes the Site entry and all the children
  83. //
  84. public static void DeleteSiteEntry( string siteCN )
  85. {
  86. if ( siteCN == null )
  87. throw new ArgumentNullException( "Site CN cannot be null" );
  88. if ( siteCN.Length == 0 )
  89. throw new ArgumentException( "Site CN cannot be empty" );
  90. string nodeCN = NormalizeCN( siteCN );
  91. string fullyQualifiedPath = GetFullyQualifiedPath( "" );
  92. DirectoryEntry entry = new DirectoryEntry( fullyQualifiedPath );
  93. DirectoryEntry sub = entry.Children.Find( nodeCN );
  94. try
  95. {
  96. // first, try deleting the node as if it was a leaf
  97. entry.Children.Remove (sub);
  98. entry.CommitChanges ();
  99. }
  100. catch (Exception) // most likely this is a tree, or we don't have permissions
  101. {
  102. // retry deleting the whole tree
  103. sub.DeleteTree ();
  104. }
  105. }
  106. // Drop + Create the whole site node
  107. public static DirectoryEntry ResetSiteEntry( string siteCN )
  108. {
  109. if ( siteCN == null )
  110. throw new ArgumentNullException( "Site CN cannot be null" );
  111. if ( siteCN.Length == 0 )
  112. throw new ArgumentException( "Site CN cannot be empty" );
  113. try
  114. {
  115. DeleteSiteEntry( siteCN );
  116. }
  117. catch(Exception)
  118. {
  119. }
  120. return CreateSiteEntry( siteCN );
  121. }
  122. //
  123. // Creates a Web Service entry point (e.g. Publish API)
  124. //
  125. public static void CreateEntryPoint( string siteCN,
  126. string bindingKey, string accessPoint,
  127. string serviceClass,
  128. string displayName, string description,
  129. params object[] additionalKeywords )
  130. {
  131. if ( siteCN == null || bindingKey == null || accessPoint == null || serviceClass == null)
  132. throw new ArgumentNullException( "'Site CN', 'Binding Key', 'Acess Point' and 'Service Class' are required parameters" );
  133. if ( siteCN.Length == 0 || bindingKey.Length == 0 )
  134. throw new ArgumentException( "'Site CN', 'Binding Key', 'Acess Point' and 'Service Class' are required parameters" );
  135. string entryKey = NormalizeCN( bindingKey );
  136. //
  137. // first, make sure the Site node is OK
  138. //
  139. DirectoryEntry siteNode = CreateSiteEntry( siteCN );
  140. //
  141. // then see whether the entry has been created already
  142. //
  143. DirectoryEntry svcEntry = null;
  144. try
  145. {
  146. svcEntry = siteNode.Children.Find( entryKey, "serviceConnectionPoint" );
  147. }
  148. catch (Exception)
  149. {
  150. svcEntry = null;
  151. }
  152. //
  153. // create a new entry if there is no one yet.
  154. // Otherwise, just leave it alone
  155. //
  156. if ( svcEntry == null )
  157. {
  158. svcEntry = siteNode.Children.Add( entryKey, "serviceConnectionPoint" );
  159. // now add all the rest
  160. svcEntry.Properties[ "url" ].Add( accessPoint );
  161. if ( displayName != null && displayName.Length > 0 )
  162. svcEntry.Properties[ "displayName" ].Add( displayName );
  163. if ( description != null && description.Length > 0 )
  164. svcEntry.Properties[ "description" ].Add( description );
  165. svcEntry.Properties[ "serviceClassName" ].Add( serviceClass );
  166. svcEntry.Properties[ "serviceBindingInformation" ].Add( accessPoint );
  167. //
  168. // try to save...
  169. //
  170. svcEntry.CommitChanges();
  171. }
  172. // now set the keywords
  173. try
  174. {
  175. AddNodeKeywords( svcEntry, additionalKeywords );
  176. }
  177. catch (Exception)
  178. {
  179. }
  180. }
  181. //
  182. // Removes specific service "entry point" node for the Site
  183. // E.g., one can drop "Publish API" entry but leave the rest intact
  184. //
  185. public static void RemoveEntryPoint( string siteCN, string bindingKey )
  186. {
  187. if ( siteCN == null || bindingKey == null )
  188. throw new ArgumentNullException( "Neither 'Site CN' nor 'Binding Key' can be null" );
  189. if ( siteCN.Length == 0 || bindingKey.Length == 0 )
  190. throw new ArgumentException( "Neither 'Site CN' nor 'Binding Key' can be empty" );
  191. string nodeCN = NormalizeCN( siteCN );
  192. string subKey = NormalizeCN( bindingKey );
  193. string fullyQualifiedPath = GetFullyQualifiedPath( nodeCN );
  194. DirectoryEntry entry = new DirectoryEntry( fullyQualifiedPath );
  195. DirectoryEntry sub = entry.Children.Find( subKey );
  196. try
  197. {
  198. // first, try deleting the node as if it was a leaf
  199. entry.Children.Remove (sub);
  200. entry.CommitChanges ();
  201. }
  202. catch (Exception) // most likely this is a tree, or we don't have permissions
  203. {
  204. // retry deleting the whole tree
  205. sub.DeleteTree ();
  206. }
  207. }
  208. //***************************************************************************
  209. // Internal helpers go here
  210. //
  211. //
  212. // Verifies the AD path from the root and creates the missing nodes
  213. // if necessary. Returns the AD Directory entry that corresponds to
  214. // the last (rightmost) node in the path
  215. //
  216. protected static DirectoryEntry CreateFullADPath (string[] path)
  217. {
  218. DirectoryEntry objDE = new DirectoryEntry( "LDAP://RootDSE" );
  219. string szNamingContext = objDE.Properties["defaultNamingContext"][0].ToString();
  220. DirectoryEntry adOurRoot = new DirectoryEntry ("LDAP://" + szNamingContext);
  221. DirectoryEntry adNode = adOurRoot;
  222. if ( path.Length == 0 )
  223. return adNode;
  224. foreach (string pathCN in path)
  225. {
  226. string pathPart = NormalizeCN( pathCN );
  227. DirectoryEntry subnode = null;
  228. try
  229. {
  230. subnode = adNode.Children.Find( pathPart, "container" );
  231. }
  232. catch (Exception) // not found
  233. {
  234. subnode = null;
  235. }
  236. if ( subnode == null ) // not found, go create one
  237. {
  238. subnode = adNode.Children.Add( pathPart, "container" );
  239. subnode.CommitChanges();
  240. }
  241. adNode = subnode;
  242. }
  243. return adNode;
  244. }
  245. //
  246. // Makes sure the CN node is prepended with "cn="
  247. //
  248. static protected string NormalizeCN( string szCN )
  249. {
  250. string nodeCN = szCN.ToLower();
  251. if ( !nodeCN.StartsWith( "cn=" ) )
  252. nodeCN = "CN=" + szCN;
  253. else
  254. nodeCN = szCN;
  255. return nodeCN;
  256. }
  257. //
  258. // Composes a full "path" based on the defaule naming context and our "root" path
  259. // Optionally, a "leaf" under the path can be specified
  260. //
  261. static protected string GetFullyQualifiedPath( string leafNode )
  262. {
  263. string[] ADPath = szADUDDIRootPath.Split( cADPathSeparator );
  264. string fullyQualifiedPath = "";
  265. if ( leafNode != null && leafNode.Length > 0 )
  266. fullyQualifiedPath = NormalizeCN( leafNode ) + ",";
  267. for (int i = ADPath.Length - 1; i >= 0; i-- )
  268. {
  269. fullyQualifiedPath += NormalizeCN( ADPath[i] );
  270. fullyQualifiedPath += ",";
  271. }
  272. DirectoryEntry objRoot = new DirectoryEntry ("LDAP://RootDSE");
  273. string szNamingContext = objRoot.Properties["defaultNamingContext"][0].ToString();
  274. fullyQualifiedPath = "LDAP://" + fullyQualifiedPath + szNamingContext;
  275. return fullyQualifiedPath;
  276. }
  277. //
  278. // Attempts to add the required keywords to the node
  279. // Sets up the "required" ones and then appends the "optional"
  280. //
  281. static protected void AddNodeKeywords( DirectoryEntry node, params object[] optionalKwds )
  282. {
  283. if ( node == null )
  284. throw new ArgumentNullException ("'Node' cannot be null");
  285. string[] keywords = szDefSiteKeywords.Split( ',' );
  286. foreach ( string szKwd in keywords )
  287. {
  288. node.Properties[ "keywords" ].Add( szKwd );
  289. }
  290. foreach ( object szOptKwd in optionalKwds )
  291. {
  292. node.Properties[ "keywords" ].Add( szOptKwd.ToString() );
  293. }
  294. node.CommitChanges();
  295. }
  296. }
  297. }