/py/modules/IcePy/ObjectFactory.cpp

https://bitbucket.org/cleto/zeroc-ice-package · C++ · 196 lines · 134 code · 28 blank · 34 comment · 19 complexity · 7ced64a5a44194535755d945f06fa812 MD5 · raw file

  1. // **********************************************************************
  2. //
  3. // Copyright (c) 2003-2013 ZeroC, Inc. All rights reserved.
  4. //
  5. // This copy of Ice is licensed to you under the terms described in the
  6. // ICE_LICENSE file included in this distribution.
  7. //
  8. // **********************************************************************
  9. #ifdef _WIN32
  10. # include <IceUtil/Config.h>
  11. #endif
  12. #include <ObjectFactory.h>
  13. #include <Thread.h>
  14. #include <Types.h>
  15. #include <Util.h>
  16. #include <Ice/LocalException.h>
  17. using namespace std;
  18. using namespace IcePy;
  19. IcePy::ObjectFactory::ObjectFactory()
  20. {
  21. }
  22. IcePy::ObjectFactory::~ObjectFactory()
  23. {
  24. assert(_factoryMap.empty());
  25. }
  26. Ice::ObjectPtr
  27. IcePy::ObjectFactory::create(const string& id)
  28. {
  29. PyObject* factory = 0;
  30. //
  31. // Check if the application has registered a factory for this id.
  32. //
  33. {
  34. Lock sync(*this);
  35. FactoryMap::iterator p = _factoryMap.find(id);
  36. if(p != _factoryMap.end())
  37. {
  38. factory = p->second;
  39. }
  40. }
  41. //
  42. // Get the type information.
  43. //
  44. ClassInfoPtr info;
  45. if(id == Ice::Object::ice_staticId())
  46. {
  47. //
  48. // When the ID is that of Ice::Object, it indicates that the stream has not
  49. // found a factory and is providing us an opportunity to preserve the object.
  50. //
  51. info = lookupClassInfo("::Ice::UnknownSlicedObject");
  52. }
  53. else
  54. {
  55. info = lookupClassInfo(id);
  56. }
  57. if(!info)
  58. {
  59. return 0;
  60. }
  61. if(factory)
  62. {
  63. //
  64. // Invoke the create method on the Python factory object.
  65. //
  66. PyObjectHandle obj = PyObject_CallMethod(factory, STRCAST("create"), STRCAST("s"), id.c_str());
  67. if(!obj.get())
  68. {
  69. assert(PyErr_Occurred());
  70. throw AbortMarshaling();
  71. }
  72. if(obj.get() == Py_None)
  73. {
  74. return 0;
  75. }
  76. return new ObjectReader(obj.get(), info);
  77. }
  78. //
  79. // If the requested type is an abstract class, then we give up.
  80. //
  81. if(info->isAbstract)
  82. {
  83. return 0;
  84. }
  85. //
  86. // Instantiate the object.
  87. //
  88. PyTypeObject* type = reinterpret_cast<PyTypeObject*>(info->pythonType.get());
  89. PyObjectHandle args = PyTuple_New(0);
  90. PyObjectHandle obj = type->tp_new(type, args.get(), 0);
  91. if(!obj.get())
  92. {
  93. assert(PyErr_Occurred());
  94. throw AbortMarshaling();
  95. }
  96. return new ObjectReader(obj.get(), info);
  97. }
  98. void
  99. IcePy::ObjectFactory::destroy()
  100. {
  101. FactoryMap factories;
  102. {
  103. Lock sync(*this);
  104. factories = _factoryMap;
  105. _factoryMap.clear();
  106. }
  107. //
  108. // We release the GIL before calling communicator->destroy(), so we must
  109. // reacquire it before calling back into Python.
  110. //
  111. AdoptThread adoptThread;
  112. for(FactoryMap::iterator p = factories.begin(); p != factories.end(); ++p)
  113. {
  114. //
  115. // Invoke the destroy method on each registered Python factory.
  116. //
  117. PyObjectHandle obj = PyObject_CallMethod(p->second, STRCAST("destroy"), 0);
  118. PyErr_Clear(); // Ignore errors.
  119. Py_DECREF(p->second);
  120. }
  121. }
  122. bool
  123. IcePy::ObjectFactory::add(PyObject* factory, const string& id)
  124. {
  125. Lock sync(*this);
  126. FactoryMap::iterator p = _factoryMap.find(id);
  127. if(p != _factoryMap.end())
  128. {
  129. Ice::AlreadyRegisteredException ex(__FILE__, __LINE__);
  130. ex.kindOfObject = "object factory";
  131. ex.id = id;
  132. setPythonException(ex);
  133. return false;
  134. }
  135. _factoryMap.insert(FactoryMap::value_type(id, factory));
  136. Py_INCREF(factory);
  137. return true;
  138. }
  139. bool
  140. IcePy::ObjectFactory::remove(const string& id)
  141. {
  142. Lock sync(*this);
  143. FactoryMap::iterator p = _factoryMap.find(id);
  144. if(p == _factoryMap.end())
  145. {
  146. Ice::NotRegisteredException ex(__FILE__, __LINE__);
  147. ex.kindOfObject = "object factory";
  148. ex.id = id;
  149. setPythonException(ex);
  150. return false;
  151. }
  152. Py_DECREF(p->second);
  153. _factoryMap.erase(p);
  154. return true;
  155. }
  156. PyObject*
  157. IcePy::ObjectFactory::find(const string& id)
  158. {
  159. Lock sync(*this);
  160. FactoryMap::iterator p = _factoryMap.find(id);
  161. if(p == _factoryMap.end())
  162. {
  163. Py_INCREF(Py_None);
  164. return Py_None;
  165. }
  166. Py_INCREF(p->second);
  167. return p->second;
  168. }