comparison Plugins/Engine/OrthancPlugins.cpp @ 1630:ffd23c0104af

"/system" URI gives information about the plugins used for storage area and DB back-end
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 21 Sep 2015 13:26:45 +0200
parents 77c4cc4def0f
children eb8fbcf008b5
comparison
equal deleted inserted replaced
1629:bad4772b605c 1630:ffd23c0104af
53 53
54 #include <boost/regex.hpp> 54 #include <boost/regex.hpp>
55 55
56 namespace Orthanc 56 namespace Orthanc
57 { 57 {
58 namespace
59 {
60 class PluginStorageArea : public IStorageArea
61 {
62 private:
63 _OrthancPluginRegisterStorageArea callbacks_;
64
65 void Free(void* buffer) const
66 {
67 if (buffer != NULL)
68 {
69 callbacks_.free(buffer);
70 }
71 }
72
73 public:
74 PluginStorageArea(const _OrthancPluginRegisterStorageArea& callbacks) : callbacks_(callbacks)
75 {
76 }
77
78
79 virtual void Create(const std::string& uuid,
80 const void* content,
81 size_t size,
82 FileContentType type)
83 {
84 OrthancPluginErrorCode error = callbacks_.create
85 (uuid.c_str(), content, size, Plugins::Convert(type));
86
87 if (error != OrthancPluginErrorCode_Success)
88 {
89 throw OrthancException(Plugins::Convert(error));
90 }
91 }
92
93
94 virtual void Read(std::string& content,
95 const std::string& uuid,
96 FileContentType type)
97 {
98 void* buffer = NULL;
99 int64_t size = 0;
100
101 OrthancPluginErrorCode error = callbacks_.read
102 (&buffer, &size, uuid.c_str(), Plugins::Convert(type));
103
104 if (error != OrthancPluginErrorCode_Success)
105 {
106 throw OrthancException(Plugins::Convert(error));
107 }
108
109 try
110 {
111 content.resize(static_cast<size_t>(size));
112 }
113 catch (...)
114 {
115 Free(buffer);
116 throw;
117 }
118
119 if (size > 0)
120 {
121 memcpy(&content[0], buffer, static_cast<size_t>(size));
122 }
123
124 Free(buffer);
125 }
126
127
128 virtual void Remove(const std::string& uuid,
129 FileContentType type)
130 {
131 OrthancPluginErrorCode error = callbacks_.remove
132 (uuid.c_str(), Plugins::Convert(type));
133
134 if (error != OrthancPluginErrorCode_Success)
135 {
136 throw OrthancException(Plugins::Convert(error));
137 }
138 }
139 };
140
141
142 class StorageAreaFactory : public boost::noncopyable
143 {
144 private:
145 SharedLibrary& sharedLibrary_;
146 _OrthancPluginRegisterStorageArea callbacks_;
147
148 public:
149 StorageAreaFactory(SharedLibrary& sharedLibrary,
150 const _OrthancPluginRegisterStorageArea& callbacks) :
151 sharedLibrary_(sharedLibrary),
152 callbacks_(callbacks)
153 {
154 }
155
156 SharedLibrary& GetSharedLibrary()
157 {
158 return sharedLibrary_;
159 }
160
161 IStorageArea* Create() const
162 {
163 return new PluginStorageArea(callbacks_);
164 }
165 };
166 }
167
168
58 struct OrthancPlugins::PImpl 169 struct OrthancPlugins::PImpl
59 { 170 {
60 class RestCallback : public boost::noncopyable 171 class RestCallback : public boost::noncopyable
61 { 172 {
62 private: 173 private:
103 return InvokeInternal(output, flatUri, request); 214 return InvokeInternal(output, flatUri, request);
104 } 215 }
105 } 216 }
106 }; 217 };
107 218
219
108 typedef std::pair<std::string, _OrthancPluginProperty> Property; 220 typedef std::pair<std::string, _OrthancPluginProperty> Property;
109 typedef std::list<RestCallback*> RestCallbacks; 221 typedef std::list<RestCallback*> RestCallbacks;
110 typedef std::list<OrthancPluginOnStoredInstanceCallback> OnStoredCallbacks; 222 typedef std::list<OrthancPluginOnStoredInstanceCallback> OnStoredCallbacks;
111 typedef std::list<OrthancPluginOnChangeCallback> OnChangeCallbacks; 223 typedef std::list<OrthancPluginOnChangeCallback> OnChangeCallbacks;
112 typedef std::map<Property, std::string> Properties; 224 typedef std::map<Property, std::string> Properties;
114 PluginsManager manager_; 226 PluginsManager manager_;
115 ServerContext* context_; 227 ServerContext* context_;
116 RestCallbacks restCallbacks_; 228 RestCallbacks restCallbacks_;
117 OnStoredCallbacks onStoredCallbacks_; 229 OnStoredCallbacks onStoredCallbacks_;
118 OnChangeCallbacks onChangeCallbacks_; 230 OnChangeCallbacks onChangeCallbacks_;
119 bool hasStorageArea_; 231 std::auto_ptr<StorageAreaFactory> storageArea_;
120 _OrthancPluginRegisterStorageArea storageArea_;
121 boost::recursive_mutex restCallbackMutex_; 232 boost::recursive_mutex restCallbackMutex_;
122 boost::recursive_mutex storedCallbackMutex_; 233 boost::recursive_mutex storedCallbackMutex_;
123 boost::recursive_mutex changeCallbackMutex_; 234 boost::recursive_mutex changeCallbackMutex_;
124 boost::recursive_mutex invokeServiceMutex_; 235 boost::recursive_mutex invokeServiceMutex_;
125 Properties properties_; 236 Properties properties_;
127 char** argv_; 238 char** argv_;
128 std::auto_ptr<OrthancPluginDatabase> database_; 239 std::auto_ptr<OrthancPluginDatabase> database_;
129 240
130 PImpl() : 241 PImpl() :
131 context_(NULL), 242 context_(NULL),
132 hasStorageArea_(false),
133 argc_(1), 243 argc_(1),
134 argv_(NULL) 244 argv_(NULL)
135 { 245 {
136 memset(&storageArea_, 0, sizeof(storageArea_));
137 } 246 }
138 }; 247 };
139 248
140 249
141 250
1100 1209
1101 font.Draw(target, p.utf8Text, p.x, p.y, p.r, p.g, p.b); 1210 font.Draw(target, p.utf8Text, p.x, p.y, p.r, p.g, p.b);
1102 } 1211 }
1103 1212
1104 1213
1105 bool OrthancPlugins::InvokeService(_OrthancPluginService service, 1214 bool OrthancPlugins::InvokeService(SharedLibrary& plugin,
1215 _OrthancPluginService service,
1106 const void* parameters) 1216 const void* parameters)
1107 { 1217 {
1108 VLOG(1) << "Calling plugin service: " << service; 1218 VLOG(1) << "Calling service " << service << " from plugin " << plugin.GetPath();
1109 1219
1110 boost::recursive_mutex::scoped_lock lock(pimpl_->invokeServiceMutex_); 1220 boost::recursive_mutex::scoped_lock lock(pimpl_->invokeServiceMutex_);
1111 1221
1112 switch (service) 1222 switch (service)
1113 { 1223 {
1259 { 1369 {
1260 LOG(INFO) << "Plugin has registered a custom storage area"; 1370 LOG(INFO) << "Plugin has registered a custom storage area";
1261 const _OrthancPluginRegisterStorageArea& p = 1371 const _OrthancPluginRegisterStorageArea& p =
1262 *reinterpret_cast<const _OrthancPluginRegisterStorageArea*>(parameters); 1372 *reinterpret_cast<const _OrthancPluginRegisterStorageArea*>(parameters);
1263 1373
1264 pimpl_->storageArea_ = p; 1374 if (pimpl_->storageArea_.get() == NULL)
1265 pimpl_->hasStorageArea_ = true; 1375 {
1376 pimpl_->storageArea_.reset(new StorageAreaFactory(plugin, p));
1377 }
1378 else
1379 {
1380 throw OrthancException(ErrorCode_StorageAreaAlreadyRegistered);
1381 }
1382
1266 return true; 1383 return true;
1267 } 1384 }
1268 1385
1269 case _OrthancPluginService_SetPluginProperty: 1386 case _OrthancPluginService_SetPluginProperty:
1270 { 1387 {
1330 { 1447 {
1331 LOG(INFO) << "Plugin has registered a custom database back-end"; 1448 LOG(INFO) << "Plugin has registered a custom database back-end";
1332 1449
1333 const _OrthancPluginRegisterDatabaseBackend& p = 1450 const _OrthancPluginRegisterDatabaseBackend& p =
1334 *reinterpret_cast<const _OrthancPluginRegisterDatabaseBackend*>(parameters); 1451 *reinterpret_cast<const _OrthancPluginRegisterDatabaseBackend*>(parameters);
1335 pimpl_->database_.reset(new OrthancPluginDatabase(*p.backend, NULL, 0, p.payload)); 1452
1453 if (pimpl_->database_.get() == NULL)
1454 {
1455 pimpl_->database_.reset(new OrthancPluginDatabase(plugin, *p.backend, NULL, 0, p.payload));
1456 }
1457 else
1458 {
1459 throw OrthancException(ErrorCode_DatabaseBackendAlreadyRegistered);
1460 }
1336 1461
1337 *(p.result) = reinterpret_cast<OrthancPluginDatabaseContext*>(pimpl_->database_.get()); 1462 *(p.result) = reinterpret_cast<OrthancPluginDatabaseContext*>(pimpl_->database_.get());
1338 1463
1339 return true; 1464 return true;
1340 } 1465 }
1343 { 1468 {
1344 LOG(INFO) << "Plugin has registered a custom database back-end"; 1469 LOG(INFO) << "Plugin has registered a custom database back-end";
1345 1470
1346 const _OrthancPluginRegisterDatabaseBackendV2& p = 1471 const _OrthancPluginRegisterDatabaseBackendV2& p =
1347 *reinterpret_cast<const _OrthancPluginRegisterDatabaseBackendV2*>(parameters); 1472 *reinterpret_cast<const _OrthancPluginRegisterDatabaseBackendV2*>(parameters);
1348 pimpl_->database_.reset(new OrthancPluginDatabase(*p.backend, p.extensions, p.extensionsSize, p.payload)); 1473
1474 if (pimpl_->database_.get() == NULL)
1475 {
1476 pimpl_->database_.reset(new OrthancPluginDatabase(plugin, *p.backend, p.extensions,
1477 p.extensionsSize, p.payload));
1478 }
1479 else
1480 {
1481 throw OrthancException(ErrorCode_DatabaseBackendAlreadyRegistered);
1482 }
1349 1483
1350 *(p.result) = reinterpret_cast<OrthancPluginDatabaseContext*>(pimpl_->database_.get()); 1484 *(p.result) = reinterpret_cast<OrthancPluginDatabaseContext*>(pimpl_->database_.get());
1351 1485
1352 return true; 1486 return true;
1353 } 1487 }
1354 1488
1355 case _OrthancPluginService_DatabaseAnswer: 1489 case _OrthancPluginService_DatabaseAnswer:
1356 { 1490 {
1357 const _OrthancPluginDatabaseAnswer& p = 1491 const _OrthancPluginDatabaseAnswer& p =
1358 *reinterpret_cast<const _OrthancPluginDatabaseAnswer*>(parameters); 1492 *reinterpret_cast<const _OrthancPluginDatabaseAnswer*>(parameters);
1493
1359 if (pimpl_->database_.get() != NULL) 1494 if (pimpl_->database_.get() != NULL)
1360 { 1495 {
1361 pimpl_->database_->AnswerReceived(p); 1496 pimpl_->database_->AnswerReceived(p);
1362 return true; 1497 return true;
1363 } 1498 }
1543 } 1678 }
1544 1679
1545 1680
1546 bool OrthancPlugins::HasStorageArea() const 1681 bool OrthancPlugins::HasStorageArea() const
1547 { 1682 {
1548 return pimpl_->hasStorageArea_; 1683 return pimpl_->storageArea_.get() != NULL;
1549 } 1684 }
1550 1685
1551 bool OrthancPlugins::HasDatabase() const 1686 bool OrthancPlugins::HasDatabaseBackend() const
1552 { 1687 {
1553 return pimpl_->database_.get() != NULL; 1688 return pimpl_->database_.get() != NULL;
1554 } 1689 }
1555 1690
1556 1691
1557
1558 namespace
1559 {
1560 class PluginStorageArea : public IStorageArea
1561 {
1562 private:
1563 _OrthancPluginRegisterStorageArea params_;
1564
1565 void Free(void* buffer) const
1566 {
1567 if (buffer != NULL)
1568 {
1569 params_.free(buffer);
1570 }
1571 }
1572
1573 public:
1574 PluginStorageArea(const _OrthancPluginRegisterStorageArea& params) : params_(params)
1575 {
1576 }
1577
1578
1579 virtual void Create(const std::string& uuid,
1580 const void* content,
1581 size_t size,
1582 FileContentType type)
1583 {
1584 OrthancPluginErrorCode error = params_.create
1585 (uuid.c_str(), content, size, Plugins::Convert(type));
1586
1587 if (error != OrthancPluginErrorCode_Success)
1588 {
1589 throw OrthancException(Plugins::Convert(error));
1590 }
1591 }
1592
1593
1594 virtual void Read(std::string& content,
1595 const std::string& uuid,
1596 FileContentType type)
1597 {
1598 void* buffer = NULL;
1599 int64_t size = 0;
1600
1601 OrthancPluginErrorCode error = params_.read
1602 (&buffer, &size, uuid.c_str(), Plugins::Convert(type));
1603
1604 if (error != OrthancPluginErrorCode_Success)
1605 {
1606 throw OrthancException(Plugins::Convert(error));
1607 }
1608
1609 try
1610 {
1611 content.resize(static_cast<size_t>(size));
1612 }
1613 catch (...)
1614 {
1615 Free(buffer);
1616 throw;
1617 }
1618
1619 if (size > 0)
1620 {
1621 memcpy(&content[0], buffer, static_cast<size_t>(size));
1622 }
1623
1624 Free(buffer);
1625 }
1626
1627
1628 virtual void Remove(const std::string& uuid,
1629 FileContentType type)
1630 {
1631 OrthancPluginErrorCode error = params_.remove
1632 (uuid.c_str(), Plugins::Convert(type));
1633
1634 if (error != OrthancPluginErrorCode_Success)
1635 {
1636 throw OrthancException(Plugins::Convert(error));
1637 }
1638 }
1639 };
1640 }
1641
1642
1643 IStorageArea* OrthancPlugins::CreateStorageArea() 1692 IStorageArea* OrthancPlugins::CreateStorageArea()
1644 { 1693 {
1645 if (!HasStorageArea()) 1694 if (!HasStorageArea())
1646 { 1695 {
1647 throw OrthancException(ErrorCode_BadSequenceOfCalls); 1696 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1648 } 1697 }
1649 1698 else
1650 return new PluginStorageArea(pimpl_->storageArea_); 1699 {
1651 } 1700 return pimpl_->storageArea_->Create();
1652 1701 }
1653 1702 }
1654 IDatabaseWrapper& OrthancPlugins::GetDatabase() 1703
1655 { 1704
1656 if (!HasDatabase()) 1705 const SharedLibrary& OrthancPlugins::GetStorageAreaLibrary() const
1706 {
1707 if (!HasStorageArea())
1657 { 1708 {
1658 throw OrthancException(ErrorCode_BadSequenceOfCalls); 1709 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1659 } 1710 }
1660 1711 else
1661 return *pimpl_->database_; 1712 {
1662 } 1713 return pimpl_->storageArea_->GetSharedLibrary();
1663 1714 }
1664 1715 }
1665 1716
1717
1718 IDatabaseWrapper& OrthancPlugins::GetDatabaseBackend()
1719 {
1720 if (!HasDatabaseBackend())
1721 {
1722 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1723 }
1724 else
1725 {
1726 return *pimpl_->database_;
1727 }
1728 }
1729
1730
1731 const SharedLibrary& OrthancPlugins::GetDatabaseBackendLibrary() const
1732 {
1733 if (!HasDatabaseBackend())
1734 {
1735 throw OrthancException(ErrorCode_BadSequenceOfCalls);
1736 }
1737 else
1738 {
1739 return pimpl_->database_->GetSharedLibrary();
1740 }
1741 }
1666 1742
1667 1743
1668 const char* OrthancPlugins::GetProperty(const char* plugin, 1744 const char* OrthancPlugins::GetProperty(const char* plugin,
1669 _OrthancPluginProperty property) const 1745 _OrthancPluginProperty property) const
1670 { 1746 {