Mercurial > hg > orthanc
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 { |