listener.C

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
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           // Fetch the root naming context
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 }

Generated on Sun Jul 30 22:55:48 2006 for Archon by  doxygen 1.4.4