00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <archon/util/cxx_demangle.H>
00021 #include <archon/util/mutex.H>
00022
00023 #include <archon/x3d/sai/listener.H>
00024
00025 #define CORBA_ENTRY_D(x) try { listener->x; } \
00026 catch(CORBA::UserException &) { throw; } \
00027 catch(ForwardDestroyedException &) {} \
00028 catch(...) { string m = SAI::exceptionCatchShortExplanation(); \
00029 throw x3d::sai::ServerErrorException(m.c_str()); }
00030
00031 #define CORBA_ENTRY_V(x) try { listener->x; } \
00032 catch(CORBA::UserException &) { throw; } \
00033 catch(ForwardDestroyedException &) \
00034 { throw x3d::sai::InvalidSessionException(); } \
00035 catch(...) { string m = SAI::exceptionCatchShortExplanation(); \
00036 throw x3d::sai::ServerErrorException(m.c_str()); }
00037
00038 #define CORBA_ENTRY_R(x) try { return listener->x; } \
00039 catch(CORBA::UserException &) { throw; } \
00040 catch(ForwardDestroyedException &) \
00041 { throw x3d::sai::InvalidSessionException(); } \
00042 catch(...) { string m = SAI::exceptionCatchShortExplanation(); \
00043 throw x3d::sai::ServerErrorException(m.c_str()); }
00044
00045 namespace Archon
00046 {
00047 namespace X3D
00048 {
00049 namespace SAI
00050 {
00051 struct Listener::Servant:
00052 POA_x3d::sai::Server, PortableServer::RefCountServantBase
00053 {
00054 const BackRef<Listener> listener;
00055
00056 Servant(Ref<Listener> listener): listener(listener) {}
00057
00058 CORBA::ULong getNodeTypeBitsInId()
00059 {
00060 CORBA_ENTRY_R(getNodeTypeBitsInId());
00061 }
00062
00063 CORBA::ULong getNodeType(const char *typeName)
00064 {
00065 CORBA_ENTRY_R(getNodeType(typeName));
00066 }
00067
00068 CORBA::ULong getImmediateField(CORBA::ULong nodeTypeId,
00069 const char *fieldName)
00070 {
00071 CORBA_ENTRY_R(getImmediateField(nodeTypeId, fieldName));
00072 }
00073
00074 x3d::sai::Session_ptr createSession(x3d::sai::Application_ptr a)
00075 {
00076 CORBA_ENTRY_R(createSession(a));
00077 }
00078 };
00079
00080
00081 Listener::Listener(Ref<Server> server,
00082 Time applicationHeartbeat,
00083 int corbaEndpointPort):
00084 server(server),
00085 applicationHeartbeat(applicationHeartbeat),
00086 orb(corbaEndpointPort), active(false)
00087 {
00088 }
00089
00090 Listener::~Listener()
00091 {{
00092 }}
00093
00094 void Listener::activate() throw(NameServerException)
00095 {
00096 if(active) return;
00097 ServantRef<Servant> servant = new Servant(this);
00098 servantId = orb.getPoa()->activate_object(servant.get());
00099 x3d::sai::Server_var ref = servant->_this();
00100
00101 CosNaming::NamingContext_var context;
00102 CosNaming::Name label;
00103 label.length(1);
00104
00105 try
00106 {
00107
00108 CORBA::Object_var obj =
00109 orb.getCorbaOrb()->resolve_initial_references("NameService");
00110 context = CosNaming::NamingContext::_narrow(obj);
00111 if(CORBA::is_nil(context))
00112 ARCHON_THROW1(NameServerException,
00113 "CORBA naming service is not available1.");
00114 }
00115 catch(CORBA::Exception &e)
00116 {
00117 ARCHON_THROW1(NameServerException,
00118 "CORBA naming service is not available.");
00119 }
00120
00121 try
00122 {
00123 label[0].id = "x3d";
00124 context = context->bind_new_context(label);
00125 }
00126 catch(CosNaming::NamingContext::AlreadyBound &ex)
00127 {
00128 CORBA::Object_var obj = context->resolve(label);
00129 context = CosNaming::NamingContext::_narrow(obj);
00130 if(CORBA::is_nil(context))
00131 ARCHON_THROW1(NameServerException,
00132 "'/x3d.context' is not a naming context.");
00133 }
00134
00135 try
00136 {
00137 label[0].id = "sai";
00138 context = context->bind_new_context(label);
00139 }
00140 catch(CosNaming::NamingContext::AlreadyBound &ex)
00141 {
00142 CORBA::Object_var obj = context->resolve(label);
00143 context = CosNaming::NamingContext::_narrow(obj);
00144 if(CORBA::is_nil(context))
00145 ARCHON_THROW1(NameServerException,
00146 "'/x3d.context/sai.context' is not a naming "
00147 "context.");
00148 }
00149
00150 string name = server->getName();
00151 label[0].id = name.c_str();
00152 try
00153 {
00154 context->bind(label, ref);
00155 }
00156 catch(CosNaming::NamingContext::AlreadyBound &)
00157 {
00158 CORBA::Object_var boundObj = context->resolve(label);
00159 for(;;)
00160 {
00161 try
00162 {
00163 if(boundObj->_non_existent()) break;
00164 }
00165 catch(CORBA::Exception &) { break; }
00166 ARCHON_THROW1(NameServerException,
00167 "'/x3d.context/sai.context/" +
00168 name + ".object' is in use.");
00169 }
00170 context->rebind(label, ref);
00171 }
00172
00173 active = true;
00174 }
00175
00176 void Listener::deactivate()
00177 {
00178 if(!active) return;
00179 orb.getPoa()->deactivate_object(servantId);
00180 active = false;
00181 }
00182
00183 void Listener::startServingClientRequests(Ref<GroupingNode> applicationContainer)
00184 throw(NameServerException)
00185 {
00186 Mutex::Lock lock(mutex);
00187 this->applicationContainer = applicationContainer;
00188 activate();
00189 }
00190
00191 CORBA::ULong Listener::getNodeTypeBitsInId()
00192 {
00193 return NodeType::maxIndexBits;
00194 }
00195
00196 CORBA::ULong Listener::getNodeType(const char *n)
00197 {
00198 const NodeType *t = NodeType::lookup(n);
00199 if(!t) throw x3d::sai::InvalidNameException();
00200 return t->getIndex();
00201 }
00202
00203 CORBA::ULong Listener::getImmediateField(CORBA::ULong ti, const char *n)
00204 {
00205 if(ti >= NodeType::getTotalNumber())
00206 throw x3d::sai::InvalidTypeException();
00207 const NodeType *t = NodeType::get(ti);
00208 const FieldBase *f = t->lookupImmediateField(n);
00209 if(!f) throw x3d::sai::InvalidNameException();
00210 return f->getId();
00211 }
00212
00213 x3d::sai::Session_ptr Listener::
00214 createSession(x3d::sai::Application_ptr a)
00215 {
00216 Ref<Session> session = new Session(this, a);
00217 x3d::sai::Session_var ref =
00218 session->createServant(applicationHeartbeat);
00219 {
00220 Mutex::Lock lock(mutex);
00221 sessions.push_back(session);
00222 }
00223 return ref._retn();
00224 }
00225
00226 void Listener::removeSession(Ref<Session> s)
00227 {
00228 Mutex::Lock lock(mutex);
00229 sessions.remove(s);
00230 }
00231
00232 void Listener::refForwardDestroy()
00233 {
00234 deactivate();
00235 sessions.clear();
00236 applicationContainer.reset();
00237 }
00238 }
00239 }
00240 }