1 // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
2 
3 #pragma once
4 
5 #include <fbjni/fbjni.h>
6 #include "boost/functional/hash.hpp"
7 
8 #include <memory>
9 #include <unordered_map>
10 
11 namespace jni = facebook::jni;
12 
13 namespace expo {
14 using MethodHashMap = std::unordered_map<
15   std::pair<std::string, std::string>,
16   jmethodID,
17   boost::hash<std::pair<std::string, std::string>>
18 >;
19 
20 /**
21  * Singleton registry used to store references to often used Java classes.
22  */
23 class JavaReferencesCache {
24 public:
25   /**
26    * An entry in the Java class registry.
27    */
28   class CachedJClass {
29   public:
30     CachedJClass(jclass clazz, MethodHashMap methods);
31 
32     /**
33      * A bare reference to the class object.
34      */
35     jclass clazz;
36 
37     /**
38      * Returns a cached method id for provided method name and signature.
39      */
40     jmethodID getMethod(const std::string &name, const std::string &signature);
41 
42   private:
43     MethodHashMap methods;
44   };
45 
46   JavaReferencesCache(JavaReferencesCache const &) = delete;
47 
48   JavaReferencesCache &operator=(JavaReferencesCache const &) = delete;
49 
50   /**
51    * Gets a singleton instance
52    */
53   static std::shared_ptr<JavaReferencesCache> instance();
54 
55   /**
56    * Gets a cached Java class entry.
57    */
58   CachedJClass &getJClass(const std::string &className);
59 
60   /**
61    * Loads predefined set of Java classes and stores them
62    */
63   void loadJClasses(JNIEnv *env);
64 
65 private:
66   JavaReferencesCache() = default;
67 
68   std::unordered_map<std::string, CachedJClass> jClassRegistry;
69 
70   void loadJClass(
71     JNIEnv *env,
72     const std::string &name,
73     const std::vector<std::pair<std::string, std::string>> &methods
74   );
75 };
76 } // namespace expo
77