daeURI.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. /*
  2. * Copyright 2006 Sony Computer Entertainment Inc.
  3. *
  4. * Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); you may not use this
  5. * file except in compliance with the License. You may obtain a copy of the License at:
  6. * http://research.scea.com/scea_shared_source_license.html
  7. *
  8. * Unless required by applicable law or agreed to in writing, software distributed under the License
  9. * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  10. * implied. See the License for the specific language governing permissions and limitations under the
  11. * License.
  12. */
  13. #ifndef __DAE_URI_H__
  14. #define __DAE_URI_H__
  15. #include <string>
  16. #include <dae/daeTypes.h>
  17. #include <dae/daeElement.h>
  18. #include <dae/daeUtils.h>
  19. class DAE;
  20. /**
  21. * The @c daeURI is a simple class designed to aid in the parsing and resolution
  22. * of URI references inside COLLADA elements.
  23. * A @c daeURI is created for every @c anyURL and @c IDREF in the COLLADA schema.
  24. * For example, the <instance> element has the url= attribute of type @c anyURL, and the
  25. * <controller> element has the target= attribute of type @c IDREF.
  26. * The @c daeURI class contains a URI string; the @c set() method breaks the string into
  27. * its components including scheme, authority, path (directory), and fragment.
  28. * It also has the capability to attempt to resolve this reference
  29. * into a @c daeElement, through the method @c resolveElement().
  30. * If a @c daeURI is stored within a @c daeElement, it fills
  31. * its container field to point to the containing element.
  32. *
  33. * The main API on the @c daeURI, @c resolveElement(), uses a @c daeURIResolver
  34. * to search for the @c daeElement inside a @c daeDatabase.
  35. *
  36. * URIs are resolved hierarchically, where each URI is resolved based on
  37. * the following criteria via itself and its element's base URI, which represents the
  38. * URI of the document that contains the element, retrieved by
  39. * <tt>daeElement::getBaseURI().</tt>
  40. * If no base URI is provided, then the application URI
  41. * is used as a base.
  42. *
  43. * The URI resolution order for the COLLADA DOM is as follows:
  44. * - Absolute URI is specified (see definition below):
  45. * The URI ignores its parent/base URI when validating.
  46. * - Relative URI is specified:
  47. * The URI uses the base URI to provide the scheme, authority, and base path.
  48. * This URI's path is appended to the path given the the base URI.
  49. * This URI's file and ID are used.
  50. * - Each level of URI is resolved in this way against the base URI of the
  51. * containing file until the top level is reached. Then the application URI
  52. * is used as the default.
  53. *
  54. * <b>Definition of Absolute URI:</b>
  55. * For the purposes of the COLLADA DOM, a URI is considered absolute
  56. * if it starts by specifying a scheme.
  57. * For example,
  58. * - file:///c:/data/foo.dae#myScene is an absolute URI.
  59. * - foo.dae#myScene is relative.
  60. * - foo.dae is a top-level file reference and is relative.
  61. * If the URI does not include a pound sign (#), the <tt><i>fragment</i></tt> is empty.
  62. */
  63. class DLLSPEC daeURI
  64. {
  65. private:
  66. daeElement* internalResolveElement() const;
  67. public:
  68. /**
  69. * An enum describing the status of the URI resolution process.
  70. * This is pretty much entirely useless now. Just use the various accessors
  71. * to query the state of the uri.
  72. */
  73. enum ResolveState{
  74. /** No URI specified */
  75. uri_empty,
  76. /** URI specified but unresolved */
  77. uri_loaded,
  78. /** Resolution pending */
  79. uri_pending,
  80. /** Resolution successful */
  81. uri_success,
  82. /** Failure due to unsupported URI scheme */
  83. uri_failed_unsupported_protocol,
  84. /** Failure because the file was not found */
  85. uri_failed_file_not_found,
  86. /** Failure because the fragment was not found */
  87. uri_failed_id_not_found,
  88. /** Failure due to an invalid fragment */
  89. uri_failed_invalid_id,
  90. /** A flag specifying that the URI should be resolved locally to its own document */
  91. uri_resolve_local,
  92. /** A flag specifying that the URI should be resolved using this relative URI */
  93. uri_resolve_relative,
  94. /** A flag specifying that the URI should be resolved using this absolute URI */
  95. uri_resolve_absolute,
  96. /** Failure due to an invalid reference */
  97. uri_failed_invalid_reference,
  98. /** Failure due to an external error */
  99. uri_failed_externalization,
  100. /** Failure due to missing document */
  101. uri_failed_missing_container,
  102. /** Failure because automatic loading of a document is turned off */
  103. uri_failed_external_document
  104. };
  105. private:
  106. // All daeURIs have a pointer to a master DAE that they use to access global information.
  107. mutable DAE* dae;
  108. /** Resolved version of the URI */
  109. std::string uriString;
  110. /** Original URI before resolution */
  111. std::string originalURIString;
  112. /** scheme component */
  113. std::string _scheme;
  114. /** authority component */
  115. std::string _authority;
  116. /** path component */
  117. std::string _path;
  118. /** query component */
  119. std::string _query;
  120. /** fragment component */
  121. std::string _fragment;
  122. /** Pointer to the element that owns this URI */
  123. daeElement* container;
  124. public:
  125. /**
  126. * Constructs a daeURI object that contains no URI reference.
  127. * @param dae The DAE associated with this daeURI.
  128. * current working directory.
  129. */
  130. daeURI(DAE& dae);
  131. /**
  132. * Destructor
  133. */
  134. ~daeURI();
  135. /**
  136. * Constructs a daeURI object from a URI passed in as a string.
  137. * @param dae The DAE associated with this daeURI.
  138. * @param URIString Passed to set() automatically.
  139. * @param nofrag If true, the fragment part of the URI is stripped off before construction.
  140. */
  141. daeURI(DAE& dae, const std::string& URIString, daeBool nofrag = false);
  142. /**
  143. * Constructs a daeURI object using a <tt><i>baseURI</i></tt> and a <tt><i>uriString.</i></tt>
  144. * Calls set(URIString), and @c validate(baseURI).
  145. * @param baseURI Base URI to resolve against.
  146. * @param URIString String designating this URI.
  147. */
  148. daeURI(const daeURI& baseURI, const std::string& URIString);
  149. /**
  150. * Constructs a daeURI object based on a simple copy from an existing @c daeURI.
  151. * @param constructFromURI URI to copy into this one.
  152. */
  153. daeURI(const daeURI& constructFromURI);
  154. /**
  155. * Constructs a daeURI given a container element and a URI string.
  156. * @param container The container element.
  157. * @param uriString the URI string.
  158. */
  159. daeURI(daeElement& container, const std::string& uriString = "");
  160. // This constructor is for internal DOM purposes only. For client code, use the constructor
  161. // that takes only a daeElement instead of this one.
  162. daeURI(DAE& dae, daeElement& container, const std::string& uriString = "");
  163. /**
  164. * Gets the DAE objects associated with this daeURI.
  165. * @return Returns a pointer to the associated DAE. This will never return null.
  166. */
  167. DAE* getDAE() const;
  168. // Returns the fully resolved URI as a string
  169. const std::string& str() const;
  170. // Returns the URI as originally set (i.e. not resolved against the base URI)
  171. const std::string& originalStr() const;
  172. // Old C string versions of the previous functions
  173. daeString getURI() const; // Alias for str()
  174. daeString getOriginalURI() const; // Alias for originalStr();
  175. // Setter function for setting the full uri.
  176. void set(const std::string& uriStr, const daeURI* baseURI = NULL);
  177. // Setter function for setting the individual uri components.
  178. void set(const std::string& scheme,
  179. const std::string& authority,
  180. const std::string& path,
  181. const std::string& query,
  182. const std::string& fragment,
  183. const daeURI* baseURI = NULL);
  184. // Old C string function. Alias for set().
  185. void setURI(daeString uriStr, const daeURI* baseURI = NULL);
  186. // std::string based component accessors.
  187. const std::string& scheme() const;
  188. const std::string& authority() const;
  189. const std::string& path() const;
  190. const std::string& query() const;
  191. const std::string& fragment() const;
  192. const std::string& id() const; // Alias for fragment()
  193. // Component setter functions. If you're going to be calling multiple setters, as in
  194. // uri.path(path);
  195. // uri.fragment(frag);
  196. // it'd be more efficient to call uri.set once instead.
  197. void scheme(const std::string& scheme);
  198. void authority(const std::string& authority);
  199. void path(const std::string& path);
  200. void query(const std::string& query);
  201. void fragment(const std::string& fragment);
  202. void id(const std::string& id); // Alias for uri.fragment(frag)
  203. // Retrieves the individual path components. For example, in a uri of the form
  204. // file:/folder/file.dae, dir = /folder/, baseName = file, ext = .dae
  205. void pathComponents(std::string& dir, std::string& baseName, std::string& ext) const;
  206. // Individual path component accessors. If you need access to multiple path
  207. // components, calling pathComponents() will be faster.
  208. std::string pathDir() const; // daeURI("/folder/file.dae").pathDir() == "/folder/"
  209. std::string pathFileBase() const; // daeURI("/folder/file.dae").pathFileBase() == "file"
  210. std::string pathExt() const; // daeURI("/folder/file.dae").pathExt() == ".dae"
  211. std::string pathFile() const; // daeURI("/folder/file.dae").pathFile() == "file.dae"
  212. // Path component setter.
  213. void path(const std::string& dir, const std::string& baseName, const std::string& ext);
  214. // Individual path component setters. If you're going to be calling multiple setters,
  215. // it'd be more efficient to call set() instead.
  216. void pathDir(const std::string& dir);
  217. void pathFileBase(const std::string& baseName);
  218. void pathExt(const std::string& ext);
  219. void pathFile(const std::string& file);
  220. // The older C string accessors. Aliases for the std::string based component accessors.
  221. daeString getScheme() const;
  222. daeString getProtocol() const; // Alias for getScheme()
  223. daeString getAuthority() const;
  224. daeString getPath() const;
  225. daeString getQuery() const;
  226. daeString getFragment() const;
  227. daeString getID() const; // Alias for getFragment()
  228. // Same as getPath(), but puts the result in the destination buffer. This is only here
  229. // for backward compatibility. Use getPath() instead.
  230. daeBool getPath(daeChar* dest, daeInt size) const;
  231. /**
  232. * Gets the element that this URI resolves to in memory.
  233. * @return Returns a ref to the element.
  234. */
  235. daeElementRef getElement() const;
  236. // Returns the document that this URI references, or null if the document
  237. // hasn't been loaded yet.
  238. daeDocument* getReferencedDocument() const;
  239. /**
  240. * Gets a pointer to the @c daeElement that contains this URI.
  241. * @return Returns the pointer to the containing daeElmement.
  242. */
  243. inline daeElement* getContainer() const {return(container);};
  244. /**
  245. * Sets the pointer to the @c daeElement that contains this URI.
  246. * @param cont Pointer to the containing @c daeElmement.
  247. */
  248. void setContainer(daeElement* container);
  249. /**
  250. * Gets if this URI resolves to an element that is not contained in the same document as the URI.
  251. * @return Returns true if the URI references an external element. False otherwise.
  252. */
  253. daeBool isExternalReference() const;
  254. /**
  255. * Copies the URI specified in <tt><i>from</i></tt> into @c this.
  256. * Performs a simple copy without validating the URI.
  257. * @param from URI to copy from.
  258. */
  259. void copyFrom(const daeURI& from);
  260. /**
  261. * Outputs all components of this URI to stderr.
  262. * Useful for debugging URIs, this outputs each part of the URI separately.
  263. */
  264. void print();
  265. /**
  266. * Makes the "originalURI" in this URI relative to some other uri
  267. * @param uri the URI to make "this" relative to.
  268. * @note this is experimental and not fully tested, please don't use in critical code yet.
  269. */
  270. int makeRelativeTo(const daeURI* uri);
  271. /**
  272. * Comparison operator.
  273. * @return Returns true if URI's are equal.
  274. */
  275. inline bool operator==(const daeURI& other) const {
  276. return uriString == other.uriString;
  277. }
  278. daeURI& operator=(const daeURI& other);
  279. daeURI& operator=(const std::string& uri);
  280. // These methods are deprecated.
  281. void resolveElement(); // Call getElement directly.
  282. void validate(const daeURI* baseURI = NULL); // Shouldn't ever need to call this.
  283. ResolveState getState() const; // Call getElement to see if resolving succeeded.
  284. void setState(ResolveState newState); // Don't call this.
  285. private:
  286. /**
  287. * Resets this URI; frees all string references
  288. * and returns <tt><i>state</i></tt> to @c empty.
  289. */
  290. void reset();
  291. /**
  292. * Provides a shared initialization for all constructors
  293. */
  294. void initialize();
  295. public:
  296. /**
  297. * Performs RFC2396 path normalization.
  298. * @param path Path to be normalized.
  299. */
  300. static void normalizeURIPath(char* path);
  301. };
  302. class daeURIResolver;
  303. typedef daeTArray<daeURIResolver*> daeURIResolverPtrArray;
  304. /**
  305. * The @c daeURIResolver class is the plugin point for URI resolution.
  306. * This class is an abstract base class that defines an interface for
  307. * resolving URIs.
  308. * Every URI is passed through this list of @c daeURIResolvers for resolution.
  309. * The list is ordered on a first come, first serve basis, and resolution
  310. * terminates after any resolver instance resolves the URI.
  311. */
  312. class DLLSPEC daeURIResolver
  313. {
  314. public:
  315. /**
  316. * Constructor
  317. * @param dae The associated dae object.
  318. */
  319. daeURIResolver(DAE& dae);
  320. /**
  321. * Destructor
  322. */
  323. virtual ~daeURIResolver();
  324. /**
  325. * Sets a flag that tells the URI resolver whether or not to load a separate document if a URI
  326. * being resolved points to one.
  327. * @param load Set to true if you want the URI Resolver to automatically load other documents to
  328. * resolve URIs.
  329. */
  330. static void setAutoLoadExternalDocuments( daeBool load );
  331. /**
  332. * Gets a flag that tells if the URI resolver is set to load an external document if a URI
  333. * being resolved points to one.
  334. * @return Returns true if the resolver will automatically load documents to resolve a URI.
  335. * False otherwise.
  336. */
  337. static daeBool getAutoLoadExternalDocuments();
  338. /**
  339. * Provides an abstract interface for converting a @c daeURI into a @c daeElement
  340. * @param uri @c daeURI to resolve.
  341. * @return Returns the resolved element, or null if resolving failed.
  342. * returns false otherwise.
  343. */
  344. virtual daeElement* resolveElement(const daeURI& uri) = 0;
  345. /**
  346. * Gets the name of this resolver.
  347. * @return Returns the resolver name as a string.
  348. */
  349. virtual daeString getName() = 0;
  350. protected:
  351. static daeBool _loadExternalDocuments;
  352. DAE* dae;
  353. };
  354. // This is a container class for storing a modifiable list of daeURIResolver objects.
  355. class DLLSPEC daeURIResolverList {
  356. public:
  357. daeURIResolverList();
  358. ~daeURIResolverList();
  359. daeTArray<daeURIResolver*>& list();
  360. daeElement* resolveElement(const daeURI& uri);
  361. private:
  362. // Disabled copy constructor/assignment operator
  363. daeURIResolverList(const daeURIResolverList& resolverList) { };
  364. daeURIResolverList& operator=(const daeURIResolverList& resolverList) { return *this; };
  365. daeTArray<daeURIResolver*> resolvers;
  366. };
  367. // Helper functions for file path <--> URI conversion
  368. namespace cdom {
  369. // Takes a uri reference and parses it into its components.
  370. DLLSPEC bool parseUriRef(const std::string& uriRef,
  371. std::string& scheme,
  372. std::string& authority,
  373. std::string& path,
  374. std::string& query,
  375. std::string& fragment);
  376. // Takes the uri components of a uri ref and combines them.
  377. //
  378. // The 'forceLibxmlCompatible' param is meant to work around bugs in the file
  379. // scheme uri handling of libxml. It causes the function to output a uri
  380. // that's fully compatible with libxml. It only modifies file scheme uris,
  381. // since uris with other schemes seem to work fine.
  382. //
  383. // The known libxml uri bugs are as follows:
  384. // 1) libxml won't write files when given file scheme URIs with an empty
  385. // authority, as in "file:/home".
  386. // 2) libxml won't read or write Windows UNC paths represented with the
  387. // machine name in the authority, as in "file://otherMachine/folder/file.dae"
  388. // 3) On Windows, libxml won't read or write paths that don't have a drive
  389. // letter, as in "/folder/file.dae".
  390. DLLSPEC std::string assembleUri(const std::string& scheme,
  391. const std::string& authority,
  392. const std::string& path,
  393. const std::string& query,
  394. const std::string& fragment,
  395. bool forceLibxmlCompatible = false);
  396. // A wrapper function for calling assembleUri to create a URI that's compatible
  397. // with libxml.
  398. DLLSPEC std::string fixUriForLibxml(const std::string& uriRef);
  399. // This function takes a file path in the OS's native format and converts it to
  400. // a URI reference. If a relative path is given, a relative URI reference is
  401. // returned. If an absolute path is given, a relative URI reference containing
  402. // a fully specified path is returned. Spaces are encoded as %20. The 'type'
  403. // parameter indicates the format of the nativePath.
  404. //
  405. // Examples - Windows
  406. // nativePathToUri("C:\myFolder\myFile.dae") --> "/C:/myFolder/myFile.dae"
  407. // nativePathToUri("\myFolder\myFile.dae") --> "/myFolder/myFile.dae"
  408. // nativePathToUri("..\myFolder\myFile.dae") --> "../myFolder/myFile.dae"
  409. // nativePathToUri("\\otherComputer\myFile.dae") --> "//otherComputer/myFile.dae"
  410. //
  411. // Examples - Linux/Mac
  412. // nativePathToUri("/myFolder/myFile.dae") --> "/myFolder/myFile.dae"
  413. // nativePathToUri("../myFolder/myFile.dae") --> "../myFolder/myFile.dae"
  414. // nativePathToUri("/my folder/my file.dae") --> "/my%20folder/my%20file.dae"
  415. DLLSPEC std::string nativePathToUri(const std::string& nativePath,
  416. systemType type = getSystemType());
  417. // This function takes a URI reference and converts it to an OS file path. Conversion
  418. // can fail if the URI reference is ill-formed, or if the URI contains a scheme other
  419. // than "file", in which case an empty string is returned. The 'type' parameter
  420. // indicates the format of the returned native path.
  421. //
  422. // Examples - Windows
  423. // uriToNativePath("../folder/file.dae") --> "..\folder\file.dae"
  424. // uriToNativePath("/folder/file.dae") --> "\folder\file.dae"
  425. // uriToNativePath("file:/C:/folder/file.dae") --> "C:\folder\file.dae"
  426. // uriToNativePath("file://otherComputer/file.dae") --> "\\otherComputer\file.dae"
  427. // uriToNativePath("http://www.slashdot.org") --> "" (it's not a file scheme URI!)
  428. //
  429. // Examples - Linux/Mac
  430. // uriToNativePath("../folder/file.dae") --> "../folder/file.dae"
  431. // uriToNativePath("file:/folder/file.dae") --> "/folder/file.dae"
  432. // uriToNativePath("http://www.slashdot.org") --> "" (it's not a file scheme URI!)
  433. DLLSPEC std::string uriToNativePath(const std::string& uriRef,
  434. systemType type = getSystemType());
  435. DLLSPEC std::string filePathToUri(const std::string& filePath); // Alias for nativePathToUri
  436. DLLSPEC std::string uriToFilePath(const std::string& uriRef); // Alias for uriToNativePath
  437. }
  438. #endif //__DAE_URI_H__