// ********************************************************************** // // Copyright (c) 2002 // ZeroC, Inc. // Billerica, MA, USA // // All Rights Reserved. // // Ice is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License version 2 as published by // the Free Software Foundation. // // ********************************************************************** #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace Ice; using namespace IceInternal; IceInternal::IncomingBase::IncomingBase(Instance* instance, Connection* connection, const ObjectAdapterPtr& adapter, bool response) : _connection(connection), _response(response), _is(instance), _os(instance) { _current.adapter = adapter; } IceInternal::IncomingBase::IncomingBase(IncomingBase& in) : _current(in._current), _servant(in._servant), _locator(in._locator), _cookie(in._cookie), _connection(in._connection), _response(in._response), _is(in._is.instance()), _os(in._os.instance()) { _is.swap(in._is); _os.swap(in._os); } void IceInternal::IncomingBase::__finishInvoke() { if(_locator && _servant) { _locator->finished(_current, _servant, _cookie); } _is.endReadEncaps(); // // Send a response if necessary. If we don't need to send a // response, we still need to tell the connection that we're // finished with dispatching. // if(_response) { _connection->sendResponse(&_os); } else { _connection->sendNoResponse(); } } void IceInternal::IncomingBase::__warning(const Exception& ex) const { ostringstream str; str << ex; __warning(str.str()); } void IceInternal::IncomingBase::__warning(const string& msg) const { if(_os.instance()->properties()->getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0) { Warning out(_os.instance()->logger()); out << "dispatch exception: " << msg; out << "\nidentity: " << _current.id; out << "\nfacet: "; vector::const_iterator p = _current.facet.begin(); while(p != _current.facet.end()) { out << encodeString(*p++, "/"); if(p != _current.facet.end()) { out << '/'; } } out << "\noperation: " << _current.operation; } } IceInternal::Incoming::Incoming(Instance* instance, Connection* connection, const ObjectAdapterPtr& adapter, bool response) : IncomingBase(instance, connection, adapter, response) { } void IceInternal::Incoming::invoke(const ServantManagerPtr& servantManager) { // // Read the current. // _current.id.__read(&_is); _is.read(_current.facet); _is.read(_current.operation); Byte b; _is.read(b); _current.mode = static_cast(b); Int sz; _is.readSize(sz); while(sz--) { pair pr; _is.read(pr.first); _is.read(pr.second); _current.ctx.insert(_current.ctx.end(), pr); } _is.startReadEncaps(); if(_response) { assert(_os.b.size() == headerSize + 4); // Dispatch status position. _os.write(static_cast(0)); _os.startWriteEncaps(); } DispatchStatus status; // // Don't put the code above into the try block below. Exceptions // in the code above are considered fatal, and must propagate to // the caller of this operation. // try { if(servantManager) { _servant = servantManager->findServant(_current.id); if(!_servant && !_current.id.category.empty()) { _locator = servantManager->findServantLocator(_current.id.category); if(_locator) { _servant = _locator->locate(_current, _cookie); } } if(!_servant) { _locator = servantManager->findServantLocator(""); if(_locator) { _servant = _locator->locate(_current, _cookie); } } } if(!_servant) { status = DispatchObjectNotExist; } else { if(!_current.facet.empty()) { ObjectPtr facetServant = _servant->ice_findFacetPath(_current.facet, 0); if(!facetServant) { status = DispatchFacetNotExist; } else { status = facetServant->__dispatch(*this, _current); } } else { status = _servant->__dispatch(*this, _current); } // // In case of an asynchronous dispatch, _is is now empty, // because an IncomingAsync has adopted this Incoming. // if(_is.b.empty()) { // // If this was an asynchronous dispatch, we're done // here. We do *not* call __finishInvoke(), because the // call is not finished yet. // assert(status == DispatchOK); return; } } } catch(RequestFailedException& ex) { if(ex.id.name.empty()) { ex.id = _current.id; } if(ex.facet.empty() && !_current.facet.empty()) { ex.facet = _current.facet; } if(ex.operation.empty() && !_current.operation.empty()) { ex.operation = _current.operation; } __warning(ex); if(_response) { _os.endWriteEncaps(); _os.b.resize(headerSize + 4); // Dispatch status position. if(dynamic_cast(&ex)) { _os.write(static_cast(DispatchObjectNotExist)); } else if(dynamic_cast(&ex)) { _os.write(static_cast(DispatchFacetNotExist)); } else if(dynamic_cast(&ex)) { _os.write(static_cast(DispatchOperationNotExist)); } else { assert(false); } ex.id.__write(&_os); _os.write(ex.facet); _os.write(ex.operation); } __finishInvoke(); return; } catch(const LocalException& ex) { __warning(ex); if(_response) { _os.endWriteEncaps(); _os.b.resize(headerSize + 4); // Dispatch status position. _os.write(static_cast(DispatchUnknownLocalException)); ostringstream str; str << ex; _os.write(str.str()); } __finishInvoke(); return; } catch(const UserException& ex) { __warning(ex); if(_response) { _os.endWriteEncaps(); _os.b.resize(headerSize + 4); // Dispatch status position. _os.write(static_cast(DispatchUnknownUserException)); ostringstream str; str << ex; _os.write(str.str()); } __finishInvoke(); return; } catch(const Exception& ex) { __warning(ex); if(_response) { _os.endWriteEncaps(); _os.b.resize(headerSize + 4); // Dispatch status position. _os.write(static_cast(DispatchUnknownException)); ostringstream str; str << ex; _os.write(str.str()); } __finishInvoke(); return; } catch(const std::exception& ex) { __warning(string("std::exception: ") + ex.what()); if(_response) { _os.endWriteEncaps(); _os.b.resize(headerSize + 4); // Dispatch status position. _os.write(static_cast(DispatchUnknownException)); ostringstream str; str << "std::exception: " << ex.what(); _os.write(str.str()); } __finishInvoke(); return; } catch(...) { __warning("unknown c++ exception"); if(_response) { _os.endWriteEncaps(); _os.b.resize(headerSize + 4); // Dispatch status position. _os.write(static_cast(DispatchUnknownException)); string reason = "unknown c++ exception"; _os.write(reason); } __finishInvoke(); return; } // // Don't put the code below into the try block above. Exceptions // in the code below are considered fatal, and must propagate to // the caller of this operation. // if(_response) { _os.endWriteEncaps(); if(status != DispatchOK && status != DispatchUserException) { assert(status == DispatchObjectNotExist || status == DispatchFacetNotExist || status == DispatchOperationNotExist); _os.b.resize(headerSize + 4); // Dispatch status position. _os.write(static_cast(status)); _current.id.__write(&_os); _os.write(_current.facet); _os.write(_current.operation); } else { *(_os.b.begin() + headerSize + 4) = static_cast(status); // Dispatch status position. } } __finishInvoke(); }