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.

416 lines
12 KiB

  1. /*
  2. **++
  3. **
  4. ** Copyright (c) 2002 Microsoft Corporation
  5. **
  6. **
  7. ** Module Name:
  8. **
  9. ** writerconfig.h
  10. **
  11. **
  12. ** Abstract:
  13. **
  14. ** declare classes that encapsulate the Test writer's configuration
  15. **
  16. ** Author:
  17. **
  18. ** Reuven Lax [reuvenl] 04-June-2002
  19. **
  20. **
  21. **
  22. ** Revision History:
  23. **
  24. **--
  25. */
  26. #ifndef _WRITERCONFIG_H_
  27. #define _WRITERCONFIG_H_
  28. ///////////////////////////////////////////////////////////////////////////////
  29. // Includes
  30. #include <string>
  31. #include <algorithm>
  32. #include <vector>
  33. #include "vs_xml.hxx"
  34. #include "utility.h"
  35. using std::wstring;
  36. using Utility::missingAttribute;
  37. using Utility::missingElement;
  38. using Utility::AutoCS;
  39. ///////////////////////////////////////////////////////////////////////////////
  40. // Declarations
  41. // this namespace contains all XML data
  42. namespace XMLData {
  43. // names of attributes and elements
  44. extern wchar_t AlternateLocationMapping[];
  45. extern wchar_t Component[];
  46. extern wchar_t ComponentFile[];
  47. extern wchar_t ExcludeFile[];
  48. extern wchar_t NewTarget[];
  49. extern wchar_t FailEvent[];
  50. extern wchar_t Dependency[];
  51. }
  52. ///////////////////////////////////////////////////////////////////////////////
  53. // Class Declarations
  54. // this is the generic collection class for sequences in the XML document
  55. template <class T, wchar_t ElementName[]>
  56. class XMLCollection {
  57. public:
  58. // required typedefs for a collection class
  59. typedef const T value_type ;
  60. typedef const T& reference ;
  61. typedef const T& const_reference ;
  62. typedef T* pointer ;
  63. typedef const T* const_pointer ;
  64. typedef long size_type ;
  65. class Iterator;
  66. typedef Iterator iterator;
  67. typedef Iterator const_iterator ;
  68. // The iterator for objects in the collection. The iterator is read only -- objects in the collection can't be modified
  69. class Iterator : public std::iterator<std::input_iterator_tag, T> {
  70. CXMLDocument m_doc;
  71. mutable long* m_identifier;
  72. mutable T* m_currentElement;
  73. bool m_pastEnd;
  74. unsigned long m_index;
  75. public:
  76. Iterator() : m_identifier(NULL), m_currentElement(NULL), m_pastEnd(true), m_index(0) {}
  77. Iterator(const Iterator& other) : m_identifier(NULL) { *this = other; }
  78. Iterator(const XMLCollection& collection) : m_doc(collection.m_doc), m_currentElement(NULL), m_pastEnd(false), m_index(0)
  79. {
  80. // the assumption is that m_doc is currently at a node with type ElementName
  81. // bad things will ensue if this is not true
  82. m_doc.SetToplevel();
  83. // m_identifer is used to ensure the following statements
  84. // iterator i1 = ...;
  85. // iterator i2 = i1;
  86. // assert(i1 == i2);
  87. // assert(++i1 == ++i2);
  88. m_identifier = new long(1);
  89. if (m_identifier == NULL)
  90. throw std::bad_alloc();
  91. }
  92. virtual ~Iterator() {
  93. if (m_identifier && --*m_identifier == 0)
  94. delete m_identifier;
  95. delete m_currentElement;
  96. }
  97. Iterator& operator=(const Iterator& other) {
  98. if (&other == this)
  99. return *this;
  100. m_currentElement = NULL;
  101. m_doc = other.m_doc;
  102. m_pastEnd = other.m_pastEnd;
  103. m_index = other.m_index;
  104. // make the reference count right
  105. if (other.m_identifier)
  106. ++*other.m_identifier;
  107. if(m_identifier && --*m_identifier == 0)
  108. delete m_identifier;
  109. m_identifier = other.m_identifier;
  110. return *this;
  111. }
  112. bool operator==(const Iterator& other) const {
  113. return (m_pastEnd && other.m_pastEnd) ||
  114. ((m_identifier == other.m_identifier) && (m_index == other.m_index) && !m_pastEnd && !other.m_pastEnd);
  115. }
  116. bool operator!=(const Iterator& other) const { return !(*this == other); }
  117. const_reference operator*() const {
  118. assert(m_identifier);
  119. assert(!m_pastEnd);
  120. if (!m_currentElement)
  121. m_currentElement = new T(m_doc);
  122. if (m_currentElement == NULL)
  123. throw std::bad_alloc();
  124. return *m_currentElement;
  125. }
  126. const_pointer operator->() const { return &**this; }
  127. Iterator& operator++() {
  128. if (m_pastEnd) {
  129. assert(false);
  130. return *this;
  131. }
  132. assert(m_identifier);
  133. delete m_currentElement;
  134. m_currentElement = NULL;
  135. if (!m_doc.FindElement(ElementName, false))
  136. m_pastEnd = true;
  137. ++m_index;
  138. return *this;
  139. }
  140. Iterator operator++(int) {
  141. Iterator temp = *this;
  142. ++*this;
  143. return temp;
  144. }
  145. };
  146. XMLCollection() : m_size(0) {} // initialize an empty collection
  147. XMLCollection(const XMLCollection& other) { *this = other; }
  148. XMLCollection(CXMLDocument& document) : m_doc(document), m_size(-1) { m_doc.SetToplevel(); }
  149. virtual ~XMLCollection() {}
  150. XMLCollection& operator= (const XMLCollection& other) {
  151. m_doc = other.m_doc;
  152. m_size = other.m_size;
  153. return *this;
  154. }
  155. bool operator==(const XMLCollection& other) const {
  156. return (size() == other.size()) && std::equal(begin(), end(), other.begin());
  157. }
  158. bool operator!=(const XMLCollection& other) const { return !(*this == other); }
  159. size_type size() const {
  160. // if we've already calculated the size, return it
  161. if (m_size != -1)
  162. return m_size;
  163. // otherwise, calculate the size and return it
  164. assert(!m_doc.IsEmpty()); // if so, then m_size should==0, and we wouldn't be here
  165. size_type size = 0;
  166. iterator current(*this); // can't use begin()/end() as that would recurse
  167. while (current != m_pastEndIterator) {
  168. ++size;
  169. ++current;
  170. }
  171. assert(size > 0);
  172. return (m_size = size);
  173. }
  174. size_type max_size() const { return LONG_MAX; }
  175. bool empty() const { return size() == 0; }
  176. iterator begin() const { return empty() ? m_pastEndIterator : Iterator(*this); }
  177. iterator end() const { return m_pastEndIterator; }
  178. private:
  179. friend class Iterator;
  180. CXMLDocument m_doc;
  181. mutable long m_size;
  182. Iterator m_pastEndIterator;
  183. };
  184. // little class to ensure that the document is always reset at the end of each function
  185. struct Resetter {
  186. CXMLDocument& m_config;
  187. Resetter(CXMLDocument& config) : m_config(config) {}
  188. ~Resetter() { m_config.ResetToDocument(); }
  189. };
  190. // generic file specification.
  191. struct File {
  192. File(CXMLDocument node);
  193. File(const wstring& path, const wstring& filespec, bool recursive) :
  194. m_path(path), m_filespec(filespec), m_recursive(recursive) {
  195. std::transform(m_path.begin(), m_path.end(), m_path.begin(), towupper);
  196. std::transform(m_filespec.begin(), m_filespec.end(), m_filespec.begin(), towupper);
  197. }
  198. bool operator==(const File& other) const {
  199. return (m_path == other.m_path) &&
  200. (m_filespec == other.m_filespec) &&
  201. (m_recursive == other.m_recursive);
  202. }
  203. bool operator!=(const File& other) const { return !(*this == other); }
  204. wstring toString() const;
  205. wstring m_path;
  206. wstring m_filespec;
  207. bool m_recursive;
  208. };
  209. // file specification together with an alternate-path target.
  210. struct TargetedFile : public File {
  211. TargetedFile(CXMLDocument node);
  212. TargetedFile(const wstring &path, const wstring& filespec,
  213. bool recursive, const wstring& alternate) : File(path, filespec, recursive),
  214. m_alternatePath(alternate) {
  215. std::transform(m_alternatePath.begin(), m_alternatePath.end(), m_alternatePath.begin(), towupper);
  216. }
  217. bool operator==(const TargetedFile& other) const {
  218. return (m_alternatePath == other.m_alternatePath) &&
  219. (File::operator==(other));
  220. }
  221. bool operator!=(const TargetedFile& other) const { return !(*this == other); }
  222. wstring toString() const;
  223. wstring m_alternatePath;
  224. };
  225. // Writer restore method
  226. struct RestoreMethod {
  227. RestoreMethod(CXMLDocument node);
  228. bool operator==(const RestoreMethod& other) const {
  229. return (m_method == other.m_method) &&
  230. (m_writerRestore == other.m_writerRestore) &&
  231. (m_service ==other.m_service) &&
  232. (m_rebootRequired == other.m_rebootRequired) &&
  233. (m_alternateLocations == other.m_alternateLocations);
  234. }
  235. bool operator!=(const RestoreMethod& other) const { return !(*this == other); }
  236. wstring toString() const;
  237. VSS_RESTOREMETHOD_ENUM m_method;
  238. VSS_WRITERRESTORE_ENUM m_writerRestore;
  239. wstring m_service;
  240. bool m_rebootRequired;
  241. typedef XMLCollection<TargetedFile, XMLData::AlternateLocationMapping> AlternateList ;
  242. AlternateList m_alternateLocations;
  243. };
  244. // component dependency
  245. struct Dependency {
  246. Dependency(CXMLDocument node);
  247. bool operator==(const Dependency& other) const {
  248. return (m_writerId == other.m_writerId) &&
  249. (m_logicalPath == other.m_logicalPath) &&
  250. (m_componentName == other.m_componentName);
  251. }
  252. bool operator!=(const Dependency& other) const { return !(*this == other); }
  253. wstring toString() const;
  254. VSS_ID m_writerId;
  255. wstring m_logicalPath;
  256. wstring m_componentName;
  257. };
  258. // Writer component
  259. struct ComponentBase {
  260. ComponentBase(const wstring& path = L"", const wstring& name = L"") : m_logicalPath(path), m_name(name)
  261. {}
  262. wstring toString() const;
  263. wstring m_logicalPath;
  264. wstring m_name;
  265. };
  266. struct Component : public ComponentBase {
  267. Component(CXMLDocument node);
  268. VSS_COMPONENT_TYPE m_componentType;
  269. VSS_RESTORE_TARGET m_restoreTarget;
  270. bool m_selectable;
  271. bool m_selectableForRestore;
  272. typedef XMLCollection<TargetedFile, XMLData::ComponentFile> ComponentFileList;
  273. typedef std::vector<TargetedFile> TargetList;
  274. typedef XMLCollection<Dependency, XMLData::Dependency> DependencyList;
  275. ComponentFileList m_files;
  276. DependencyList m_dependencies;
  277. TargetList m_newTargets;
  278. };
  279. // comparison operators for Component and ComponentBase
  280. bool operator==(const ComponentBase& left, const ComponentBase& right);
  281. bool operator!=(const ComponentBase& left, const ComponentBase& right);
  282. bool operator==(const Component& left, const Component& right);
  283. bool operator!=(const Component& left, const Component& right);
  284. // Writer event.
  285. struct WriterEvent {
  286. WriterEvent(CXMLDocument node);
  287. WriterEvent(Utility::Events event, bool retryable = true, long failures = 1) :
  288. m_writerEvent(event), m_retryable(retryable),
  289. m_numFailures(failures) {}
  290. bool operator==(const WriterEvent& other) const { return m_writerEvent == other.m_writerEvent; }
  291. bool operator!=(const WriterEvent& other) const { return !(*this == other); }
  292. Utility::Events m_writerEvent;
  293. bool m_retryable;
  294. long m_numFailures;
  295. };
  296. // Singleton class that encapsulates writer configuration
  297. class WriterConfiguration {
  298. private:
  299. // disallow explicit creation of this class
  300. WriterConfiguration() {}
  301. WriterConfiguration(WriterConfiguration&);
  302. operator= (WriterConfiguration&);
  303. mutable CComAutoCriticalSection m_section;
  304. mutable CXMLDocument m_doc;
  305. template <class T, wchar_t ElementName[]>
  306. const XMLCollection<T, ElementName> getCollection() const {
  307. assert(m_doc.GetLevel() == 0);
  308. AutoCS critical(m_section);
  309. Resetter reset(m_doc);
  310. if (m_doc.FindElement(ElementName, true))
  311. return XMLCollection<T, ElementName>(m_doc);
  312. else
  313. return XMLCollection<T,ElementName>();
  314. }
  315. public:
  316. typedef XMLCollection<File, XMLData::ExcludeFile> ExcludeFileList;
  317. typedef XMLCollection<Component, XMLData::Component>ComponentList;
  318. typedef XMLCollection<WriterEvent, XMLData::FailEvent> FailEventList;
  319. static WriterConfiguration* instance();
  320. void loadFromXML(const wstring& xml);
  321. VSS_USAGE_TYPE usage() const;
  322. Utility::Verbosity verbosity() const;
  323. bool checkExcludes() const;
  324. bool checkIncludes() const;
  325. RestoreMethod restoreMethod() const;
  326. const ExcludeFileList excludeFiles() const
  327. { return getCollection<File, XMLData::ExcludeFile>(); }
  328. const ComponentList components() const
  329. { return getCollection<Component, XMLData::Component>(); }
  330. const FailEventList failEvents() const
  331. { return getCollection<WriterEvent, XMLData::FailEvent>(); }
  332. };
  333. // return the singleton instance of the class
  334. // This is always called for the first time at the beginning of main, so no critical section
  335. // need be involved
  336. inline WriterConfiguration* WriterConfiguration::instance()
  337. {
  338. static WriterConfiguration configuration;
  339. return &configuration;
  340. }
  341. #endif