// ********************************************************************** // // Copyright (c) 2003 - 2004 // ZeroC, Inc. // North Palm Beach, FL, USA // // All Rights Reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #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, Byte compress) : _response(response), _compress(compress), _os(instance), _connection(connection) { _current.adapter = adapter; } IceInternal::IncomingBase::IncomingBase(IncomingBase& in) : _current(in._current), _servant(in._servant), _locator(in._locator), _cookie(in._cookie), _response(in._response), _compress(in._compress), _os(in._os.instance()), _connection(in._connection) { _os.swap(in._os); } void IceInternal::IncomingBase::__finishInvoke() { if(_locator && _servant) { _locator->finished(_current, _servant, _cookie); } // // 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, _compress); } 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 { Warning out(_os.instance()->logger()); out << "dispatch exception: " << msg; out << "\nidentity: " << _current.id; out << "\nfacet: " << IceUtil::escapeString(_current.facet, ""); out << "\noperation: " << _current.operation; } IceInternal::Incoming::Incoming(Instance* instance, Connection* connection, const ObjectAdapterPtr& adapter, bool response, Byte compress) : IncomingBase(instance, connection, adapter, response, compress), _is(instance) { } void IceInternal::Incoming::invoke(const ServantManagerPtr& servantManager) { // // Read the current. // _current.id.__read(&_is); // // For compatibility with the old FacetPath. // vector facetPath; _is.read(facetPath); string facet; if(!facetPath.empty()) // TODO: Throw an exception if facetPath has more than one element? { facet.swap(facetPath[0]); } _current.facet.swap(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(const_cast(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, _current.facet); 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) { if(servantManager->hasServant(_current.id)) { status = DispatchFacetNotExist; } else { status = DispatchObjectNotExist; } } else { status = _servant->__dispatch(*this, _current); } } catch(RequestFailedException& ex) { _is.endReadEncaps(); 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; } if(_os.instance()->properties()->getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 1) { __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); // // For compatibility with the old FacetPath. // if(ex.facet.empty()) { _os.write(vector()); } else { vector facetPath; facetPath.push_back(ex.facet); _os.write(facetPath); } _os.write(ex.operation); } // // Must be called last, so that if an exception is raised, // this function is definitely *not* called. // __finishInvoke(); return; } catch(const LocalException& ex) { _is.endReadEncaps(); if(_os.instance()->properties()->getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0) { __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()); } // // Must be called last, so that if an exception is raised, // this function is definitely *not* called. // __finishInvoke(); return; } catch(const UserException& ex) { _is.endReadEncaps(); if(_os.instance()->properties()->getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0) { __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()); } // // Must be called last, so that if an exception is raised, // this function is definitely *not* called. // __finishInvoke(); return; } catch(const Exception& ex) { _is.endReadEncaps(); if(_os.instance()->properties()->getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0) { __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()); } // // Must be called last, so that if an exception is raised, // this function is definitely *not* called. // __finishInvoke(); return; } catch(const std::exception& ex) { _is.endReadEncaps(); if(_os.instance()->properties()->getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0) { __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()); } // // Must be called last, so that if an exception is raised, // this function is definitely *not* called. // __finishInvoke(); return; } catch(...) { _is.endReadEncaps(); if(_os.instance()->properties()->getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0) { __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); } // // Must be called last, so that if an exception is raised, // this function is definitely *not* called. // __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. // _is.endReadEncaps(); // // DispatchAsync is "pseudo dispatch status", used internally only // to indicate async dispatch. // if(status == DispatchAsync) { // // If this was an asynchronous dispatch, we're done here. We // do *not* call __finishInvoke(), because the call is not // finished yet. // return; } 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); // // For compatibility with the old FacetPath. // if(_current.facet.empty()) { _os.write(vector()); } else { vector facetPath; facetPath.push_back(_current.facet); _os.write(facetPath); } _os.write(_current.operation); } else { *(_os.b.begin() + headerSize + 4) = static_cast(status); // Dispatch status position. } } // // Must be called last, so that if an exception is raised, // this function is definitely *not* called. // __finishInvoke(); }