1
#pragma once
2

            
3
#include <algorithm>
4
#include <functional>
5
#include <map>
6
#include <string>
7
#include <vector>
8

            
9
#include "envoy/common/exception.h"
10
#include "envoy/config/core/v3/base.pb.h"
11

            
12
#include "source/common/common/assert.h"
13
#include "source/common/common/fmt.h"
14
#include "source/common/common/logger.h"
15
#include "source/common/common/utility.h"
16
#include "source/common/protobuf/utility.h"
17

            
18
#include "absl/base/attributes.h"
19
#include "absl/container/flat_hash_map.h"
20
#include "absl/strings/str_join.h"
21
#include "absl/strings/string_view.h"
22
#include "fmt/ranges.h"
23

            
24
namespace Envoy {
25
namespace Registry {
26

            
27
template <class Base> class FactoryRegistry;
28
template <class T, class Base> class RegisterFactory;
29

            
30
/**
31
 * FactoryRegistryProxy is a proxy object that provides access to the
32
 * static methods of a strongly-typed factory registry.
33
 */
34
class FactoryRegistryProxy {
35
public:
36
  virtual ~FactoryRegistryProxy() = default;
37
  virtual std::vector<absl::string_view> registeredNames() const PURE;
38
  // Return all registered factory names, including disabled factories.
39
  virtual std::vector<absl::string_view> allRegisteredNames() const PURE;
40
  virtual absl::optional<envoy::config::core::v3::BuildVersion>
41
  getFactoryVersion(absl::string_view name) const PURE;
42
  virtual bool disableFactory(absl::string_view) PURE;
43
  virtual bool isFactoryDisabled(absl::string_view) const PURE;
44
  virtual absl::flat_hash_map<std::string, std::vector<std::string>> registeredTypes() const PURE;
45
  virtual absl::string_view canonicalFactoryName(absl::string_view) const PURE;
46
};
47

            
48
template <class Base> class FactoryRegistryProxyImpl : public FactoryRegistryProxy {
49
public:
50
  using FactoryRegistry = Envoy::Registry::FactoryRegistry<Base>;
51

            
52
6274
  std::vector<absl::string_view> registeredNames() const override {
53
6274
    return FactoryRegistry::registeredNames();
54
6274
  }
55

            
56
497665
  std::vector<absl::string_view> allRegisteredNames() const override {
57
497665
    return FactoryRegistry::registeredNames(true);
58
497665
  }
59

            
60
  absl::optional<envoy::config::core::v3::BuildVersion>
61
1490948
  getFactoryVersion(absl::string_view name) const override {
62
1490948
    return FactoryRegistry::getFactoryVersion(name);
63
1490948
  }
64

            
65
1
  bool disableFactory(absl::string_view name) override {
66
1
    return FactoryRegistry::disableFactory(name);
67
1
  }
68

            
69
1490946
  bool isFactoryDisabled(absl::string_view name) const override {
70
1490946
    return FactoryRegistry::isFactoryDisabled(name);
71
1490946
  }
72

            
73
497665
  absl::flat_hash_map<std::string, std::vector<std::string>> registeredTypes() const override {
74
497665
    return FactoryRegistry::registeredTypes();
75
497665
  }
76

            
77
467
  absl::string_view canonicalFactoryName(absl::string_view name) const override {
78
467
    return FactoryRegistry::canonicalFactoryName(name);
79
467
  }
80
};
81

            
82
/**
83
 * BaseFactoryCategoryRegistry holds the static factory map for
84
 * FactoryCategoryRegistry, ensuring that friends of that class
85
 * cannot get non-const access to it.
86
 */
87
class BaseFactoryCategoryRegistry {
88
protected:
89
  using MapType = absl::flat_hash_map<std::string, FactoryRegistryProxy*>;
90

            
91
292359
  static MapType& factories() {
92
292359
    static auto* factories = new MapType();
93
292359
    return *factories;
94
292359
  }
95
};
96

            
97
/**
98
 * FactoryCategoryRegistry registers factory registries by their
99
 * declared category. The category is exposed by a static category()
100
 * method on the factory base type.
101
 *
102
 * Only RegisterFactory instances are able to register factory registries.
103
 */
104
class FactoryCategoryRegistry : public BaseFactoryCategoryRegistry {
105
public:
106
  /**
107
   * @return a read-only reference to the map of registered factory
108
   * registries.
109
   */
110
21362
  static const MapType& registeredFactories() { return factories(); }
111

            
112
  /**
113
   * @return whether the given category name is already registered.
114
   */
115
115382
  static bool isRegistered(absl::string_view category) {
116
115382
    return factories().find(category) != factories().end();
117
115382
  }
118

            
119
1
  static bool disableFactory(absl::string_view category, absl::string_view name) {
120
1
    auto registry = factories().find(category);
121

            
122
1
    if (registry != factories().end()) {
123
1
      return registry->second->disableFactory(name);
124
1
    }
125

            
126
    return false;
127
1
  }
128

            
129
private:
130
  // Allow RegisterFactory and the test helper InjectFactoryCategory to register a category, but
131
  // no-one else. This enforces correct use of the registration machinery.
132
  template <class T, class Base> friend class RegisterFactory;
133
  template <class Base> friend class InjectFactoryCategory;
134

            
135
40231
  static void registerCategory(const std::string& category, FactoryRegistryProxy* factory_names) {
136
40231
    auto result = factories().emplace(std::make_pair(category, factory_names));
137
40231
    RELEASE_ASSERT(result.second == true,
138
40231
                   fmt::format("Double registration for category: '{}'", category));
139
40231
  }
140

            
141
  static void deregisterCategoryForTest(const std::string& category) {
142
    factories().erase(category);
143
    RELEASE_ASSERT(factories().find(category) == factories().end(),
144
                   fmt::format("Deregistration for category '{}' failed", category));
145
  }
146
};
147

            
148
// Forward declaration of test class for friend declaration below.
149
template <typename T> class InjectFactory;
150

            
151
/**
152
 * General registry for implementation factories. The registry is templated by the Base class that a
153
 * set of factories conforms to.
154
 *
155
 * Classes are found by name, so a single name cannot be registered twice for the same Base class.
156
 * Factories are registered by reference and this reference is expected to be valid through the life
157
 * of the program. Factories cannot be deregistered.
158
 * Factories should generally be registered by statically instantiating the RegisterFactory class.
159
 *
160
 * Note: This class is not thread safe, so registration should only occur in a single threaded
161
 * environment, which is guaranteed by the static instantiation mentioned above.
162
 *
163
 * Example lookup: BaseFactoryType *factory =
164
 * FactoryRegistry<BaseFactoryType>::getFactory("example_factory_name");
165
 */
166
template <class Base> class FactoryRegistry : public Logger::Loggable<Logger::Id::config> {
167
public:
168
  /**
169
   * Return a sorted vector of registered factory names.
170
   */
171
503939
  static std::vector<absl::string_view> registeredNames(bool include_disabled = false) {
172
503939
    std::vector<absl::string_view> ret;
173

            
174
503939
    ret.reserve(factories().size());
175

            
176
1508486
    for (const auto& [factory_name, factory] : factories()) {
177
1508486
      if (factory || include_disabled) {
178
1508452
        ret.push_back(factory_name);
179
1508452
      }
180
1508486
    }
181

            
182
503939
    std::sort(ret.begin(), ret.end());
183

            
184
503939
    return ret;
185
503939
  }
186

            
187
  /**
188
   * Gets the current map of factory implementations.
189
   */
190
4330717
  static absl::flat_hash_map<std::string, Base*>& factories() {
191
4330717
    static auto* factories = new absl::flat_hash_map<std::string, Base*>;
192
4330717
    return *factories;
193
4330717
  }
194

            
195
  /**
196
   * Gets the current map of vendor specific factory versions.
197
   */
198
  static absl::flat_hash_map<std::string, envoy::config::core::v3::BuildVersion>&
199
2981897
  versionedFactories() {
200
2981897
    using VersionedFactoryMap =
201
2981897
        absl::flat_hash_map<std::string, envoy::config::core::v3::BuildVersion>;
202
2981897
    MUTABLE_CONSTRUCT_ON_FIRST_USE(VersionedFactoryMap);
203
2981897
  }
204

            
205
7541
  static absl::flat_hash_map<std::string, std::string>& deprecatedFactoryNames() {
206
7541
    static auto* deprecated_factory_names = new absl::flat_hash_map<std::string, std::string>;
207
7541
    return *deprecated_factory_names;
208
7541
  }
209

            
210
  /**
211
   * Lazily constructs a mapping from the configuration message type to a factory,
212
   * including the deprecated configuration message types.
213
   * Must be invoked after factory registration is completed.
214
   */
215
780869
  static absl::flat_hash_map<std::string, Base*>& factoriesByType() {
216
780869
    static absl::flat_hash_map<std::string, Base*>* factories_by_type =
217
780869
        buildFactoriesByType().release();
218

            
219
780869
    return *factories_by_type;
220
780869
  }
221

            
222
9
  static bool& allowDuplicates() {
223
9
    static bool* allow_duplicates = new bool(false);
224
9
    return *allow_duplicates;
225
9
  }
226

            
227
  /**
228
   * instead_value are used when passed name was deprecated.
229
   */
230
  static void registerFactory(Base& factory, absl::string_view name,
231
131474
                              absl::string_view instead_value = "") {
232
131474
    auto result = factories().emplace(std::make_pair(name, &factory));
233
131474
    if (!result.second && !allowDuplicates()) {
234
1
      ExceptionUtil::throwEnvoyException(
235
1
          fmt::format("Double registration for name: '{}'", factory.name()));
236
1
    }
237

            
238
131474
    if (!instead_value.empty()) {
239
6604
      deprecatedFactoryNames().emplace(std::make_pair(name, instead_value));
240
6604
    }
241
131474
  }
242

            
243
  /**
244
   * version is used for registering vendor specific factories that are versioned
245
   * independently of Envoy.
246
   */
247
  static void registerFactory(Base& factory, absl::string_view name,
248
                              const envoy::config::core::v3::BuildVersion& version,
249
1
                              absl::string_view instead_value = "") {
250
1
    auto result = factories().emplace(std::make_pair(name, &factory));
251
1
    if (!result.second) {
252
      ExceptionUtil::throwEnvoyException(
253
          fmt::format("Double registration for name: '{}'", factory.name()));
254
    }
255
1
    versionedFactories().emplace(std::make_pair(name, version));
256
1
    if (!instead_value.empty()) {
257
      deprecatedFactoryNames().emplace(std::make_pair(name, instead_value));
258
    }
259
1
  }
260

            
261
  /**
262
   * Permanently disables the named factory by setting the corresponding
263
   * factory pointer to null. If the factory is registered under multiple
264
   * (deprecated) names, all the possible names are disabled.
265
   */
266
1
  static bool disableFactory(absl::string_view name) {
267
2
    const auto disable = [](absl::string_view name) -> bool {
268
2
      auto it = factories().find(name);
269
2
      if (it != factories().end()) {
270
2
        it->second = nullptr;
271
2
        return true;
272
2
      }
273
      return false;
274
2
    };
275

            
276
    // First, find the canonical name for this factory.
277
1
    absl::string_view canonicalName = canonicalFactoryName(name);
278

            
279
    // Next, disable the factory by all its deprecated names.
280
4
    for (const auto& [deprecated_name, mapped_canonical_name] : deprecatedFactoryNames()) {
281
4
      if (mapped_canonical_name == canonicalName) {
282
1
        disable(deprecated_name);
283
1
      }
284
4
    }
285

            
286
    // Finally, disable the factory by its canonical name.
287
1
    return disable(canonicalName);
288
1
  }
289

            
290
  /**
291
   * Gets a factory by name. If the name isn't found in the registry, returns nullptr.
292
   */
293
818301
  static Base* getFactory(absl::string_view name) {
294
818301
    auto it = factories().find(name);
295
818301
    if (it == factories().end()) {
296
43128
      return nullptr;
297
43128
    }
298

            
299
775173
    return it->second;
300
818301
  }
301

            
302
139312
  static Base* getFactoryByType(absl::string_view type) {
303
139312
    auto it = factoriesByType().find(type);
304
139312
    if (it == factoriesByType().end()) {
305
220
      return nullptr;
306
220
    }
307
139092
    return it->second;
308
139312
  }
309

            
310
  /**
311
   * @return the canonical name of the factory. If the given name is a
312
   * deprecated factory name, the canonical name is returned instead.
313
   */
314
468
  static absl::string_view canonicalFactoryName(absl::string_view name) {
315
468
    const auto it = deprecatedFactoryNames().find(name);
316
468
    return (it == deprecatedFactoryNames().end()) ? name : it->second;
317
468
  }
318

            
319
  /**
320
   * @return true if the named factory was disabled.
321
   */
322
1490946
  static bool isFactoryDisabled(absl::string_view name) {
323
1490946
    auto it = factories().find(name);
324
1490946
    ASSERT(it != factories().end());
325
1490946
    return it->second == nullptr;
326
1490946
  }
327

            
328
  /**
329
   * @return vendor specific version of a factory.
330
   */
331
  static absl::optional<envoy::config::core::v3::BuildVersion>
332
1490948
  getFactoryVersion(absl::string_view name) {
333
1490948
    auto it = versionedFactories().find(name);
334
1490948
    if (it == versionedFactories().end()) {
335
1490947
      return absl::nullopt;
336
1490947
    }
337
1
    return it->second;
338
1490948
  }
339

            
340
  /**
341
   * @return set of config type names indexed by the factory name.
342
   */
343
497665
  static absl::flat_hash_map<std::string, std::vector<std::string>> registeredTypes() {
344
497665
    absl::flat_hash_map<std::string, std::vector<std::string>> mapping;
345
834411
    for (const auto& [config_type, factory] : factoriesByType()) {
346
834411
      mapping[factory->name()].push_back(config_type);
347
834411
    }
348
497665
    return mapping;
349
497665
  }
350

            
351
private:
352
  // Allow factory injection only in tests.
353
  friend class InjectFactory<Base>;
354

            
355
26735
  static std::unique_ptr<absl::flat_hash_map<std::string, Base*>> buildFactoriesByType() {
356
26735
    auto mapping = std::make_unique<absl::flat_hash_map<std::string, Base*>>();
357

            
358
73756
    for (const auto& [factory_name, factory] : factories()) {
359
73236
      UNREFERENCED_PARAMETER(factory_name);
360
73236
      if (factory == nullptr) {
361
        continue;
362
      }
363

            
364
73334
      for (const auto& config_type : factory->configTypes()) {
365
47454
        ASSERT(!config_type.empty(), "Extension config types can never be empty string");
366

            
367
        // Register config types in the mapping.
368
47454
        auto it = mapping->find(config_type);
369
47454
        if (it != mapping->end() && it->second != factory) {
370
          // Mark double-registered types with a nullptr for tests only.
371
          // See issue https://github.com/envoyproxy/envoy/issues/9643.
372
          RELEASE_ASSERT(false, fmt::format("Double registration for type: '{}' by '{}' and '{}'",
373
                                            config_type, factory->name(),
374
                                            it->second ? it->second->name() : ""));
375
          it->second = nullptr;
376
47454
        } else {
377
47454
          mapping->emplace(std::make_pair(config_type, factory));
378
47454
        }
379
47454
      }
380
73236
    }
381

            
382
26735
    return mapping;
383
26735
  }
384

            
385
  // Rebuild the factories-by-type map based on the current factories.
386
4580
  static void rebuildFactoriesByTypeForTest() {
387
4580
    auto& mapping = factoriesByType();
388
4580
    auto updated_mapping = buildFactoriesByType();
389

            
390
    // Copy the updated mapping over the old one.
391
4580
    mapping = *updated_mapping;
392
4580
  }
393

            
394
  /**
395
   * Replaces a factory by name. This method should only be used for testing purposes.
396
   * @param factory is the factory to inject.
397
   * @param deprecated_names install the given deprecated names for this factory.
398
   * @return std::function<void()> a function that will restore the previously registered factories
399
   *         (by name or type).
400
   */
401
  static std::function<void()>
402
  replaceFactoryForTest(Base& factory,
403
2286
                        std::initializer_list<absl::string_view> deprecated_names = {}) {
404
2286
    using DeprecatedNamesVector = std::vector<std::pair<std::string, std::string>>;
405

            
406
    // If an existing factory is registered with this name, track it for later restoration.
407
2286
    Base* prev_by_name = nullptr;
408
2286
    auto it = factories().find(factory.name());
409
2286
    if (it != factories().end()) {
410
444
      prev_by_name = it->second;
411
444
      factories().erase(it);
412

            
413
444
      ENVOY_LOG(
414
444
          info, "Factory '{}' (type '{}') displaced-by-name with test factory '{}' (type '{}')",
415
444
          prev_by_name->name(), prev_by_name->configTypes(), factory.name(), factory.configTypes());
416
2168
    } else {
417
1842
      ENVOY_LOG(info, "Factory '{}' (type '{}') registered for tests", factory.name(),
418
1842
                factory.configTypes());
419
1842
    }
420

            
421
2286
    factories().emplace(factory.name(), &factory);
422
2286
    RELEASE_ASSERT(getFactory(factory.name()) == &factory,
423
2286
                   "test factory by-name registration failed");
424

            
425
2286
    DeprecatedNamesVector prev_deprecated_names;
426
2286
    if (deprecated_names.size() > 0) {
427
      for (auto deprecated_name : deprecated_names) {
428
        auto it = deprecatedFactoryNames().find(deprecated_name);
429
        if (it != deprecatedFactoryNames().end()) {
430
          prev_deprecated_names.emplace_back(std::make_pair(it->first, it->second));
431
          deprecatedFactoryNames().erase(it);
432

            
433
          ENVOY_LOG(
434
              info,
435
              "Deprecated name '{}' (mapped to '{}') displaced with test factory '{}' (type '{}')",
436
              it->first, it->second, factory.name(), factory.configTypes());
437
        } else {
438
          // Name not previously mapped, remember to remove it.
439
          prev_deprecated_names.emplace_back(std::make_pair(deprecated_name, ""));
440

            
441
          ENVOY_LOG(info, "Deprecated name '{}' (mapped to '{}')", deprecated_name, factory.name());
442
        }
443

            
444
        // Register the replacement factory with a deprecated name.
445
        factories().emplace(deprecated_name, &factory);
446
        RELEASE_ASSERT(getFactory(deprecated_name) == &factory,
447
                       "test factory registration by deprecated name failed");
448

            
449
        // Register the replacement factory's deprecated name.
450
        deprecatedFactoryNames().emplace(std::make_pair(deprecated_name, factory.name()));
451
      }
452
    }
453

            
454
2286
    rebuildFactoriesByTypeForTest();
455

            
456
2286
    return [replacement = &factory, prev_by_name, prev_deprecated_names]() {
457
      // Unregister the replacement factory by name.
458
2286
      factories().erase(replacement->name());
459

            
460
2286
      ENVOY_LOG(info, "Removed test factory '{}' (type '{}')", replacement->name(),
461
2286
                replacement->configTypes());
462

            
463
2286
      if (prev_by_name) {
464
        // Restore any factory displaced by name, but only register the type if it's non-empty.
465
444
        factories().emplace(prev_by_name->name(), prev_by_name);
466

            
467
444
        ENVOY_LOG(info, "Restored factory '{}' (type '{}'), formerly displaced-by-name",
468
444
                  prev_by_name->name(), prev_by_name->configTypes());
469
444
      }
470

            
471
2286
      for (auto [prev_deprecated_name, mapped_canonical_name] : prev_deprecated_names) {
472
        deprecatedFactoryNames().erase(prev_deprecated_name);
473

            
474
        ENVOY_LOG(info, "Removed deprecated name '{}'", prev_deprecated_name);
475

            
476
        if (!mapped_canonical_name.empty()) {
477
          deprecatedFactoryNames().emplace(
478
              std::make_pair(prev_deprecated_name, mapped_canonical_name));
479

            
480
          auto* deprecated_factory = getFactory(mapped_canonical_name);
481
          RELEASE_ASSERT(deprecated_factory != nullptr,
482
                         "failed to restore deprecated factory name");
483
          factories().emplace(mapped_canonical_name, deprecated_factory);
484

            
485
          ENVOY_LOG(info, "Restored deprecated name '{}' (mapped to '{}'", prev_deprecated_name,
486
                    mapped_canonical_name);
487
        }
488
      }
489

            
490
2286
      rebuildFactoriesByTypeForTest();
491
2286
    };
492
2286
  }
493
};
494

            
495
/**
496
 * Factory registration template. Enables users to register a particular implementation factory with
497
 * the FactoryRegistry by instantiating this templated class with the specific factory class and the
498
 * general Base class to which that factory conforms.
499
 *
500
 * Because factories are generally registered once and live for the length of the program, the
501
 * standard use of this class is static instantiation within a linked implementation's translation
502
 * unit. For an example of a typical use case, @see NamedNetworkFilterConfigFactory.
503
 *
504
 * Example registration: REGISTER_FACTORY(SpecificFactory, BaseFactory);
505
 *                       LEGACY_REGISTER_FACTORY(SpecificFactory, BaseFactory, "deprecated_name");
506
 */
507
template <class T, class Base> class RegisterFactory {
508
public:
509
  /**
510
   * Constructor that registers an instance of the factory with the FactoryRegistry.
511
   */
512
108778
  RegisterFactory() {
513
108778
    ASSERT(!instance_.name().empty());
514
108778
    FactoryRegistry<Base>::registerFactory(instance_, instance_.name());
515

            
516
    // Also register this factory with its category.
517
    //
518
    // Each time a factory registers, the registry will attempt to
519
    // register its category here. This means that we have to ignore
520
    // multiple attempts to register the same category and can't detect
521
    // duplicate categories.
522
108778
    if (!FactoryCategoryRegistry::isRegistered(instance_.category())) {
523
36631
      FactoryCategoryRegistry::registerCategory(instance_.category(),
524
36631
                                                new FactoryRegistryProxyImpl<Base>());
525
36631
    }
526
108778
  }
527

            
528
  /**
529
   * Constructor that registers an instance of the factory with the FactoryRegistry along with
530
   * deprecated names.
531
   */
532
6604
  explicit RegisterFactory(std::initializer_list<absl::string_view> deprecated_names) {
533
6604
    if (!instance_.name().empty()) {
534
6604
      FactoryRegistry<Base>::registerFactory(instance_, instance_.name());
535
6604
    } else {
536
      ASSERT(deprecated_names.size() != 0,
537
             "Attempted to register a factory without a name or deprecated name");
538
    }
539

            
540
6604
    for (auto deprecated_name : deprecated_names) {
541
6604
      ASSERT(!deprecated_name.empty());
542
6604
      FactoryRegistry<Base>::registerFactory(instance_, deprecated_name, instance_.name());
543
6604
    }
544

            
545
6604
    if (!FactoryCategoryRegistry::isRegistered(instance_.category())) {
546
3600
      FactoryCategoryRegistry::registerCategory(instance_.category(),
547
3600
                                                new FactoryRegistryProxyImpl<Base>());
548
3600
    }
549
6604
  }
550

            
551
  /**
552
   * Constructor that registers an instance of the factory with the FactoryRegistry along with
553
   * vendor specific version.
554
   */
555
  RegisterFactory(uint32_t major, uint32_t minor, uint32_t patch,
556
                  const std::map<std::string, std::string>& version_metadata)
557
1
      : RegisterFactory(major, minor, patch, version_metadata, {}) {}
558

            
559
  /**
560
   * Constructor that registers an instance of the factory with the FactoryRegistry along with
561
   * vendor specific version and deprecated names.
562
   */
563
  RegisterFactory(uint32_t major, uint32_t minor, uint32_t patch,
564
                  const std::map<std::string, std::string>& version_metadata,
565
1
                  std::initializer_list<absl::string_view> deprecated_names) {
566
1
    auto version = makeBuildVersion(major, minor, patch, version_metadata);
567
1
    if (instance_.name().empty()) {
568
      ASSERT(deprecated_names.size() != 0);
569
1
    } else {
570
1
      FactoryRegistry<Base>::registerFactory(instance_, instance_.name(), version);
571
1
    }
572

            
573
1
    for (auto deprecated_name : deprecated_names) {
574
      ASSERT(!deprecated_name.empty());
575
      FactoryRegistry<Base>::registerFactory(instance_, deprecated_name, version, instance_.name());
576
    }
577

            
578
1
    if (!FactoryCategoryRegistry::isRegistered(instance_.category())) {
579
      FactoryCategoryRegistry::registerCategory(instance_.category(),
580
                                                new FactoryRegistryProxyImpl<Base>());
581
    }
582
1
  }
583

            
584
private:
585
  static envoy::config::core::v3::BuildVersion
586
  makeBuildVersion(uint32_t major, uint32_t minor, uint32_t patch,
587
1
                   const std::map<std::string, std::string>& metadata) {
588
1
    envoy::config::core::v3::BuildVersion version;
589
1
    version.mutable_version()->set_major_number(major);
590
1
    version.mutable_version()->set_minor_number(minor);
591
1
    version.mutable_version()->set_patch(patch);
592
1
    *version.mutable_metadata() = MessageUtil::keyValueStruct(metadata);
593
1
    return version;
594
1
  }
595

            
596
  T instance_{};
597
};
598

            
599
/**
600
 * RegisterInternalFactory is a special case for registering factories
601
 * that are considered internal implementation details that should
602
 * not be exposed to operators via the factory categories.
603
 *
604
 * There is no corresponding REGISTER_INTERNAL_FACTORY because
605
 * this should be used sparingly and only in special cases.
606
 */
607
template <class T, class Base> class RegisterInternalFactory {
608
public:
609
9488
  RegisterInternalFactory() {
610
9488
    ASSERT(!instance_.name().empty());
611
9488
    FactoryRegistry<Base>::registerFactory(instance_, instance_.name());
612
9488
  }
613

            
614
private:
615
  T instance_{};
616
};
617

            
618
#ifdef ENVOY_STATIC_EXTENSION_REGISTRATION
619
/**
620
 * Macro used for static registration.
621
 */
622
#define REGISTER_FACTORY(FACTORY, BASE)                                                            \
623
  ABSL_ATTRIBUTE_UNUSED void forceRegister##FACTORY() {}                                           \
624
  static Envoy::Registry::RegisterFactory</* NOLINT(fuchsia-statically-constructed-objects) */     \
625
                                          FACTORY, BASE>                                           \
626
      FACTORY##_registered
627
/**
628
 * Macro used for static registration with deprecated name.
629
 */
630
#define LEGACY_REGISTER_FACTORY(FACTORY, BASE, DEPRECATED_NAME)                                    \
631
  ABSL_ATTRIBUTE_UNUSED void forceRegister##FACTORY() {}                                           \
632
  static Envoy::Registry::RegisterFactory</* NOLINT(fuchsia-statically-constructed-objects) */     \
633
                                          FACTORY, BASE>                                           \
634
      FACTORY##_registered {                                                                       \
635
    DEPRECATED_NAME                                                                                \
636
  }
637
#else
638
/**
639
 * Macro used to define a registration function.
640
 */
641
#define REGISTER_FACTORY(FACTORY, BASE)                                                            \
642
  ABSL_ATTRIBUTE_UNUSED void forceRegister##FACTORY() {                                            \
643
    ABSL_ATTRIBUTE_UNUSED static auto registered =                                                 \
644
        new Envoy::Registry::RegisterFactory<FACTORY, BASE>();                                     \
645
  }
646
/**
647
 * Macro used to define a registration function with deprecated name.
648
 */
649
#define LEGACY_REGISTER_FACTORY(FACTORY, BASE, DEPRECATED_NAME)                                    \
650
  ABSL_ATTRIBUTE_UNUSED void forceRegister##FACTORY() {                                            \
651
    ABSL_ATTRIBUTE_UNUSED static auto registered =                                                 \
652
        new Envoy::Registry::RegisterFactory<FACTORY, BASE>({DEPRECATED_NAME});                    \
653
  }
654
#endif
655

            
656
#define FACTORY_VERSION(major, minor, patch, ...) major, minor, patch, __VA_ARGS__
657

            
658
/**
659
 * Macro used for static registration declaration.
660
 * Calling forceRegister...(); can be used to force the static factory initializer to run in a
661
 * setting in which Envoy is bundled as a static archive. In this case, the static initializer is
662
 * not run until a function in the compilation unit is invoked. The force function can be invoked
663
 * from a static library wrapper.
664
 */
665
#define DECLARE_FACTORY(FACTORY) ABSL_ATTRIBUTE_UNUSED void forceRegister##FACTORY()
666

            
667
} // namespace Registry
668
} // namespace Envoy