1 //
2 // Copyright 2016 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 PXR_BASE_PLUG_PLUGIN_H
25 #define PXR_BASE_PLUG_PLUGIN_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/base/plug/api.h"
29 
30 #include "pxr/base/js/types.h"
31 #include "pxr/base/tf/declarePtrs.h"
32 #include "pxr/base/tf/refPtr.h"
33 #include "pxr/base/tf/weakPtr.h"
34 
35 #include <atomic>
36 #include <string>
37 #include <utility>
38 #include <vector>
39 
40 PXR_NAMESPACE_OPEN_SCOPE
41 
42 TF_DECLARE_WEAK_AND_REF_PTRS(PlugPlugin);
43 
44 class Plug_RegistrationMetadata;
45 class TfType;
46 
47 /// \class PlugPlugin
48 ///
49 /// Defines an interface to registered plugins.
50 ///
51 /// Plugins are registered using the interfaces in \c PlugRegistry.
52 ///
53 /// For each registered plugin, there is an instance of
54 /// \c PlugPlugin which can be used to load and unload
55 /// the plugin and to retrieve information about the
56 /// classes implemented by the plugin.
57 ///
58 class PlugPlugin : public TfRefBase, public TfWeakBase {
59 public:
60     PLUG_API virtual ~PlugPlugin();
61 
62     /// Loads the plugin.
63     /// This is a noop if the plugin is already loaded.
64     PLUG_API bool Load();
65 
66     /// Returns \c true if the plugin is currently loaded.  Resource
67     /// plugins always report as loaded.
68     PLUG_API bool IsLoaded() const;
69 
70 #ifdef PXR_PYTHON_SUPPORT_ENABLED
71     /// Returns \c true if the plugin is a python module.
72     PLUG_API bool IsPythonModule() const;
73 #endif // PXR_PYTHON_SUPPORT_ENABLED
74 
75     /// Returns \c true if the plugin is resource-only.
76     PLUG_API bool IsResource() const;
77 
78     /// Returns the dictionary containing meta-data for the plugin.
79     PLUG_API JsObject GetMetadata();
80 
81     /// Returns the metadata sub-dictionary for a particular type.
82     PLUG_API JsObject GetMetadataForType(const TfType &type);
83 
84     /// Returns the dictionary containing the dependencies for the plugin.
85     PLUG_API JsObject GetDependencies();
86 
87     /// Returns true if \p type is declared by this plugin.
88     /// If \p includeSubclasses is specified, also returns true if any
89     /// subclasses of \p type have been declared.
90     PLUG_API bool DeclaresType(const TfType& type, bool includeSubclasses = false) const;
91 
92     /// Returns the plugin's name.
GetName()93     std::string const &GetName() const {
94         return _name;
95     }
96 
97     /// Returns the plugin's filesystem path.
GetPath()98     std::string const &GetPath() const {
99         return _path;
100     }
101 
102     /// Returns the plugin's resources filesystem path.
GetResourcePath()103     std::string const &GetResourcePath() const {
104         return _resourcePath;
105     }
106 
107     /// Build a plugin resource path by returning a given absolute path or
108     /// combining the plugin's resource path with a given relative path.
109     PLUG_API std::string MakeResourcePath(const std::string& path) const;
110 
111     /// Find a plugin resource by absolute or relative path optionally
112     /// verifying that file exists.  If verification fails an empty path
113     /// is returned.  Relative paths are relative to the plugin's resource
114     /// path.
115     PLUG_API std::string FindPluginResource(const std::string& path, bool verify = true) const;
116 
117 private:
118     enum _Type {
119         LibraryType,
120 #ifdef PXR_PYTHON_SUPPORT_ENABLED
121         PythonType,
122 #endif // PXR_PYTHON_SUPPORT_ENABLED
123         ResourceType
124     };
125 
126     // Private ctor, plugins are constructed only by PlugRegistry.
127     PLUG_LOCAL
128     PlugPlugin(const std::string & path,
129                const std::string & name,
130                const std::string & resourcePath,
131                const JsObject & plugInfo,
132                _Type type);
133 
134     PLUG_LOCAL
135     static PlugPluginPtr _GetPluginForType(const TfType & type);
136 
137     PLUG_LOCAL
138     static void _RegisterAllPlugins();
139     PLUG_LOCAL
140     static PlugPluginPtr _GetPluginWithName(const std::string& name);
141     PLUG_LOCAL
142     static PlugPluginPtrVector _GetAllPlugins();
143 
144     template <class PluginMap>
145     PLUG_LOCAL
146     static std::pair<PlugPluginPtr, bool>
147     _NewPlugin(const Plug_RegistrationMetadata &metadata,
148                _Type pluginType,
149                const std::string& pluginCreationPath,
150                PluginMap *allPluginsByNamePtr);
151 
152     PLUG_LOCAL
153     static std::pair<PlugPluginPtr, bool>
154     _NewDynamicLibraryPlugin(const Plug_RegistrationMetadata& metadata);
155 
156 #ifdef PXR_PYTHON_SUPPORT_ENABLED
157     PLUG_LOCAL
158     static std::pair<PlugPluginPtr, bool>
159     _NewPythonModulePlugin(const Plug_RegistrationMetadata& metadata);
160 #endif // PXR_PYTHON_SUPPORT_ENABLED
161 
162     PLUG_LOCAL
163     static std::pair<PlugPluginPtr, bool>
164     _NewResourcePlugin(const Plug_RegistrationMetadata& metadata);
165 
166     PLUG_LOCAL
167     bool _Load();
168 
169     PLUG_LOCAL
170     void _DeclareAliases( TfType t, const JsObject & metadata );
171     PLUG_LOCAL
172     void _DeclareTypes();
173     PLUG_LOCAL
174     void _DeclareType(const std::string &name, const JsObject &dict);
175     PLUG_LOCAL
176     static void _DefineType( TfType t );
177 
178     struct _SeenPlugins;
179     PLUG_LOCAL
180     bool _LoadWithDependents(_SeenPlugins * seenPlugins);
181 
182     PLUG_LOCAL
183     static void _UpdatePluginMaps( const TfType & baseType );
184 
185     PLUG_LOCAL
186     static constexpr char const *_GetPluginTypeDisplayName(_Type type);
187 
188 private:
189     std::string _name;
190     std::string _path;
191     std::string _resourcePath;
192     JsObject _dict;
193     void *_handle;      // the handle returned by ArchLibraryOpen() is a void*
194     std::atomic<bool> _isLoaded;
195     _Type _type;
196 
197     friend class PlugRegistry;
198 };
199 
200 /// Find a plugin's resource by absolute or relative path optionally
201 /// verifying that file exists.  If \c plugin is \c NULL or verification
202 /// fails an empty path is returned.  Relative paths are relative to the
203 /// plugin's resource path.
204 PLUG_API
205 std::string
206 PlugFindPluginResource(const PlugPluginPtr& plugin,
207                        const std::string& path, bool verify = true);
208 
209 PXR_NAMESPACE_CLOSE_SCOPE
210 
211 #endif // PXR_BASE_PLUG_PLUGIN_H
212