1 // 2 // Copyright 2020 Pixar 3 // 4 // Licensed under the Apache License, Version 2.0 (the "Apache License") 5 // with the following modification; you may not use this file except in 6 // compliance with the Apache License and the following modification to it: 7 // Section 6. Trademarks. is deleted and replaced with: 8 // 9 // 6. Trademarks. This License does not grant permission to use the trade 10 // names, trademarks, service marks, or product names of the Licensor 11 // and its affiliates, except as required to comply with Section 4(c) of 12 // the License and to reproduce the content of the NOTICE file. 13 // 14 // You may obtain a copy of the Apache License at 15 // 16 // http://www.apache.org/licenses/LICENSE-2.0 17 // 18 // Unless required by applicable law or agreed to in writing, software 19 // distributed under the Apache License with the above modification is 20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 // KIND, either express or implied. See the Apache License for the specific 22 // language governing permissions and limitations under the Apache License. 23 // 24 #ifndef INCLUDE_AR_RESOLVER 25 #error This file should not be included directly. Include resolver.h instead. 26 #endif 27 28 #ifndef PXR_USD_AR_RESOLVER_V1_H 29 #define PXR_USD_AR_RESOLVER_V1_H 30 31 /// \file ar/resolver_v1.h 32 33 #include "pxr/pxr.h" 34 #include "pxr/usd/ar/api.h" 35 #include <memory> 36 #include <string> 37 #include <vector> 38 39 PXR_NAMESPACE_OPEN_SCOPE 40 41 class ArAsset; 42 class ArAssetInfo; 43 class ArResolverContext; 44 class TfType; 45 class VtValue; 46 47 /// \class ArResolver 48 /// 49 /// Interface for the asset resolution system. An asset resolver is 50 /// responsible for resolving asset information (including the asset's 51 /// physical path) from a logical path. 52 /// 53 /// See \ref ar_implementing_resolver for information on how to customize 54 /// asset resolution behavior by implementing a subclass of ArResolver. 55 /// Clients may use #ArGetResolver to access the configured asset resolver. 56 /// 57 class ArResolver 58 { 59 public: 60 AR_API 61 virtual ~ArResolver(); 62 63 // Disallow copies 64 ArResolver(const ArResolver&) = delete; 65 ArResolver& operator=(const ArResolver&) = delete; 66 67 // --------------------------------------------------------------------- // 68 /// \anchor ArResolver_resolution 69 /// \name Path Resolution Operations 70 /// 71 /// @{ 72 // --------------------------------------------------------------------- // 73 74 /// Configures the resolver for a given asset path 75 AR_API 76 virtual void ConfigureResolverForAsset(const std::string& path) = 0; 77 78 /// Returns the path formed by anchoring \p path to \p anchorPath. 79 /// 80 /// If \p anchorPath ends with a trailing '/', it is treated as 81 /// a directory to which \p path will be anchored. Otherwise, it 82 /// is treated as a file and \p path will be anchored to its 83 /// containing directory. 84 /// 85 /// If \p anchorPath is empty, \p path will be returned as-is. 86 /// 87 /// If \p path is empty or not a relative path, it will be 88 /// returned as-is. 89 AR_API 90 virtual std::string AnchorRelativePath( 91 const std::string& anchorPath, 92 const std::string& path) = 0; 93 94 /// Returns true if the given path is a relative path. 95 AR_API 96 virtual bool IsRelativePath(const std::string& path) = 0; 97 98 /// Returns true if the given path is a repository path. 99 AR_API 100 virtual bool IsRepositoryPath(const std::string& path) = 0; 101 102 /// Returns whether this path is a search path. 103 AR_API 104 virtual bool IsSearchPath(const std::string& path) = 0; 105 106 /// Returns the normalized extension for the given \p path. 107 AR_API 108 virtual std::string GetExtension(const std::string& path) = 0; 109 110 /// Returns a normalized version of the given \p path 111 AR_API 112 virtual std::string ComputeNormalizedPath(const std::string& path) = 0; 113 114 /// Returns the computed repository path using the current resolver 115 AR_API 116 virtual std::string ComputeRepositoryPath(const std::string& path) = 0; 117 118 /// Returns the local path for the given \p path. 119 AR_API 120 virtual std::string ComputeLocalPath(const std::string& path) = 0; 121 122 /// Returns the resolved filesystem path for the file identified by 123 /// the given \p path if it exists. If the file does not exist, 124 /// returns an empty string. 125 AR_API 126 virtual std::string Resolve(const std::string& path) = 0; 127 128 /// @} 129 130 // --------------------------------------------------------------------- // 131 /// \anchor ArResolver_context 132 /// \name Asset Resolver Context Operations 133 /// 134 /// @{ 135 // --------------------------------------------------------------------- // 136 137 /// Binds the given context to this resolver. 138 /// 139 /// Clients should generally use ArResolverContextBinder instead of calling 140 /// this function directly. 141 /// 142 /// \see ArResolverContextBinder 143 AR_API 144 virtual void BindContext( 145 const ArResolverContext& context, 146 VtValue* bindingData) = 0; 147 148 /// Unbind the given context from this resolver. 149 /// 150 /// Clients should generally use ArResolverContextBinder instead of calling 151 /// this function directly. 152 /// 153 /// \see ArResolverContextBinder 154 AR_API 155 virtual void UnbindContext( 156 const ArResolverContext& context, 157 VtValue* bindingData) = 0; 158 159 /// Return a default ArResolverContext that may be bound to this resolver 160 /// to resolve assets when no other context is explicitly specified. 161 /// 162 /// This function should not automatically bind this context, but should 163 /// create one that may be used later. 164 AR_API 165 virtual ArResolverContext CreateDefaultContext() = 0; 166 167 /// Return a default ArResolverContext that may be bound to this resolver 168 /// to resolve the asset located at \p filePath when no other context is 169 /// explicitly specified. 170 /// 171 /// This function should not automatically bind this context, but should 172 /// create one that may be used later. 173 AR_API 174 virtual ArResolverContext CreateDefaultContextForAsset( 175 const std::string& filePath) = 0; 176 177 /// Refresh any caches associated with the given context. 178 AR_API 179 virtual void RefreshContext(const ArResolverContext& context) = 0; 180 181 /// Returns the currently-bound asset resolver context. 182 /// 183 /// \see ArResolver::BindContext, ArResolver::UnbindContext 184 AR_API 185 virtual ArResolverContext GetCurrentContext() = 0; 186 187 /// @} 188 189 // --------------------------------------------------------------------- // 190 /// \anchor ArResolver_files 191 /// \name File/asset-specific Operations 192 /// 193 /// @{ 194 // --------------------------------------------------------------------- // 195 196 /// Returns the resolved filesystem path for the file identified 197 /// by \p path following the same path resolution behavior as in 198 /// \ref Resolve(const std::string&). 199 /// 200 /// If the file identified by \p path represents an asset and 201 /// \p assetInfo is not \c nullptr, the resolver should populate 202 /// \p assetInfo with whatever additional metadata it knows or can 203 /// reasonably compute about the asset without actually opening it. 204 /// 205 /// \see Resolve(const std::string&). 206 AR_API 207 virtual std::string ResolveWithAssetInfo( 208 const std::string& path, 209 ArAssetInfo* assetInfo) = 0; 210 211 /// Update \p assetInfo with respect to the given \p fileVersion . 212 /// \note This API is currently in flux. In general, you should prefer 213 /// to call ResolveWithAssetInfo() 214 AR_API 215 virtual void UpdateAssetInfo( 216 const std::string& identifier, 217 const std::string& filePath, 218 const std::string& fileVersion, 219 ArAssetInfo* assetInfo) = 0; 220 221 /// Returns a value representing the last time the asset identified 222 /// by \p path was modified. \p resolvedPath is the resolved path 223 /// of the asset. 224 /// 225 /// Implementations may use whatever value is most appropriate 226 /// for this timestamp. The value must be equality comparable, 227 /// and this function must return a different timestamp whenever 228 /// an asset has been modified. For instance, if an asset is stored 229 /// as a file on disk, the timestamp may simply be that file's mtime. 230 /// 231 /// If a timestamp cannot be retrieved, returns an empty VtValue. 232 AR_API 233 virtual VtValue GetModificationTimestamp( 234 const std::string& path, 235 const std::string& resolvedPath) = 0; 236 237 /// Fetch the asset identified by \p path to the filesystem location 238 /// specified by \p resolvedPath. \p resolvedPath is the resolved path 239 /// that results from calling Resolve or ResolveWithAssetInfo on 240 /// \p path. 241 /// 242 /// This method provides a way for consumers that expect assets 243 /// to exist as physical files on disk to retrieve data from 244 /// systems that store data in external data stores, e.g. databases, 245 /// etc. 246 /// 247 /// Returns true if the asset was successfully fetched to the specified 248 /// \p resolvedPath or if no fetching was required. If \p resolvedPath 249 /// is not a local path or the asset could not be fetched to that path, 250 /// returns false. 251 AR_API 252 virtual bool FetchToLocalResolvedPath( 253 const std::string& path, 254 const std::string& resolvedPath) = 0; 255 256 /// Returns an ArAsset object for the asset located at \p resolvedPath. 257 /// Returns an invalid std::shared_ptr if object could not be created. 258 /// 259 /// The returned ArAsset object provides functions for accessing the 260 /// contents of the specified asset. 261 /// 262 /// Note that clients may still be using the data associated with 263 /// this object even after the last shared_ptr has been destroyed. For 264 /// example, a client may have created a memory mapping using the FILE* 265 /// presented in the ArAsset object; this would preclude truncating or 266 /// overwriting any of the contents of that file. 267 AR_API 268 virtual std::shared_ptr<ArAsset> OpenAsset( 269 const std::string& resolvedPath) = 0; 270 271 /// Create path needed to write a file to the given \p path. 272 /// 273 /// For example: 274 /// - A filesystem-based resolver might create the directories specified 275 /// in \p path. 276 /// - A database-based resolver might create a new table, or it might 277 /// ignore this altogether. 278 /// 279 /// In practice, when writing a layer, CanWriteLayerToPath will be called 280 /// first to check if writing is permitted. If this returns true, then 281 /// CreatePathForLayer will be called before writing the layer out. 282 /// 283 /// Returns true on success, false otherwise. 284 AR_API 285 virtual bool CreatePathForLayer( 286 const std::string& path) = 0; 287 288 /// Returns true if a file may be written to the given \p path, false 289 /// otherwise. 290 /// 291 /// In practice, when writing a layer, CanWriteLayerToPath will be called 292 /// first to check if writing is permitted. If this returns true, then 293 /// CreatePathForLayer will be called before writing the layer out. 294 /// 295 /// If this function returns false and \p whyNot is not \c nullptr, 296 /// it will be filled in with an explanation. 297 AR_API 298 virtual bool CanWriteLayerToPath( 299 const std::string& path, 300 std::string* whyNot) = 0; 301 302 /// Returns true if a new file may be created using the given 303 /// \p identifier, false otherwise. 304 /// 305 /// If this function returns false and \p whyNot is not \c nullptr, 306 /// it will be filled in with an explanation. 307 AR_API 308 virtual bool CanCreateNewLayerWithIdentifier( 309 const std::string& identifier, 310 std::string* whyNot) = 0; 311 312 /// @} 313 314 // --------------------------------------------------------------------- // 315 /// \anchor ArResolver_scopedCache 316 /// \name Scoped Resolution Cache 317 /// 318 /// A scoped resolution cache indicates to the resolver that results of 319 /// calls to Resolve should be cached for a certain scope. This is 320 /// important for performance and also for consistency -- it ensures 321 /// that repeated calls to Resolve with the same parameters will 322 /// return the same result. 323 /// 324 /// A resolution cache scope is opened by a call to BeginCacheScope and 325 /// must be closed with a matching call to EndCacheScope. The resolver must 326 /// cache the results of Resolve until the scope is closed. Note that these 327 /// calls may be nested. 328 /// 329 /// Cache scopes are thread-specific: if multiple threads are running and 330 /// a cache scope is opened in one of those threads, caching should be 331 /// enabled in that thread only. 332 /// 333 /// When opening a scope, a resolver may return additional data for 334 /// implementation-specific purposes. This data may be shared across 335 /// threads, so long as it is safe to access this data concurrently. 336 /// 337 /// ArResolverScopedCache is an RAII object for managing cache scope 338 /// lifetimes and data. Clients should generally use that class rather 339 /// than calling the BeginCacheScope and EndCacheScope functions manually. 340 /// 341 /// \see ArResolverScopedCache 342 /// @{ 343 // --------------------------------------------------------------------- // 344 345 /// Mark the start of a resolution caching scope. 346 /// 347 /// Clients should generally use ArResolverScopedCache instead of calling 348 /// this function directly. 349 /// 350 /// Resolvers may fill \p cacheScopeData with arbitrary data. Clients may 351 /// also pass in a \p cacheScopeData populated by an earlier call to 352 /// BeginCacheScope to allow the resolver access to that information. 353 /// 354 /// \see ArResolverScopedCache 355 AR_API 356 virtual void BeginCacheScope( 357 VtValue* cacheScopeData) = 0; 358 359 /// Mark the end of a resolution caching scope. 360 /// 361 /// Clients should generally use ArResolverScopedCache instead of calling 362 /// this function directly. 363 /// 364 /// \p cacheScopeData should contain the data that was populated by the 365 /// previous corresponding call to BeginCacheScope. 366 /// 367 /// \see ArResolverScopedCache 368 AR_API 369 virtual void EndCacheScope( 370 VtValue* cacheScopeData) = 0; 371 372 /// @} 373 374 protected: 375 AR_API 376 ArResolver(); 377 }; 378 379 /// Returns the configured asset resolver. 380 /// 381 /// When first called, this function will determine the ArResolver subclass 382 /// to use for asset resolution via the following process: 383 /// 384 /// - If a preferred resolver has been set via \ref ArSetPreferredResolver, 385 /// it will be selected. 386 /// 387 /// - Otherwise, a list of available ArResolver subclasses in plugins will 388 /// be generated. If multiple ArResolver subclasses are found, the list 389 /// will be sorted by typename. ArDefaultResolver will be added as the last 390 /// element of this list, and the first resolver in the list will be 391 /// selected. 392 /// 393 /// - The plugin for the selected subclass will be loaded and an instance 394 /// of the subclass will be constructed. 395 /// 396 /// - If an error occurs, an ArDefaultResolver will be constructed. 397 /// 398 /// The constructed ArResolver subclass will be cached and used to service 399 /// function calls made on the returned resolver. 400 /// 401 /// Note that this function may not return the constructed subclass itself, 402 /// meaning that dynamic casts to the subclass type may fail. See 403 /// ArGetUnderlyingResolver if access to this object is needed. 404 AR_API 405 ArResolver& ArGetResolver(); 406 407 /// Set the preferred ArResolver subclass used by ArGetResolver. 408 /// 409 /// Consumers may override ArGetResolver's plugin resolver discovery and 410 /// force the use of a specific resolver subclass by calling this 411 /// function with the typename of the implementation to use. 412 /// 413 /// If the subclass specified by \p resolverTypeName cannot be found, 414 /// ArGetResolver will issue a warning and fall back to using 415 /// ArDefaultResolver. 416 /// 417 /// This must be called before the first call to ArGetResolver. 418 AR_API 419 void ArSetPreferredResolver(const std::string& resolverTypeName); 420 421 /// \name Advanced API 422 /// 423 /// \warning These functions should typically not be used by consumers except 424 /// in very specific cases. Consumers who want to retrieve an ArResolver to 425 /// perform asset resolution should use \ref ArGetResolver. 426 /// 427 /// @{ 428 429 /// Returns the underlying ArResolver instance used by ArGetResolver. 430 /// 431 /// This function returns the instance of the ArResolver subclass used by 432 /// ArGetResolver and can be dynamic_cast to that type. 433 /// 434 /// \warning This functions should typically not be used by consumers except 435 /// in very specific cases. Consumers who want to retrieve an ArResolver to 436 /// perform asset resolution should use \ref ArGetResolver. 437 AR_API 438 ArResolver& ArGetUnderlyingResolver(); 439 440 /// Returns list of TfTypes for available ArResolver subclasses. 441 /// 442 /// This function returns the list of ArResolver subclasses used to determine 443 /// the resolver implementation returned by \ref ArGetResolver. See 444 /// documentation on that function for more details. 445 /// 446 /// If this function is called from within a call (or calls) to 447 /// \ref ArCreateResolver, the ArResolver subclass(es) being created will 448 /// be removed from the returned list. 449 /// 450 /// This function is not safe to call concurrently with itself or 451 /// \ref ArCreateResolver. 452 /// 453 /// \warning This functions should typically not be used by consumers except 454 /// in very specific cases. Consumers who want to retrieve an ArResolver to 455 /// perform asset resolution should use \ref ArGetResolver. 456 AR_API 457 std::vector<TfType> ArGetAvailableResolvers(); 458 459 /// Construct an instance of the ArResolver subclass specified by 460 /// \p resolverType. 461 /// 462 /// This function will load the plugin for the given \p resolverType and 463 /// construct and return a new instance of the specified ArResolver subclass. 464 /// If an error occurs, coding errors will be emitted and this function 465 /// will return an ArDefaultResolver instance. 466 /// 467 /// Note that this function *does not* change the resolver used by 468 /// \ref ArGetResolver to an instance of \p resolverType. 469 /// 470 /// This function is not safe to call concurrently with itself or 471 /// \ref ArGetAvailableResolvers. 472 /// 473 /// \warning This functions should typically not be used by consumers except 474 /// in very specific cases. Consumers who want to retrieve an ArResolver to 475 /// perform asset resolution should use \ref ArGetResolver. 476 AR_API 477 std::unique_ptr<ArResolver> ArCreateResolver(const TfType& resolverType); 478 479 /// @} 480 481 PXR_NAMESPACE_CLOSE_SCOPE 482 483 #endif 484