DCCL v4
dynamic_protobuf_manager.cpp
1 // Copyright 2012-2019:
2 // GobySoft, LLC (2013-)
3 // Massachusetts Institute of Technology (2007-2014)
4 // Community contributors (see AUTHORS file)
5 // File authors:
6 // Toby Schneider <toby@gobysoft.org>
7 // Chris Murphy <cmurphy@aphysci.com>
8 //
9 //
10 // This file is part of the Dynamic Compact Control Language Library
11 // ("DCCL").
12 //
13 // DCCL is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU Lesser General Public License as published by
15 // the Free Software Foundation, either version 2.1 of the License, or
16 // (at your option) any later version.
17 //
18 // DCCL is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU Lesser General Public License for more details.
22 //
23 // You should have received a copy of the GNU Lesser General Public License
24 // along with DCCL. If not, see <http://www.gnu.org/licenses/>.
25 #include <sstream>
26 
27 #include "dynamic_protobuf_manager.h"
28 #include "exception.h"
29 #include "logger.h"
30 
31 std::shared_ptr<dccl::DynamicProtobufManager> dccl::DynamicProtobufManager::inst_;
32 
33 //
34 // STATIC
35 //
36 const google::protobuf::Descriptor*
37 dccl::DynamicProtobufManager::find_descriptor(const std::string& protobuf_type_name,
38  bool user_pool_first)
39 {
40  DCCL_LOCK_DYNAMIC_PROTOBUF_MANAGER_MUTEX
41  const google::protobuf::Descriptor* desc = nullptr;
42  if (user_pool_first)
43  {
44  // try the user pool
45  desc = get_instance()->user_descriptor_pool_->FindMessageTypeByName(protobuf_type_name);
46  if (desc)
47  return desc;
48  }
49 
50  // try the generated pool
51  desc = google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(
52  protobuf_type_name);
53  if (desc)
54  return desc;
55 
56  if (!user_pool_first)
57  {
58  // try the user pool
59  desc = get_instance()->user_descriptor_pool_->FindMessageTypeByName(protobuf_type_name);
60  }
61 
62  return desc;
63 }
64 
65 std::shared_ptr<google::protobuf::Message>
66 dccl::DynamicProtobufManager::new_protobuf_message(const google::protobuf::Descriptor* desc)
67 {
68  DCCL_LOCK_DYNAMIC_PROTOBUF_MANAGER_MUTEX
69  return new_protobuf_message<std::shared_ptr<google::protobuf::Message>>(desc);
70 }
71 
72 std::shared_ptr<google::protobuf::Message>
73 dccl::DynamicProtobufManager::new_protobuf_message(const std::string& protobuf_type_name)
74 {
75  DCCL_LOCK_DYNAMIC_PROTOBUF_MANAGER_MUTEX
76  return new_protobuf_message<std::shared_ptr<google::protobuf::Message>>(protobuf_type_name);
77 }
78 
80  std::shared_ptr<google::protobuf::DescriptorDatabase> database)
81 {
82  DCCL_LOCK_DYNAMIC_PROTOBUF_MANAGER_MUTEX
83  get_instance()->databases_.push_back(database);
84  get_instance()->update_databases();
85 }
86 
88 {
89  DCCL_LOCK_DYNAMIC_PROTOBUF_MANAGER_MUTEX
90 
91  if (!get_instance()->disk_source_tree_)
92  throw(std::runtime_error(
93  "Must called enable_compilation() before loading proto files directly"));
94 
95  get_instance()->disk_source_tree_->MapPath("", path);
96 }
97 
98 void* dccl::DynamicProtobufManager::load_from_shared_lib(const std::string& shared_lib_path)
99 {
100  DCCL_LOCK_DYNAMIC_PROTOBUF_MANAGER_MUTEX
101  void* handle = dlopen(shared_lib_path.c_str(), RTLD_LAZY);
102  if (handle)
103  get_instance()->dl_handles_.push_back(handle);
104  return handle;
105 }
106 
112 const google::protobuf::FileDescriptor*
113 dccl::DynamicProtobufManager::load_from_proto_file(const std::string& protofile_absolute_path)
114 {
115  DCCL_LOCK_DYNAMIC_PROTOBUF_MANAGER_MUTEX
116 
117  if (!get_instance()->source_database_)
118  throw(dccl::Exception(
119  "Must called enable_compilation() before loading proto files directly"));
120 
121  return get_instance()->user_descriptor_pool_->FindFileByName(protofile_absolute_path);
122 }
123 
124 const google::protobuf::FileDescriptor*
125 dccl::DynamicProtobufManager::add_protobuf_file(const google::protobuf::FileDescriptorProto& proto)
126 {
127  DCCL_LOCK_DYNAMIC_PROTOBUF_MANAGER_MUTEX
128  get_instance()->simple_database_->Add(proto);
129 
130  const google::protobuf::FileDescriptor* return_desc =
131  get_instance()->user_descriptor_pool_->FindFileByName(proto.name());
132  return return_desc;
133 }
134 
135 //
136 // NON STATIC
137 //
138 
139 void dccl::DynamicProtobufManager::enable_disk_source_database()
140 {
141  if (disk_source_tree_)
142  return;
143 
144  disk_source_tree_.reset(new google::protobuf::compiler::DiskSourceTree);
145  source_database_.reset(
146  new google::protobuf::compiler::SourceTreeDescriptorDatabase(disk_source_tree_.get()));
147  error_collector_.reset(new DLogMultiFileErrorCollector);
148 
149  source_database_->RecordErrorsTo(error_collector_.get());
150  disk_source_tree_->MapPath("/", "/");
151  disk_source_tree_->MapPath("", "");
152  add_database(source_database_);
153 }
154 
155 // DLogMultiFileErrorCollector
156 void dccl::DynamicProtobufManager::DLogMultiFileErrorCollector::AddError(
157  const std::string& filename, int line, int column, const std::string& message)
158 {
159  std::stringstream ss;
160  ss << "File: " << filename << " has error (line: " << line << ", column: " << column
161  << "):" << message;
162 
163  throw(dccl::Exception(ss.str()));
164 }
dccl::DynamicProtobufManager::add_protobuf_file
static const google::protobuf::FileDescriptor * add_protobuf_file(const google::protobuf::FileDescriptorProto &proto)
Add a protobuf file defined in a google::protobuf::FileDescriptorProto.
Definition: dynamic_protobuf_manager.cpp:125
dccl::Exception
Exception class for DCCL.
Definition: exception.h:47
dccl::DynamicProtobufManager::load_from_shared_lib
static void * load_from_shared_lib(const std::string &shared_lib_path)
Load compiled .proto files from a UNIX shared library (i.e. *.so or *.dylib)
Definition: dynamic_protobuf_manager.cpp:98
dccl::DynamicProtobufManager::add_database
static void add_database(std::shared_ptr< google::protobuf::DescriptorDatabase > database)
Add a Google Protobuf DescriptorDatabase to the set of databases searched for Message Descriptors.
Definition: dynamic_protobuf_manager.cpp:79
dccl::DynamicProtobufManager::load_from_proto_file
static const google::protobuf::FileDescriptor * load_from_proto_file(const std::string &protofile_absolute_path)
Load a message from a .proto file on the disk. enable_compilation() must be called first.
Definition: dynamic_protobuf_manager.cpp:113
dccl::DynamicProtobufManager::add_include_path
static void add_include_path(const std::string &path)
Add a path for searching for import messages when loading .proto files using load_from_proto_file()
Definition: dynamic_protobuf_manager.cpp:87
dccl::DynamicProtobufManager::new_protobuf_message
static GoogleProtobufMessagePointer new_protobuf_message(const std::string &protobuf_type_name, bool user_pool_first=false)
Create a new (empty) Google Protobuf message of a given type by name.
Definition: dynamic_protobuf_manager.h:77
dccl::DynamicProtobufManager::find_descriptor
static const google::protobuf::Descriptor * find_descriptor(const std::string &protobuf_type_name, bool user_pool_first=false)
Finds the Google Protobuf Descriptor (essentially a meta-class for a given Message) from a given Mess...
Definition: dynamic_protobuf_manager.cpp:37