diff options
author | Jose <jose@zeroc.com> | 2009-10-02 02:23:52 +0200 |
---|---|---|
committer | Jose <jose@zeroc.com> | 2009-10-02 02:23:52 +0200 |
commit | 1d9f29e281770ecdad4a245271f2b828bd64a32f (patch) | |
tree | ac083f28b06a444e484c24f8fcf1b12a36202c84 | |
parent | Updated demo README (diff) | |
download | ice-1d9f29e281770ecdad4a245271f2b828bd64a32f.tar.bz2 ice-1d9f29e281770ecdad4a245271f2b828bd64a32f.tar.xz ice-1d9f29e281770ecdad4a245271f2b828bd64a32f.zip |
3772. Recovering from Glacier2 / Ice router session failure.
79 files changed, 7756 insertions, 719 deletions
diff --git a/cpp/demo/Glacier2/callback/Client.cpp b/cpp/demo/Glacier2/callback/Client.cpp index 4c1416db640..4c744819014 100644 --- a/cpp/demo/Glacier2/callback/Client.cpp +++ b/cpp/demo/Glacier2/callback/Client.cpp @@ -10,44 +10,20 @@ #include <IceUtil/IceUtil.h> #include <Ice/Ice.h> #include <Glacier2/Router.h> +#include <Glacier2/Application.h> #include <CallbackI.h> using namespace std; using namespace Demo; -class PingTask : public IceUtil::TimerTask -{ -public: - - PingTask(const Glacier2::RouterPrx& router) : - _router(router) - { - } - - virtual void runTimerTask() - { - try - { - _router->refreshSession(); - } - catch(const Ice::Exception&) - { - // Ignore - } - } - -private: - - const Glacier2::RouterPrx _router; -}; - -class CallbackClient : public Ice::Application +class CallbackClient : public Glacier2::Application { public: CallbackClient(); - - virtual int run(int, char*[]); + + virtual int runWithSession(int, char**); + virtual Glacier2::SessionPrx createSession(); }; int @@ -78,34 +54,15 @@ CallbackClient::CallbackClient() : // Since this is an interactive demo we don't want any signal // handling. // - Ice::Application(Ice::NoSignalHandling) + Glacier2::Application(Ice::NoSignalHandling) { } -int -CallbackClient::run(int argc, char* argv[]) +Glacier2::SessionPrx +CallbackClient::createSession() { - if(argc > 1) - { - cerr << appName() << ": too many arguments" << endl; - return EXIT_FAILURE; - } - - Ice::RouterPrx defaultRouter = communicator()->getDefaultRouter(); - if(!defaultRouter) - { - cerr << argv[0] << ": no default router set" << endl; - return EXIT_FAILURE; - } - - Glacier2::RouterPrx router = Glacier2::RouterPrx::checkedCast(defaultRouter); - if(!router) - { - cerr << argv[0] << ": configured router is not a Glacier2 router" << endl; - return EXIT_FAILURE; - } - - while(true) + Glacier2::SessionPrx session; + while(true) { cout << "This demo accepts any user-id / password combination.\n"; @@ -122,21 +79,32 @@ CallbackClient::run(int argc, char* argv[]) #if defined(__BCPLUSPLUS__) && (__BCPLUSPLUS__ >= 0x0600) IceUtil::DummyBCC dummy; #endif - router->createSession(id, pw); + router()->createSession(id, pw); break; } catch(const Glacier2::PermissionDeniedException& ex) { cout << "permission denied:\n" << ex.reason << endl; } + catch(const Glacier2::CannotCreateSessionException ex) + { + cout << "cannot create session:\n" << ex.reason << endl; + } } + return session; +} - IceUtil::TimerPtr timer = new IceUtil::Timer(); - timer->scheduleRepeated(new PingTask(router), IceUtil::Time::milliSeconds(router->getSessionTimeout() * 500)); +int +CallbackClient::runWithSession(int argc, char* argv[]) +{ + if(argc > 1) + { + cerr << appName() << ": too many arguments" << endl; + return EXIT_FAILURE; + } - Ice::Identity callbackReceiverIdent; - callbackReceiverIdent.name = "callbackReceiver"; - callbackReceiverIdent.category = router->getCategoryForClient(); + Ice::Identity callbackReceiverIdent = createCallbackIdentity("callbackReceiver"); + Ice::Identity callbackReceiverFakeIdent; callbackReceiverFakeIdent.name = "callbackReceiver"; callbackReceiverFakeIdent.category = "fake"; @@ -146,12 +114,13 @@ CallbackClient::run(int argc, char* argv[]) CallbackPrx oneway = CallbackPrx::uncheckedCast(twoway->ice_oneway()); CallbackPrx batchOneway = CallbackPrx::uncheckedCast(twoway->ice_batchOneway()); - Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapterWithRouter("Callback.Client", defaultRouter); - adapter->add(new CallbackReceiverI, callbackReceiverIdent); - adapter->add(new CallbackReceiverI, callbackReceiverFakeIdent); // Should never be called for the fake identity. - adapter->activate(); + objectAdapter()->add(new CallbackReceiverI, callbackReceiverIdent); + + // Should never be called for the fake identity. + objectAdapter()->add(new CallbackReceiverI, callbackReceiverFakeIdent); - CallbackReceiverPrx twowayR = CallbackReceiverPrx::uncheckedCast(adapter->createProxy(callbackReceiverIdent)); + CallbackReceiverPrx twowayR = CallbackReceiverPrx::uncheckedCast( + objectAdapter()->createProxy(callbackReceiverIdent)); CallbackReceiverPrx onewayR = CallbackReceiverPrx::uncheckedCast(twowayR->ice_oneway()); string override; @@ -256,27 +225,6 @@ CallbackClient::run(int argc, char* argv[]) } while(cin.good() && c != 'x'); - // - // Destroy the timer before the router session is destroyed, - // otherwise it might get a spurious ObjectNotExistException. - // - timer->destroy(); - - try - { - router->destroySession(); - } - catch(const Glacier2::SessionNotExistException& ex) - { - cerr << ex << endl; - } - catch(const Ice::ConnectionLostException&) - { - // - // Expected: the router closed the connection. - // - } - return EXIT_SUCCESS; } diff --git a/cpp/demo/Glacier2/callback/expect.py b/cpp/demo/Glacier2/callback/expect.py index 7085c18ada9..bebd86b2115 100755 --- a/cpp/demo/Glacier2/callback/expect.py +++ b/cpp/demo/Glacier2/callback/expect.py @@ -24,8 +24,6 @@ from demoscript.Glacier2 import callback server = Util.spawn('./server --Ice.PrintAdapterReady') server.expect('.* ready') -sessionserver = Util.spawn('./sessionserver --Ice.PrintAdapterReady') -sessionserver.expect('.* ready') glacier2 = Util.spawn('glacier2router --Ice.Config=config.glacier2 --Ice.PrintAdapterReady --Glacier2.SessionTimeout=5') glacier2.expect('Glacier2.Client ready') @@ -33,4 +31,4 @@ glacier2.expect('Glacier2.Server ready') client = Util.spawn('./client') -callback.run(client, server, sessionserver, glacier2) +callback.run(client, server, glacier2) diff --git a/cpp/include/Glacier2/Application.h b/cpp/include/Glacier2/Application.h new file mode 100644 index 00000000000..6519ce7cc88 --- /dev/null +++ b/cpp/include/Glacier2/Application.h @@ -0,0 +1,222 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. 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 <exception> + +#include <Ice/Application.h> + +#include <Glacier2/Session.h> +#include <Glacier2/Router.h> + +namespace Glacier2 +{ + +/** + * + * This exception is raised if the session should be restarted. + * + **/ +class GLACIER2_API RestartSessionException : public IceUtil::Exception +{ +public: + + virtual std::string ice_name() const; + virtual Exception* ice_clone() const; + virtual void ice_throw() const; +}; + +/** + * An extension of Ice.Application that makes it easy to write + * Glacier2 applications. + * + * <p> Applications must create a derived class that implements the + * {@link #createSession} and {@link #runWithSession} methods.<p> + * + * The base class invokes {@link #createSession} to create a new + * Glacier2 session and then invokes {@link #runWithSession} in + * which the subclass performs its application logic. The base class + * automatically destroys the session when {@link #runWithSession} + * returns. + * + * If {@link #runWithSession} calls {@link #restart} or raises any of + * the exceptions Ice.ConnectionRefusedException, + * Ice.ConnectionLostException, Ice.UnknownLocalException, + * Ice.RequestFailedException, or Ice.TimeoutException, the base + * class destroys the current session and restarts the application + * with another call to {@link #createSession} followed by + * {@link #runWithSession}. + * + * The application can optionally override the {@link #sessionDestroyed} + * callback method if it needs to take action when connectivity with + * the Glacier2 router is lost. + * + * A program can contain only one instance of this class. + * + * @see Ice.Application + * @see Glacier2.Router + * @see Glacier2.Session + * @see Ice.Communicator + * @see Ice.Logger + * @see #runWithSession + **/ + +class GLACIER2_API Application : public Ice::Application +{ + /** + * Initializes an instance that calls {@link Communicator#shutdown} if + * a signal is received. + **/ +public: + + Application() + { + } + + /** + * Initializes an instance that handles signals according to the signal + * policy. + * + * @param signalPolicy Determines how to respond to signals. + * + * @see SignalPolicy + **/ + Application(Ice::SignalPolicy signalPolicy) : Ice::Application(signalPolicy) + { + } + + + /** + * Called once the communicator has been initialized and the Glacier2 session + * has been established. A derived class must implement <code>runWithSession</code>, + * which is the application's starting method. + * + * @param argc The number of elements in argv. + * + * @param argv The argument vector for the application. <code>Application</code> + * scans the argument vector passed to <code>main</code> for options that are + * specific to the Ice run time and removes them; therefore, the vector passed + * to <code>run</code> is free from Ice-related options and contains only options + * and arguments that are application-specific. + * + * @return The <code>runWithSession</code> method should return zero for successful + * termination, and non-zero otherwise. <code>Application.main</code> returns the + * value returned by <code>runWithSession</code>. + **/ + virtual int runWithSession(int argc, char* argv[]) = 0; + + + /** + * Creates a new Glacier2 session. A call to + * <code>createSession</code> always precedes a call to + * <code>runWithSession</code>. If <code>Ice.LocalException</code> + * is thrown from this method, the application is terminated. + + * @return The Glacier2 session. + **/ + virtual Glacier2::SessionPrx createSession() = 0; + + /** + * Called to restart the application's Glacier2 session. This + * method never returns. + * + * @throws RestartSessionException This exception is always thrown. + **/ + void restart() + { + RestartSessionException ex; + throw ex; + } + + /** + * Called when the base class detects that the session has been destroyed. + * A subclass can override this method to take action after the loss of + * connectivity with the Glacier2 router. + **/ + virtual void sessionDestroyed() + { + } + + /** + * Returns the Glacier2 router proxy + * @return The router proxy. + **/ + static Glacier2::RouterPrx router() + { + return _router; + } + + /** + * Returns the Glacier2 session proxy + * @return The session proxy. + **/ + static Glacier2::SessionPrx session() + { + return _session; + } + + /** + * Returns the category to be used in the identities of all of the client's + * callback objects. Clients must use this category for the router to + * forward callback requests to the intended client. + * @return The category. + * @throws SessionNotExistException No session exists. + **/ + std::string categoryForClient(); + + + /** + * Create a new Ice identity for callback objects with the given + * identity name field. + * @return The identity. + **/ + Ice::Identity createCallbackIdentity(const std::string&); + + /** + * Adds a servant to the callback object adapter's Active Servant Map with a UUID. + * @param servant The servant to add. + * @return The proxy for the servant. + **/ + Ice::ObjectPrx addWithUUID(const Ice::ObjectPtr& servant); + + /** + * Creates an object adapter for callback objects. + * @return The object adapter. + */ + Ice::ObjectAdapterPtr objectAdapter(); + +protected: + + virtual int + doMain(int, char*[], const Ice::InitializationData& initData); + +private: + + bool + doMain(Ice::StringSeq&, const Ice::InitializationData&, int&); + + /** + * Run should not be overridden for Glacier2.Application. Instead + * <code>runWithSession</code> should be used. + */ + int run(int, char**) + { + // This shouldn't be called. + assert(false); + return 0; + } + + + static Ice::ObjectAdapterPtr _adapter; + static Glacier2::RouterPrx _router; + static Glacier2::SessionPrx _session; + static bool _createdSession; +}; + +} + diff --git a/cpp/include/Ice/Application.h b/cpp/include/Ice/Application.h index 1ffc86572e4..f8ac4ebae9b 100644 --- a/cpp/include/Ice/Application.h +++ b/cpp/include/Ice/Application.h @@ -12,10 +12,40 @@ #include <Ice/Ice.h> +#include <IceUtil/Mutex.h> + + namespace Ice { + enum SignalPolicy { HandleSignals, NoSignalHandling } ; + class Application; +} -enum SignalPolicy { HandleSignals, NoSignalHandling } ; +namespace IceInternal +{ + extern ICE_API IceUtil::Mutex* mutex; + extern ICE_API std::auto_ptr<IceUtil::Cond> _condVar; + + // + // Variables than can change while run() and communicator->destroy() are running! + // + extern ICE_API bool _callbackInProgress; + extern ICE_API bool _destroyed; + extern ICE_API bool _interrupted; + + // + // Variables that are immutable during run() and until communicator->destroy() has returned; + // before and after run(), and once communicator->destroy() has returned, we assume that + // only the main thread and CtrlCHandler threads are running. + // + extern ICE_API std::string _appName; + extern ICE_API Ice::CommunicatorPtr _communicator; + extern ICE_API Ice::SignalPolicy _signalPolicy; + extern ICE_API Ice::Application* _application; +} + +namespace Ice +{ class ICE_API Application : private IceUtil::noncopyable { @@ -96,9 +126,9 @@ public: // static bool interrupted(); -private: +protected: - int mainInternal(int, char*[], const Ice::InitializationData&); + virtual int doMain(int, char*[], const Ice::InitializationData&); #if defined(__SUNPRO_CC) // diff --git a/cpp/src/Glacier2/Application.cpp b/cpp/src/Glacier2/Application.cpp new file mode 100644 index 00000000000..ac5b1dd9f8a --- /dev/null +++ b/cpp/src/Glacier2/Application.cpp @@ -0,0 +1,426 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. 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 <Glacier2/Application.h> +#include <IceUtil/IceUtil.h> +#include <IceUtil/ArgVector.h> + +using namespace std; +using namespace Ice; + +Ice::ObjectAdapterPtr Glacier2::Application::_adapter; +Glacier2::RouterPrx Glacier2::Application::_router; +Glacier2::SessionPrx Glacier2::Application::_session; +bool Glacier2::Application::_createdSession = false; + +namespace +{ + +class SessionPingThread : virtual public IceUtil::Shared +{ + +public: + + virtual void done() = 0; +}; +typedef IceUtil::Handle<SessionPingThread> SessionPingThreadPtr; + +class AMI_Router_refreshSessionI : public Glacier2::AMI_Router_refreshSession +{ + +public: + + AMI_Router_refreshSessionI(Glacier2::Application* app, const SessionPingThreadPtr& pinger) : + _app(app), + _pinger(pinger) + { + } + + void + ice_response() + { + } + + void + ice_exception(const Ice::Exception& ex) + { + // Here the session has gone. The thread + // terminates, and we notify the + // application that the session has been + // destroyed. + _pinger->done(); + _app->sessionDestroyed(); + } + +private: + + Glacier2::Application* _app; + SessionPingThreadPtr _pinger; +}; + +class SessionPingThreadI : virtual public IceUtil::Thread, virtual public SessionPingThread +{ + +public: + + SessionPingThreadI(Glacier2::Application* app, const Glacier2::RouterPrx& router, long period) : + _app(app), + _router(router), + _period(period), + _done(false) + { + } + + void + run() + { + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(_monitor); + while(true) + { + _router->refreshSession_async(new AMI_Router_refreshSessionI(_app, this)); + + if(!_done) + { + _monitor.timedWait(IceUtil::Time::seconds((int)_period)); + } + if(_done) + { + break; + } + } + } + + void + done() + { + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(_monitor); + if(!_done) + { + _done = true; + _monitor.notify(); + } + } + +private: + + Glacier2::Application* _app; + Glacier2::RouterPrx _router; + long _period; + bool _done; + IceUtil::Monitor<IceUtil::Mutex> _monitor; +}; +typedef IceUtil::Handle<SessionPingThreadI> SessionPingThreadIPtr; + +} + +string +Glacier2::RestartSessionException::ice_name() const +{ + return "RestartSessionException"; +} + +Exception* +Glacier2::RestartSessionException::ice_clone() const +{ + return new RestartSessionException(*this); +} + +void +Glacier2::RestartSessionException::ice_throw() const +{ + throw *this; +} + +Ice::ObjectAdapterPtr +Glacier2::Application::objectAdapter() +{ + if(!_adapter) + { + // TODO: Depending on the resolution of + // http://bugzilla/bugzilla/show_bug.cgi?id=4264 the OA + // name could be an empty string. + _adapter = communicator()->createObjectAdapterWithRouter(IceUtil::generateUUID(), router()); + _adapter->activate(); + } + return _adapter; +} + +Ice::ObjectPrx +Glacier2::Application::addWithUUID(const Ice::ObjectPtr& servant) +{ + return objectAdapter()->add(servant, createCallbackIdentity(IceUtil::generateUUID())); +} + +Ice::Identity +Glacier2::Application::createCallbackIdentity(const string& name) +{ + Ice::Identity id; + id.name = name; + id.category = categoryForClient(); + return id; +} + +std::string +Glacier2::Application::categoryForClient() +{ + if(!_router) + { + SessionNotExistException ex; + throw ex; + } + return router()->getCategoryForClient(); +} + +int +Glacier2::Application::doMain(int argc, char* argv[], const Ice::InitializationData& initData) +{ + // Set the default properties for all Glacier2 applications. + initData.properties->setProperty("Ice.ACM.Client", "0"); + initData.properties->setProperty("Ice.RetryIntervals", "-1"); + + bool restart; + int ret = 0; + do + { + // A copy of the initialization data and the string seq + // needs to be passed to doMainInternal, as these can be + // changed by the application. + Ice::InitializationData id(initData); + id.properties = id.properties->clone(); + Ice::StringSeq args = Ice::argsToStringSeq(argc, argv); + + restart = doMain(args, id, ret); + } + while(restart); + return ret; +} + +bool +Glacier2::Application::doMain(Ice::StringSeq& args, const Ice::InitializationData& initData, int& status) +{ + // Reset internal state variables from Ice.Application. The + // remainder are reset at the end of this method. + IceInternal::_callbackInProgress = false; + IceInternal::_destroyed = false; + IceInternal::_interrupted = false; + + bool restart = false; + status = 0; + + SessionPingThreadIPtr ping; + try + { + IceInternal::_communicator = Ice::initialize(args, initData); + _router = Glacier2::RouterPrx::uncheckedCast(communicator()->getDefaultRouter()); + + if(!_router) + { + Error out(getProcessLogger()); + out << IceInternal::_appName << ": no glacier2 router configured"; + status = 1; + } + else + { + // + // The default is to destroy when a signal is received. + // + if(IceInternal::_signalPolicy == Ice::HandleSignals) + { + destroyOnInterrupt(); + } + + // If createSession throws, we're done. + try + { + _session = createSession(); + _createdSession = true; + } + catch(const Ice::LocalException& ex) + { + Error out(getProcessLogger()); + out << IceInternal::_appName << ": " << ex; + status = 1; + } + + if(_createdSession) + { + ping = new SessionPingThreadI(this, _router, (long)_router->getSessionTimeout() / 2); + ping->start(); + IceUtilInternal::ArgVector a(args); + status = runWithSession(a.argc, a.argv); + } + } + } + // We want to restart on those exceptions which indicate a + // break down in communications, but not those exceptions that + // indicate a programming logic error (ie: marshal, protocol + // failure, etc). + catch(const RestartSessionException&) + { + restart = true; + } + catch(const Ice::ConnectionRefusedException& ex) + { + Error out(getProcessLogger()); + out << IceInternal::_appName << ": " << ex; + restart = true; + } + catch(const Ice::ConnectionLostException& ex) + { + Error out(getProcessLogger()); + out << IceInternal::_appName << ": " << ex; + restart = true; + } + catch(const Ice::UnknownLocalException& ex) + { + Error out(getProcessLogger()); + out << IceInternal::_appName << ": " << ex; + restart = true; + } + catch(const Ice::RequestFailedException& ex) + { + Error out(getProcessLogger()); + out << IceInternal::_appName << ": " << ex; + restart = true; + } + catch(const Ice::TimeoutException& ex) + { + Error out(getProcessLogger()); + out << IceInternal::_appName << ": " << ex; + restart = true; + } + catch(const Ice::LocalException& ex) + { + Error out(getProcessLogger()); + out << IceInternal::_appName << ": " << ex; + status = 1; + } + catch(const std::exception& ex) + { + Error out(getProcessLogger()); + out << IceInternal::_appName << ": std::exception " << ex; + status = 1; + } + catch(const std::string& ex) + { + Error out(getProcessLogger()); + out << IceInternal::_appName << ": c++ exception " << ex; + status = 1; + } + catch(const char* ex) + { + Error out(getProcessLogger()); + out << IceInternal::_appName << ": char* exception " << ex; + status = 1; + } + catch(...) + { + Error out(getProcessLogger()); + out << IceInternal::_appName << ": unknow exception "; + status = 1; + } + + // + // Don't want any new interrupt and at this point (post-run), + // it would not make sense to release a held signal to run + // shutdown or destroy. + // + if(IceInternal::_signalPolicy == HandleSignals) + { + ignoreInterrupt(); + } + + { + IceUtil::Mutex::Lock lock(*IceInternal::mutex); + while(IceInternal::_callbackInProgress) + { + IceInternal::_condVar->wait(lock); + } + if(IceInternal::_destroyed) + { + IceInternal::_communicator = 0; + } + else + { + IceInternal::_destroyed = true; + // + // And _communicator != 0, meaning will be destroyed + // next, _destroyed = true also ensures that any + // remaining callback won't do anything + // + } + IceInternal::_application = 0; + } + + if(!ping) + { + ping->done(); + while(true) + { + ping->getThreadControl().join(); + break; + } + ping = 0; + } + + if(_createdSession && _router) + { + try + { + _router->destroySession(); + } + catch(const Ice::ConnectionLostException&) + { + // Expected: the router closed the connection. + } + catch(const Glacier2::SessionNotExistException&) + { + // This can also occur. + } + catch(const exception& ex) + { + // Not expected. + Error out(getProcessLogger()); + out << "unexpected exception when destroying the session " << ex; + } + _router = 0; + } + + if(IceInternal::_communicator) + { + try + { + IceInternal::_communicator->destroy(); + } + catch(const Ice::LocalException& ex) + { + Error out(getProcessLogger()); + out << IceInternal::_appName << ": " << ex; + status = 1; + } + catch(const exception& ex) + { + Error out(getProcessLogger()); + out << "unknown exception " << ex; + status = 1; + } + IceInternal::_communicator = 0; + } + + + // Reset internal state. We cannot reset the Application state + // here, since _destroyed must remain true until we re-run + // this method. + _adapter = 0; + _router = 0; + _session = 0; + _createdSession = false; + + return restart; +} diff --git a/cpp/src/Glacier2/Makefile b/cpp/src/Glacier2/Makefile index f936fc95556..db08d6d3dda 100644 --- a/cpp/src/Glacier2/Makefile +++ b/cpp/src/Glacier2/Makefile @@ -21,7 +21,8 @@ TARGETS = $(LIBTARGETS) $(ROUTER) OBJS = PermissionsVerifier.o \ Router.o \ SSLInfo.o \ - Session.o + Session.o \ + Application.o ROBJS = Blobject.o \ ClientBlobject.o \ diff --git a/cpp/src/Glacier2/Makefile.mak b/cpp/src/Glacier2/Makefile.mak index 4d6b204ed0b..1243667d97a 100644 --- a/cpp/src/Glacier2/Makefile.mak +++ b/cpp/src/Glacier2/Makefile.mak @@ -19,7 +19,8 @@ TARGETS = $(LIBNAME) $(DLLNAME) $(ROUTER) OBJS = PermissionsVerifier.obj \
Router.obj \
SSLInfo.obj \
- Session.obj
+ Session.obj \
+ Application.obj
ROBJS = Blobject.obj \
ClientBlobject.obj \
@@ -43,7 +44,7 @@ SDIR = $(slicedir)\Glacier2 !include $(top_srcdir)\config\Make.rules.mak
-CPPFLAGS = -I.. $(CPPFLAGS) -DWIN32_LEAN_AND_MEAN
+CPPFLAGS = -I.. $(CPPFLAGS) -DGLACIER2_API_EXPORTS -DWIN32_LEAN_AND_MEAN
LINKWITH = $(LIBS) $(OPENSSL_LIBS) glacier2$(LIBSUFFIX).lib icessl$(LIBSUFFIX).lib
!if "$(BCPLUSPLUS)" != "yes"
LINKWITH = $(LINKWITH) ws2_32.lib
diff --git a/cpp/src/Ice/Application.cpp b/cpp/src/Ice/Application.cpp index bf256c66f27..c7e41882fee 100644 --- a/cpp/src/Ice/Application.cpp +++ b/cpp/src/Ice/Application.cpp @@ -21,6 +21,21 @@ using namespace Ice; using namespace IceUtil; using namespace IceUtilInternal; + +// +// static initializations. +// +Mutex* IceInternal::mutex = 0; + +bool IceInternal::_callbackInProgress = false; +bool IceInternal::_destroyed = false; +bool IceInternal::_interrupted = false; + +string IceInternal::_appName; +CommunicatorPtr IceInternal::_communicator; +SignalPolicy IceInternal::_signalPolicy = HandleSignals; +auto_ptr<Cond> IceInternal::_condVar; +Ice::Application* IceInternal::_application; // // _mutex and _condVar are used to synchronize the main thread and // the CtrlCHandler thread @@ -29,34 +44,29 @@ using namespace IceUtilInternal; namespace { -Mutex* mutex = 0; - class Init { public: Init() { - mutex = new IceUtil::Mutex; + IceInternal::mutex = new IceUtil::Mutex; } ~Init() { - delete mutex; - mutex = 0; + delete IceInternal::mutex; + IceInternal::mutex = 0; } }; Init init; -auto_ptr<Cond> _condVar; + // // Variables than can change while run() and communicator->destroy() are running! // -bool _callbackInProgress = false; -bool _destroyed = false; -bool _interrupted = false; bool _released = false; CtrlCHandlerCallback _previousCallback = 0; @@ -65,12 +75,8 @@ CtrlCHandlerCallback _previousCallback = 0; // before and after run(), and once communicator->destroy() has returned, we assume that // only the main thread and CtrlCHandler threads are running. // -string _appName; -Application* _application; -CommunicatorPtr _communicator; CtrlCHandler* _ctrlCHandler = 0; bool _nohup = false; -SignalPolicy _signalPolicy = HandleSignals; } @@ -97,13 +103,13 @@ holdInterruptCallback(int signal) { CtrlCHandlerCallback callback = 0; { - IceUtil::Mutex::Lock lock(*mutex); + IceUtil::Mutex::Lock lock(*IceInternal::mutex); while(!_released) { - _condVar->wait(lock); + IceInternal::_condVar->wait(lock); } - if(_destroyed) + if(IceInternal::_destroyed) { // // Being destroyed by main thread @@ -124,8 +130,8 @@ static void destroyOnInterruptCallback(int signal) { { - IceUtil::Mutex::Lock lock(*mutex); - if(_destroyed) + IceUtil::Mutex::Lock lock(*IceInternal::mutex); + if(IceInternal::_destroyed) { // // Being destroyed by main thread @@ -137,16 +143,16 @@ destroyOnInterruptCallback(int signal) return; } - assert(!_callbackInProgress); - _callbackInProgress = true; - _interrupted = true; - _destroyed = true; + assert(!IceInternal::_callbackInProgress); + IceInternal::_callbackInProgress = true; + IceInternal::_interrupted = true; + IceInternal::_destroyed = true; } try { - assert(_communicator != 0); - _communicator->destroy(); + assert(IceInternal::_communicator != 0); + IceInternal::_communicator->destroy(); } catch(const std::exception& ex) { @@ -170,18 +176,18 @@ destroyOnInterruptCallback(int signal) } { - IceUtil::Mutex::Lock lock(*mutex); - _callbackInProgress = false; + IceUtil::Mutex::Lock lock(*IceInternal::mutex); + IceInternal::_callbackInProgress = false; } - _condVar->signal(); + IceInternal::_condVar->signal(); } static void shutdownOnInterruptCallback(int signal) { { - IceUtil::Mutex::Lock lock(*mutex); - if(_destroyed) + IceUtil::Mutex::Lock lock(*IceInternal::mutex); + if(IceInternal::_destroyed) { // // Being destroyed by main thread @@ -193,15 +199,15 @@ shutdownOnInterruptCallback(int signal) return; } - assert(!_callbackInProgress); - _callbackInProgress = true; - _interrupted = true; + assert(!IceInternal::_callbackInProgress); + IceInternal::_callbackInProgress = true; + IceInternal::_interrupted = true; } try { - assert(_communicator != 0); - _communicator->shutdown(); + assert(IceInternal::_communicator != 0); + IceInternal::_communicator->shutdown(); } catch(const std::exception& ex) { @@ -225,18 +231,18 @@ shutdownOnInterruptCallback(int signal) } { - IceUtil::Mutex::Lock lock(*mutex); - _callbackInProgress = false; + IceUtil::Mutex::Lock lock(*IceInternal::mutex); + IceInternal::_callbackInProgress = false; } - _condVar->signal(); + IceInternal::_condVar->signal(); } static void callbackOnInterruptCallback(int signal) { { - IceUtil::Mutex::Lock lock(*mutex); - if(_destroyed) + IceUtil::Mutex::Lock lock(*IceInternal::mutex); + if(IceInternal::_destroyed) { // // Being destroyed by main thread @@ -245,15 +251,15 @@ callbackOnInterruptCallback(int signal) } // For SIGHUP the user callback is always called. It can // decide what to do. - assert(!_callbackInProgress); - _callbackInProgress = true; - _interrupted = true; + assert(!IceInternal::_callbackInProgress); + IceInternal::_callbackInProgress = true; + IceInternal::_interrupted = true; } try { - assert(_application != 0); - _application->interruptCallback(signal); + assert(IceInternal::_application != 0); + IceInternal::_application->interruptCallback(signal); } catch(const std::exception& ex) { @@ -277,15 +283,15 @@ callbackOnInterruptCallback(int signal) } { - IceUtil::Mutex::Lock lock(*mutex); - _callbackInProgress = false; + IceUtil::Mutex::Lock lock(*IceInternal::mutex); + IceInternal::_callbackInProgress = false; } - _condVar->signal(); + IceInternal::_condVar->signal(); } Ice::Application::Application(SignalPolicy signalPolicy) { - _signalPolicy = signalPolicy; + IceInternal::_signalPolicy = signalPolicy; } Ice::Application::~Application() @@ -342,7 +348,7 @@ Ice::Application::main(int argc, char* argv[], const InitializationData& initDat setProcessLogger(new LoggerI(argv[0], "")); } - if(_communicator != 0) + if(IceInternal::_communicator != 0) { Error out(getProcessLogger()); out << "only one instance of the Application class can be used"; @@ -350,7 +356,7 @@ Ice::Application::main(int argc, char* argv[], const InitializationData& initDat } int status; - if(_signalPolicy == HandleSignals) + if(IceInternal::_signalPolicy == HandleSignals) { try { @@ -361,7 +367,7 @@ Ice::Application::main(int argc, char* argv[], const InitializationData& initDat CtrlCHandler ctrCHandler; _ctrlCHandler = &ctrCHandler; - status = mainInternal(argc, argv, initData); + status = doMain(argc, argv, initData); // // Set _ctrlCHandler to 0 only once communicator->destroy() has completed. @@ -377,7 +383,7 @@ Ice::Application::main(int argc, char* argv[], const InitializationData& initDat } else { - status = mainInternal(argc, argv, initData); + status = doMain(argc, argv, initData); } return status; @@ -412,27 +418,27 @@ Ice::Application::interruptCallback(int) const char* Ice::Application::appName() { - return _appName.c_str(); + return IceInternal::_appName.c_str(); } CommunicatorPtr Ice::Application::communicator() { - return _communicator; + return IceInternal::_communicator; } void Ice::Application::destroyOnInterrupt() { - if(_signalPolicy == HandleSignals) + if(IceInternal::_signalPolicy == HandleSignals) { if(_ctrlCHandler != 0) { - IceUtil::Mutex::Lock lock(*mutex); // we serialize all the interrupt-setting + IceUtil::Mutex::Lock lock(*IceInternal::mutex); // we serialize all the interrupt-setting if(_ctrlCHandler->getCallback() == holdInterruptCallback) { _released = true; - _condVar->signal(); + IceInternal::_condVar->signal(); } _ctrlCHandler->setCallback(destroyOnInterruptCallback); } @@ -447,15 +453,15 @@ Ice::Application::destroyOnInterrupt() void Ice::Application::shutdownOnInterrupt() { - if(_signalPolicy == HandleSignals) + if(IceInternal::_signalPolicy == HandleSignals) { if(_ctrlCHandler != 0) { - IceUtil::Mutex::Lock lock(*mutex); // we serialize all the interrupt-setting + IceUtil::Mutex::Lock lock(*IceInternal::mutex); // we serialize all the interrupt-setting if(_ctrlCHandler->getCallback() == holdInterruptCallback) { _released = true; - _condVar->signal(); + IceInternal::_condVar->signal(); } _ctrlCHandler->setCallback(shutdownOnInterruptCallback); } @@ -470,15 +476,15 @@ Ice::Application::shutdownOnInterrupt() void Ice::Application::ignoreInterrupt() { - if(_signalPolicy == HandleSignals) + if(IceInternal::_signalPolicy == HandleSignals) { if(_ctrlCHandler != 0) { - IceUtil::Mutex::Lock lock(*mutex); // we serialize all the interrupt-setting + IceUtil::Mutex::Lock lock(*IceInternal::mutex); // we serialize all the interrupt-setting if(_ctrlCHandler->getCallback() == holdInterruptCallback) { _released = true; - _condVar->signal(); + IceInternal::_condVar->signal(); } _ctrlCHandler->setCallback(0); } @@ -493,15 +499,15 @@ Ice::Application::ignoreInterrupt() void Ice::Application::callbackOnInterrupt() { - if(_signalPolicy == HandleSignals) + if(IceInternal::_signalPolicy == HandleSignals) { if(_ctrlCHandler != 0) { - IceUtil::Mutex::Lock lock(*mutex); // we serialize all the interrupt-setting + IceUtil::Mutex::Lock lock(*IceInternal::mutex); // we serialize all the interrupt-setting if(_ctrlCHandler->getCallback() == holdInterruptCallback) { _released = true; - _condVar->signal(); + IceInternal::_condVar->signal(); } _ctrlCHandler->setCallback(callbackOnInterruptCallback); } @@ -516,11 +522,11 @@ Ice::Application::callbackOnInterrupt() void Ice::Application::holdInterrupt() { - if(_signalPolicy == HandleSignals) + if(IceInternal::_signalPolicy == HandleSignals) { if(_ctrlCHandler != 0) { - IceUtil::Mutex::Lock lock(*mutex); // we serialize all the interrupt-setting + IceUtil::Mutex::Lock lock(*IceInternal::mutex); // we serialize all the interrupt-setting if(_ctrlCHandler->getCallback() != holdInterruptCallback) { _previousCallback = _ctrlCHandler->getCallback(); @@ -540,11 +546,11 @@ Ice::Application::holdInterrupt() void Ice::Application::releaseInterrupt() { - if(_signalPolicy == HandleSignals) + if(IceInternal::_signalPolicy == HandleSignals) { if(_ctrlCHandler != 0) { - IceUtil::Mutex::Lock lock(*mutex); // we serialize all the interrupt-setting + IceUtil::Mutex::Lock lock(*IceInternal::mutex); // we serialize all the interrupt-setting if(_ctrlCHandler->getCallback() == holdInterruptCallback) { // @@ -556,7 +562,7 @@ Ice::Application::releaseInterrupt() _released = true; _ctrlCHandler->setCallback(_previousCallback); - _condVar->signal(); + IceInternal::_condVar->signal(); } // Else nothing to release. } @@ -571,24 +577,24 @@ Ice::Application::releaseInterrupt() bool Ice::Application::interrupted() { - IceUtil::Mutex::Lock lock(*mutex); - return _interrupted; + IceUtil::Mutex::Lock lock(*IceInternal::mutex); + return IceInternal::_interrupted; } int -Ice::Application::mainInternal(int argc, char* argv[], const InitializationData& initializationData) +Ice::Application::doMain(int argc, char* argv[], const InitializationData& initializationData) { int status; try { - if(_condVar.get() == 0) + if(IceInternal::_condVar.get() == 0) { - _condVar.reset(new Cond); + IceInternal::_condVar.reset(new Cond); } - _interrupted = false; - _appName = argv[0] ? argv[0] : ""; + IceInternal::_interrupted = false; + IceInternal::_appName = argv[0] ? argv[0] : ""; // // We parse the properties here to extract Ice.ProgramName. @@ -605,19 +611,19 @@ Ice::Application::mainInternal(int argc, char* argv[], const InitializationData& setProcessLogger(new LoggerI(initData.properties->getProperty("Ice.ProgramName"), "")); } - _application = this; - _communicator = initialize(argc, argv, initData); - _destroyed = false; + IceInternal::_application = this; + IceInternal::_communicator = initialize(argc, argv, initData); + IceInternal::_destroyed = false; // // Used by destroyOnInterruptCallback and shutdownOnInterruptCallback. // - _nohup = (_communicator->getProperties()->getPropertyAsInt("Ice.Nohup") > 0); + _nohup = (IceInternal::_communicator->getProperties()->getPropertyAsInt("Ice.Nohup") > 0); // // The default is to destroy when a signal is received. // - if(_signalPolicy == HandleSignals) + if(IceInternal::_signalPolicy == HandleSignals) { destroyOnInterrupt(); } @@ -654,38 +660,38 @@ Ice::Application::mainInternal(int argc, char* argv[], const InitializationData& // it would not make sense to release a held signal to run // shutdown or destroy. // - if(_signalPolicy == HandleSignals) + if(IceInternal::_signalPolicy == HandleSignals) { ignoreInterrupt(); } { - IceUtil::Mutex::Lock lock(*mutex); - while(_callbackInProgress) + IceUtil::Mutex::Lock lock(*IceInternal::mutex); + while(IceInternal::_callbackInProgress) { - _condVar->wait(lock); + IceInternal::_condVar->wait(lock); } - if(_destroyed) + if(IceInternal::_destroyed) { - _communicator = 0; + IceInternal::_communicator = 0; } else { - _destroyed = true; + IceInternal::_destroyed = true; // // And _communicator != 0, meaning will be destroyed // next, _destroyed = true also ensures that any // remaining callback won't do anything // } - _application = 0; + IceInternal::_application = 0; } - if(_communicator != 0) + if(IceInternal::_communicator != 0) { try { - _communicator->destroy(); + IceInternal::_communicator->destroy(); } catch(const std::exception& ex) { @@ -699,7 +705,7 @@ Ice::Application::mainInternal(int argc, char* argv[], const InitializationData& out << "unknown exception"; status = EXIT_FAILURE; } - _communicator = 0; + IceInternal::_communicator = 0; } return status; diff --git a/cs/demo/Glacier2/callback/Client.cs b/cs/demo/Glacier2/callback/Client.cs index 19698a32bc1..aa50ad97bca 100644 --- a/cs/demo/Glacier2/callback/Client.cs +++ b/cs/demo/Glacier2/callback/Client.cs @@ -21,51 +21,8 @@ using System.Reflection; public class Client { - public class App : Ice.Application + public class App : Glacier2.Application { - class SessionRefreshThread - { - public SessionRefreshThread(Glacier2.RouterPrx router, int timeout) - { - _router = router; - _timeout = timeout; - _terminated = false; - } - - public void run() - { - lock(this) - { - while(!_terminated) - { - Monitor.Wait(this, _timeout); - if(!_terminated) - { - try - { - _router.refreshSession(); - } - catch(Ice.Exception) - { - } - } - } - } - } - - public void terminate() - { - lock(this) - { - _terminated = true; - Monitor.Pulse(this); - } - } - - private Glacier2.RouterPrx _router; - private int _timeout; - private bool _terminated; - } private static void menu() { Console.WriteLine( @@ -81,81 +38,70 @@ public class Client "?: help\n"); } - public override int run(string[] args) + public override Glacier2.SessionPrx createSession() { - if(args.Length > 0) - { - Console.Error.WriteLine(appName() + ": too many arguments"); - return 1; - } - - Ice.RouterPrx defaultRouter = communicator().getDefaultRouter(); - if(defaultRouter == null) - { - Console.Error.WriteLine("no default router set"); - return 1; - } - - Glacier2.RouterPrx router = Glacier2.RouterPrxHelper.checkedCast(defaultRouter); - if(router == null) - { - Console.Error.WriteLine("configured router is not a Glacier2 router"); - return 1; - } - + Glacier2.SessionPrx session; while(true) { Console.WriteLine("This demo accepts any user-id / password combination."); String id; - Console.Write("user id: "); - Console.Out.Flush(); - id = Console.In.ReadLine(); - String pw; - Console.Write("password: "); - Console.Out.Flush(); - pw = Console.In.ReadLine(); + try + { + Console.Write("user id: "); + Console.Out.Flush(); + id = Console.In.ReadLine().Trim(); + + Console.Write("password: "); + Console.Out.Flush(); + pw = Console.In.ReadLine().Trim(); + } + catch(System.IO.IOException ex) + { + Console.WriteLine(ex.StackTrace.ToString()); + continue; + } try { - router.createSession(id, pw); + session = router().createSession(id, pw); break; } catch(Glacier2.PermissionDeniedException ex) { - Console.Write("permission denied:\n" + ex.reason); + Console.WriteLine("permission denied:\n" + ex.reason); } catch(Glacier2.CannotCreateSessionException ex) { - Console.Write("cannot create session:\n" + ex.reason); + Console.WriteLine("cannot create session:\n" + ex.reason); } } + return session; + } - SessionRefreshThread refresh = new SessionRefreshThread(router, (int)router.getSessionTimeout() * 500); - Thread refreshThread = new Thread(new ThreadStart(refresh.run)); - refreshThread.Start(); + public override int runWithSession(string[] args) + { + if(args.Length > 0) + { + Console.Error.WriteLine(appName() + ": too many arguments"); + return 1; + } - String category = router.getCategoryForClient(); - Ice.Identity callbackReceiverIdent = new Ice.Identity(); - callbackReceiverIdent.name = "callbackReceiver"; - callbackReceiverIdent.category = category; - Ice.Identity callbackReceiverFakeIdent = new Ice.Identity(); - callbackReceiverFakeIdent.name = "callbackReceiver"; - callbackReceiverFakeIdent.category = "fake"; + + Ice.Identity callbackReceiverIdent = createCallbackIdentity("callbackReceiver"); + Ice.Identity callbackReceiverFakeIdent = new Ice.Identity("fake", "callbackReceiver"); Ice.ObjectPrx @base = communicator().propertyToProxy("Callback.Proxy"); CallbackPrx twoway = CallbackPrxHelper.checkedCast(@base); CallbackPrx oneway = CallbackPrxHelper.uncheckedCast(twoway.ice_oneway()); CallbackPrx batchOneway = CallbackPrxHelper.uncheckedCast(twoway.ice_batchOneway()); - Ice.ObjectAdapter adapter = communicator().createObjectAdapterWithRouter("Callback.Client", defaultRouter); - adapter.add(new CallbackReceiverI(), callbackReceiverIdent); - adapter.add(new CallbackReceiverI(), callbackReceiverFakeIdent); - adapter.activate(); + objectAdapter().add(new CallbackReceiverI(), callbackReceiverFakeIdent); CallbackReceiverPrx twowayR = CallbackReceiverPrxHelper.uncheckedCast( - adapter.createProxy(callbackReceiverIdent)); + objectAdapter().add(new CallbackReceiverI(), callbackReceiverIdent)); + CallbackReceiverPrx onewayR = CallbackReceiverPrxHelper.uncheckedCast(twowayR.ice_oneway()); menu(); @@ -274,25 +220,6 @@ public class Client // is set to 0 so that if session.destroy() raises an exception // the thread will not be re-terminated and re-joined. // - refresh.terminate(); - refreshThread.Join(); - refresh = null; - - try - { - router.destroySession(); - } - catch(Glacier2.SessionNotExistException ex) - { - Console.Error.WriteLine(ex); - } - catch(Ice.ConnectionLostException) - { - // - // Expected: the router closed the connection. - // - } - return 0; } } diff --git a/cs/demo/Glacier2/callback/Glacier2.callback.client.csproj b/cs/demo/Glacier2/callback/Glacier2.callback.client.csproj index 8b92a462af5..669b64e062f 100644 --- a/cs/demo/Glacier2/callback/Glacier2.callback.client.csproj +++ b/cs/demo/Glacier2/callback/Glacier2.callback.client.csproj @@ -1,7 +1,7 @@ <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<ProjectType>Local</ProjectType>
- <ProductVersion>8.0.50727</ProductVersion>
+ <ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{2AC78A13-497B-44B1-8BF0-156877B78293}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -113,7 +113,7 @@ </PropertyGroup>
<ProjectExtensions>
<VisualStudio>
- <UserProperties ZerocIce_ConsoleOutput="True" ZerocIce_Enabled="True" ZerocIce_Home="..\..\..\.." ZerocIce_HomeExpanded="..\..\..\.." />
+ <UserProperties ZerocIce_HomeExpanded="..\..\..\.." ZerocIce_Home="..\..\..\.." ZerocIce_Enabled="True" ZerocIce_ConsoleOutput="True" />
</VisualStudio>
</ProjectExtensions>
</Project>
\ No newline at end of file diff --git a/cs/demo/Glacier2/callback/expect.py b/cs/demo/Glacier2/callback/expect.py index a53d2f02678..0878334c2da 100755 --- a/cs/demo/Glacier2/callback/expect.py +++ b/cs/demo/Glacier2/callback/expect.py @@ -24,8 +24,6 @@ from demoscript.Glacier2 import callback server = Util.spawn('./server.exe --Ice.PrintAdapterReady') server.expect('.* ready') -sessionserver = Util.spawn('./sessionserver.exe --Ice.PrintAdapterReady') -sessionserver.expect('.* ready') glacier2 = Util.spawn('glacier2router --Ice.Config=config.glacier2 --Ice.PrintAdapterReady --Glacier2.SessionTimeout=5') glacier2.expect('Glacier2.Client ready') @@ -33,4 +31,4 @@ glacier2.expect('Glacier2.Server ready') client = Util.spawn('./client.exe') -callback.run(client, server, sessionserver, glacier2) +callback.run(client, server, glacier2) diff --git a/cs/demo/Glacier2/chat/App.xaml b/cs/demo/Glacier2/chat/App.xaml new file mode 100755 index 00000000000..dd7c8855d04 --- /dev/null +++ b/cs/demo/Glacier2/chat/App.xaml @@ -0,0 +1,21 @@ +<!--
+// **********************************************************************
+//
+// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+-->
+<Application x:Class="Glacier2.chat.client.App"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ StartupUri="ChatWindow.xaml" ShutdownMode="OnLastWindowClose">
+ <Application.Resources>
+ <Style x:Key="Menu">
+ <Setter Property="MenuItem.FontFamily" Value="Times New Romans"/>
+ <Setter Property="MenuItem.FontSize" Value="12"/>
+ </Style>
+ </Application.Resources>
+</Application>
diff --git a/cs/demo/Glacier2/chat/App.xaml.cs b/cs/demo/Glacier2/chat/App.xaml.cs new file mode 100755 index 00000000000..00a6e969446 --- /dev/null +++ b/cs/demo/Glacier2/chat/App.xaml.cs @@ -0,0 +1,25 @@ +// **********************************************************************
+//
+// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Windows;
+
+namespace Glacier2.chat.client
+{
+ /// <summary>
+ /// Interaction logic for App.xaml
+ /// </summary>
+ public partial class App : System.Windows.Application
+ {
+ }
+}
diff --git a/cs/demo/Glacier2/chat/CancelDialog.xaml b/cs/demo/Glacier2/chat/CancelDialog.xaml new file mode 100755 index 00000000000..f70a96bb95c --- /dev/null +++ b/cs/demo/Glacier2/chat/CancelDialog.xaml @@ -0,0 +1,27 @@ +<!--
+// **********************************************************************
+//
+// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+-->
+<Window x:Class="Glacier2.chat.client.CancelDialog"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ Title="Connecting" Height="80" Width="200" ResizeMode="NoResize">
+ <Grid>
+ <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Orientation="Vertical">
+
+ <StackPanel Orientation="Vertical">
+ <TextBlock Margin="2" Name="txtInfo" Width="180" TextWrapping="Wrap">Please wait while connecting...</TextBlock>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
+ <Button Margin="2" MaxWidth="80" Click="cancel" IsDefault="True">Cancel</Button>
+ </StackPanel>
+ </StackPanel>
+ </Grid>
+</Window>
diff --git a/cs/demo/Glacier2/chat/CancelDialog.xaml.cs b/cs/demo/Glacier2/chat/CancelDialog.xaml.cs new file mode 100755 index 00000000000..f6668b04fca --- /dev/null +++ b/cs/demo/Glacier2/chat/CancelDialog.xaml.cs @@ -0,0 +1,49 @@ +// **********************************************************************
+//
+// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace Glacier2.chat.client
+{
+ /// <summary>
+ /// Interaction logic for CancelDialog.xaml
+ /// </summary>
+ public partial class CancelDialog : Window
+ {
+ public CancelDialog()
+ {
+ InitializeComponent();
+ }
+
+ public void cancel(object sender, RoutedEventArgs args)
+ {
+ _cancel = true;
+ Close();
+ }
+
+ public bool ShowModal()
+ {
+ ShowDialog();
+ return _cancel;
+ }
+
+ private bool _cancel = false;
+ }
+}
diff --git a/cs/demo/Glacier2/chat/Chat.ice b/cs/demo/Glacier2/chat/Chat.ice new file mode 100755 index 00000000000..d55ec11be98 --- /dev/null +++ b/cs/demo/Glacier2/chat/Chat.ice @@ -0,0 +1,31 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef CHAT_ICE +#define CHAT_ICE + +#include <Glacier2/Session.ice> + +module Demo +{ + +interface ChatCallback +{ + void message(string data); +}; + +interface ChatSession extends Glacier2::Session +{ + ["ami"] void setCallback(ChatCallback* callback); + ["ami"] void say(string data); +}; + +}; + +#endif diff --git a/cs/demo/Glacier2/chat/ChatCommands.cs b/cs/demo/Glacier2/chat/ChatCommands.cs new file mode 100755 index 00000000000..11c21a10160 --- /dev/null +++ b/cs/demo/Glacier2/chat/ChatCommands.cs @@ -0,0 +1,58 @@ +// **********************************************************************
+//
+// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Input;
+
+namespace Glacier2.chat.client
+{
+ public class ChatCommands
+ {
+ static ChatCommands()
+ {
+ // Initialize logout command
+ _loginCommand = new RoutedUICommand("Login", "Login", typeof(ChatCommands), null);
+ // Initialize logout command
+ _logoutCommand = new RoutedUICommand("Logout", "Logout", typeof(ChatCommands), null);
+ // Initialize exit commnad
+ _exitCommand = new RoutedUICommand("Exit", "&Exit", typeof(ChatCommands), null);
+ }
+
+ public static RoutedUICommand Login
+ {
+ get
+ {
+ return _loginCommand;
+ }
+ }
+
+ public static RoutedUICommand Logout
+ {
+ get
+ {
+ return _logoutCommand;
+ }
+ }
+
+ public static RoutedUICommand Exit
+ {
+ get
+ {
+ return _exitCommand;
+ }
+ }
+
+ private static RoutedUICommand _loginCommand;
+ private static RoutedUICommand _logoutCommand;
+ private static RoutedUICommand _exitCommand;
+ }
+}
diff --git a/cs/demo/Glacier2/chat/ChatWindow.xaml b/cs/demo/Glacier2/chat/ChatWindow.xaml new file mode 100755 index 00000000000..3e78088256d --- /dev/null +++ b/cs/demo/Glacier2/chat/ChatWindow.xaml @@ -0,0 +1,68 @@ +<!--
+// **********************************************************************
+//
+// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+-->
+<Window x:Class="Glacier2.chat.client.ChatWindow"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="clr-namespace:Glacier2.chat.client"
+ Title="Chat Window" Height="300" Width="300" Closed="windowClosed">
+ <Window.CommandBindings>
+ <CommandBinding Command="local:ChatCommands.Login" Executed="login" CanExecute="isLoginEnabled"/>
+ <CommandBinding Command="local:ChatCommands.Logout" Executed="logout" CanExecute="isLogoutEnabled"/>
+ <CommandBinding Command="local:ChatCommands.Exit" Executed="exit"/>
+ </Window.CommandBindings>
+ <DockPanel>
+ <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" DockPanel.Dock="Top">
+ <Menu Style="{StaticResource Menu}" Background="White">
+ <MenuItem Header="Connect">
+ <MenuItem Header="_Login" Command="local:ChatCommands.Login" Background="White"/>
+ <MenuItem Header="_Logout" Command="local:ChatCommands.Logout" Background="White"/>
+ <MenuItem Header="E_xit" Command="local:ChatCommands.Exit" Background="White"/>
+ </MenuItem>
+ </Menu>
+ </StackPanel>
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="5*"></RowDefinition>
+ <RowDefinition Height="AUTO"></RowDefinition>
+ <RowDefinition Height="AUTO"></RowDefinition>
+ <RowDefinition Height="AUTO"></RowDefinition>
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition></ColumnDefinition>
+ </Grid.ColumnDefinitions>
+
+ <!-- Define a text box to show chat messages. -->
+ <TextBox Grid.Column="0" Grid.Row="0" x:Name="txtMessages"
+ FontSize="12" Text="" TextWrapping="Wrap" IsEnabled="True"
+ ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Auto"
+ ScrollViewer.VerticalScrollBarVisibility="Auto" IsReadOnly="True"
+ MinLines="4" SizeChanged="scrollDown"/>
+
+ <!-- Define another splitter to separate the upper view and the text box used
+ for input messages. -->
+ <GridSplitter Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Height="2"
+ ResizeDirection="Rows" HorizontalAlignment="Stretch"/>
+
+ <!--- Define an editable text box for the user to write messages. -->
+ <TextBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3"
+ Name="input"
+ TextWrapping="Wrap"
+ ScrollViewer.CanContentScroll="True"
+ HorizontalScrollBarVisibility="Hidden"
+ VerticalScrollBarVisibility="Auto"
+ Background="WhiteSmoke" KeyDown="sendMessage" TabIndex="1"></TextBox>
+
+ <!-- TextBlock with the status message -->
+ <Label Grid.Row="3" Name="status" Grid.Column="0" VerticalAlignment="Bottom" Content="Disconnected"/>
+
+ </Grid>
+ </DockPanel>
+</Window>
diff --git a/cs/demo/Glacier2/chat/ChatWindow.xaml.cs b/cs/demo/Glacier2/chat/ChatWindow.xaml.cs new file mode 100755 index 00000000000..cbc5affb56c --- /dev/null +++ b/cs/demo/Glacier2/chat/ChatWindow.xaml.cs @@ -0,0 +1,321 @@ +// **********************************************************************
+//
+// Copyright(c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using System.Windows.Threading;
+
+using Demo;
+
+namespace Glacier2.chat.client
+{
+ public class LoginData
+ {
+ public LoginData()
+ {
+ routerHost = "127.0.0.1";
+ userName = "test";
+ password = "";
+ }
+
+ public String routerHost;
+ public String userName;
+ public String password;
+ }
+
+ class Util
+ {
+ static public void
+ locateOnScreen(System.Windows.Window window)
+ {
+ window.Left = (System.Windows.SystemParameters.PrimaryScreenWidth - window.Width) / 2;
+ window.Top = (System.Windows.SystemParameters.PrimaryScreenHeight - window.Height) / 2;
+ }
+
+ static public void
+ centerWindow(System.Windows.Window w1, System.Windows.Window w)
+ {
+ w1.Top = w.Top + ((w.Height - w1.Height) / 2);
+ w1.Left = w.Left + ((w.Width - w1.Width) / 2);
+ }
+ }
+
+ /// <summary>
+ /// Interaction logic for ChatWindow.xaml
+ /// </summary>
+ public partial class ChatWindow : Window, Glacier2.SessionFactoryHelper.Callback
+ {
+ private class ChatCallbackI : Demo.ChatCallbackDisp_
+ {
+ public ChatCallbackI(ChatWindow window)
+ {
+ _window = window;
+ }
+ public override void
+ message(string data, Ice.Current current)
+ {
+ _window.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)delegate()
+ {
+ _window.appendMessage(data);
+ }
+ );
+ }
+ ChatWindow _window;
+ }
+
+ class AMI_ChatSession_sayI : Demo.AMI_ChatSession_say
+ {
+ public AMI_ChatSession_sayI(ChatWindow window)
+ {
+ _window = window;
+ }
+
+ public override void
+ ice_exception(Ice.Exception ex)
+ {
+ _window.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)delegate()
+ {
+ _window.appendMessage("<system-message> - " + ex.ToString());
+ });
+ }
+
+ public override void
+ ice_response()
+ {
+ }
+
+ private ChatWindow _window;
+ }
+
+ class AMI_ChatSession_setCallbackI : Demo.AMI_ChatSession_setCallback
+ {
+ public AMI_ChatSession_setCallbackI(ChatWindow window)
+ {
+ _window = window;
+ }
+
+ public override void
+ ice_response()
+ {
+ _window.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)delegate()
+ {
+ _window.closeCancelDialog();
+ _window.input.IsEnabled = true;
+ _window.status.Content = "Connected with " + _window._loginData.routerHost;
+ });
+ }
+
+ public override void
+ ice_exception(Ice.Exception ex)
+ {
+ _window.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)delegate()
+ {
+ if(_window._session != null)
+ {
+ _window._session.destroy();
+ }
+ });
+ }
+ private ChatWindow _window;
+ }
+
+ public ChatWindow()
+ {
+ Ice.Properties properties = Ice.Util.createProperties();
+ properties.load("config.client");
+
+ _factory = new SessionFactoryHelper(properties, this);
+ InitializeComponent();
+ Util.locateOnScreen(this);
+ }
+
+ private void
+ login(object sender, ExecutedRoutedEventArgs args)
+ {
+ LoginDialog loginDialog = new LoginDialog(_loginData);
+ Util.centerWindow(loginDialog, this);
+ if(loginDialog.ShowModal())
+ {
+ status.Content = "Connecting";
+ _factory.setRouterHost(_loginData.routerHost);
+ _factory.setRouterIdentity(new Ice.Identity("router", "DemoGlacier2"));
+ _session = _factory.connect(_loginData.userName, _loginData.password);
+
+ _cancelDialog = new CancelDialog();
+ Util.centerWindow(_cancelDialog, this);
+ if(_cancelDialog.ShowModal())
+ {
+ if(_session != null)
+ {
+ _session.destroy();
+ _session = null;
+ status.Content = "Connection canceled";
+ }
+ }
+ }
+ }
+
+ private void
+ logout(object sender, ExecutedRoutedEventArgs args)
+ {
+ status.Content = "Disconnecting";
+ _session.destroy();
+ _session = null;
+ }
+
+ private void
+ exit(object sender, ExecutedRoutedEventArgs args)
+ {
+ Close();
+ }
+
+ private void
+ windowClosed(object sender, EventArgs e)
+ {
+ lock(this)
+ {
+ if(_session != null)
+ {
+ _session.destroy();
+ _session = null;
+ }
+ }
+ App.Current.Shutdown(0);
+ }
+
+ private void
+ isLogoutEnabled(object sender, CanExecuteRoutedEventArgs args)
+ {
+ args.CanExecute = _session != null && _session.isConnected();
+ }
+
+ private void
+ isLoginEnabled(object sender,CanExecuteRoutedEventArgs args)
+ {
+ args.CanExecute = _session == null || !_session.isConnected();
+ }
+
+ //
+ // Event handler attached to txtChatImputLine onKeyDown.
+ // If the key is the Enter key, it sends the message asynchronously
+ // and cleans the input line; otherwise, it does nothing.
+ //
+ private void
+ sendMessage(object sender, KeyEventArgs e)
+ {
+ if(e.Key == Key.Enter)
+ {
+ string message = input.Text.Trim();
+ if(message.Length > 0)
+ {
+ _chat.say_async(new AMI_ChatSession_sayI(this), message);
+ }
+ input.Text = "";
+ }
+ }
+
+ private void
+ scrollDown(object sender, SizeChangedEventArgs e)
+ {
+ txtMessages.ScrollToEnd();
+ }
+
+ private void
+ closeCancelDialog()
+ {
+ if(_cancelDialog != null)
+ {
+ _cancelDialog.Close();
+ _cancelDialog = null;
+ }
+ }
+
+ public void
+ appendMessage(string message)
+ {
+ txtMessages.AppendText(message);
+ txtMessages.ScrollToEnd();
+ }
+
+ private LoginData _loginData = new LoginData();
+ private CancelDialog _cancelDialog = new CancelDialog();
+ private Glacier2.SessionFactoryHelper _factory;
+ private Glacier2.SessionHelper _session;
+ private Demo.ChatSessionPrx _chat;
+
+ #region Callback Members
+
+ public void connectFailed(SessionHelper session, Exception ex)
+ {
+ // If the session has been reassigned avoid the
+ // spurious callback.
+ if(session != _session)
+ {
+ return;
+ }
+
+ closeCancelDialog();
+ status.Content = ex.GetType();
+ }
+
+ public void connected(SessionHelper session)
+ {
+ // If the session has been reassigned avoid the
+ // spurious callback.
+ if(session != _session)
+ {
+ return;
+ }
+
+ Ice.Object servant = new ChatCallbackI(this);
+
+ Demo.ChatCallbackPrx callback = Demo.ChatCallbackPrxHelper.uncheckedCast(
+ _session.addWithUUID(servant));
+ _chat = Demo.ChatSessionPrxHelper.uncheckedCast(_session.session());
+ _chat.setCallback_async(new AMI_ChatSession_setCallbackI(this), callback);
+ }
+
+ public void createdCommunicator(SessionHelper session)
+ {
+ }
+
+ public void disconnected(SessionHelper session)
+ {
+ // If the session has been reassigned avoid the
+ // spurious callback.
+ if(session != _session)
+ {
+ return;
+ }
+ closeCancelDialog();
+ _session = null;
+ _chat = null;
+ input.IsEnabled = false;
+ status.Content = "Disconnected";
+ }
+
+ public Dispatcher getDispatcher()
+ {
+ return this.Dispatcher;// System.Windows.Application.Current.Dispatcher;
+ }
+
+ #endregion
+ }
+}
diff --git a/cs/demo/Glacier2/chat/Glacier2.chat.client.csproj b/cs/demo/Glacier2/chat/Glacier2.chat.client.csproj new file mode 100755 index 00000000000..67b88ed8dda --- /dev/null +++ b/cs/demo/Glacier2/chat/Glacier2.chat.client.csproj @@ -0,0 +1,148 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{53DCED47-A722-48EF-86D8-A10AD0594F21}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Glacier2.chat.client</RootNamespace>
+ <AssemblyName>Glacier2.chat.client</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>.\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Glacier2, Version=3.4.51.0, Culture=neutral, PublicKeyToken=1f998c50fec78381, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\bin\Glacier2.dll</HintPath>
+ </Reference>
+ <Reference Include="Ice, Version=3.4.51.0, Culture=neutral, PublicKeyToken=1f998c50fec78381, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\bin\Ice.dll</HintPath>
+ </Reference>
+ <Reference Include="IceSSL, Version=3.4.51.0, Culture=neutral, PublicKeyToken=1f998c50fec78381, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\bin\IceSSL.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ <Reference Include="UIAutomationProvider">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="WindowsBase">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="PresentationCore">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="PresentationFramework">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <ApplicationDefinition Include="App.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </ApplicationDefinition>
+ <Page Include="CancelDialog.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="ChatWindow.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="LoginDialog.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Compile Include="App.xaml.cs">
+ <DependentUpon>App.xaml</DependentUpon>
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="ChatWindow.xaml.cs">
+ <DependentUpon>ChatWindow.xaml</DependentUpon>
+ <SubType>Code</SubType>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="CancelDialog.xaml.cs">
+ <DependentUpon>CancelDialog.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Chat.cs" />
+ <Compile Include="ChatCommands.cs" />
+ <Compile Include="LoginDialog.xaml.cs">
+ <DependentUpon>LoginDialog.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ <None Include="Chat.ice" />
+ <None Include="config.client" />
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ <AppDesigner Include="Properties\" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ProjectExtensions>
+ <VisualStudio>
+ <UserProperties ZerocIce_Enabled="True" ZerocIce_Home="..\..\..\.." ZerocIce_HomeExpanded="..\..\..\.." />
+ </VisualStudio>
+ </ProjectExtensions>
+</Project>
\ No newline at end of file diff --git a/cs/demo/Glacier2/chat/LoginDialog.xaml b/cs/demo/Glacier2/chat/LoginDialog.xaml new file mode 100755 index 00000000000..6a1791f5d45 --- /dev/null +++ b/cs/demo/Glacier2/chat/LoginDialog.xaml @@ -0,0 +1,41 @@ +<!--
+// **********************************************************************
+//
+// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+-->
+<Window x:Class="Glacier2.chat.client.LoginDialog"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ Title="LoginDialog" Height="160" Width="240" ResizeMode="NoResize">
+ <Grid>
+ <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Orientation="Vertical"
+ MaxWidth="240">
+ <!-- Connection data -->
+ <StackPanel Orientation="Vertical">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock Margin="2" Name="lblHost" Width="60">Host:</TextBlock>
+ <TextBox Margin="2" Name="txtHost" Width="120"></TextBox>
+ </StackPanel>
+ <StackPanel Orientation="Horizontal">
+ <TextBlock Margin="2" Name="lblUsername" Width="60">Username:</TextBlock>
+ <TextBox Margin="2" Name="txtUsername" Width="120"></TextBox>
+ </StackPanel>
+ <StackPanel Orientation="Horizontal">
+ <TextBlock Margin="2" TextWrapping="NoWrap" Width="60">Password:</TextBlock>
+ <PasswordBox Margin="2" Name="txtPassword" Width="120"></PasswordBox>
+ </StackPanel>
+ </StackPanel>
+
+ <!-- Login / Cancel buttons -->
+ <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
+ <Button Margin="2" MaxWidth="80" Click="login" IsDefault="True">Login</Button>
+ <Button Margin="2" MaxWidth="80" Click="cancel" IsDefault="True">Cancel</Button>
+ </StackPanel>
+ </StackPanel>
+ </Grid>
+</Window>
diff --git a/cs/demo/Glacier2/chat/LoginDialog.xaml.cs b/cs/demo/Glacier2/chat/LoginDialog.xaml.cs new file mode 100755 index 00000000000..b9fbf56969e --- /dev/null +++ b/cs/demo/Glacier2/chat/LoginDialog.xaml.cs @@ -0,0 +1,63 @@ +// **********************************************************************
+//
+// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace Glacier2.chat.client
+{
+ /// <summary>
+ /// Interaction logic for LoginDialog.xaml
+ /// </summary>
+ public partial class LoginDialog : Window
+ {
+ public LoginDialog(LoginData loginData)
+ {
+ InitializeComponent();
+ _loginData = loginData;
+ txtHost.Text = _loginData.routerHost;
+ txtUsername.Text = _loginData.userName;
+ txtPassword.Password = _loginData.password;
+ }
+
+ public void login(object sender, RoutedEventArgs e)
+ {
+ _loginData.routerHost = txtHost.Text;
+ _loginData.userName = txtUsername.Text;
+ _loginData.password = txtPassword.Password;
+ _cancel = false;
+ Close();
+ }
+
+ public void cancel(object sender, RoutedEventArgs args)
+ {
+ _cancel = true;
+ Close();
+ }
+
+ public bool ShowModal()
+ {
+ ShowDialog();
+ return !_cancel;
+ }
+
+ private bool _cancel = true;
+ private LoginData _loginData;
+ }
+}
diff --git a/cs/demo/Glacier2/chat/Properties/AssemblyInfo.cs b/cs/demo/Glacier2/chat/Properties/AssemblyInfo.cs new file mode 100755 index 00000000000..2d92f4d8b8e --- /dev/null +++ b/cs/demo/Glacier2/chat/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Glacier2.chat.client")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Glacier2.chat.client")]
+[assembly: AssemblyCopyright("Copyright © 2009")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
+//inside a <PropertyGroup>. For example, if you are using US english
+//in your source files, set the <UICulture> to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/cs/demo/Glacier2/chat/Properties/Resources.Designer.cs b/cs/demo/Glacier2/chat/Properties/Resources.Designer.cs new file mode 100755 index 00000000000..a96435df6e7 --- /dev/null +++ b/cs/demo/Glacier2/chat/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.1433
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Glacier2.chat.client.Properties
+{
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Glacier2.chat.client.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/cs/demo/Glacier2/chat/Properties/Resources.resx b/cs/demo/Glacier2/chat/Properties/Resources.resx new file mode 100755 index 00000000000..ffecec851ab --- /dev/null +++ b/cs/demo/Glacier2/chat/Properties/Resources.resx @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
\ No newline at end of file diff --git a/cs/demo/Glacier2/chat/Properties/Settings.Designer.cs b/cs/demo/Glacier2/chat/Properties/Settings.Designer.cs new file mode 100755 index 00000000000..6b363ea5353 --- /dev/null +++ b/cs/demo/Glacier2/chat/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.1433
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Glacier2.chat.client.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/cs/demo/Glacier2/chat/Properties/Settings.settings b/cs/demo/Glacier2/chat/Properties/Settings.settings new file mode 100755 index 00000000000..8f2fd95d626 --- /dev/null +++ b/cs/demo/Glacier2/chat/Properties/Settings.settings @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile>
\ No newline at end of file diff --git a/cs/demo/Glacier2/chat/config.client b/cs/demo/Glacier2/chat/config.client new file mode 100755 index 00000000000..46cdd0d9b20 --- /dev/null +++ b/cs/demo/Glacier2/chat/config.client @@ -0,0 +1,39 @@ +# +# Warn about connection exceptions +# +#Ice.Warn.Connections=1 + +# +# Network Tracing +# +# 0 = no network tracing +# 1 = trace connection establishment and closure +# 2 = like 1, but more detailed +# 3 = like 2, but also trace data transfer +# +#Ice.Trace.Network=1 + +# +# Protocol Tracing +# +# 0 = no protocol tracing +# 1 = trace protocol messages +# +#Ice.Trace.Protocol=1 + +# +# Security Tracing +# +# 0 = no security tracing +# 1 = trace messages +# +#IceSSL.Trace.Security=1 + +# +# SSL Configuration +# +Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory +IceSSL.DefaultDir=../../../../certs +IceSSL.ImportCert.CurrentUser.Root=cacert.pem +IceSSL.CertFile=c_rsa1024.pfx +IceSSL.Password=password diff --git a/cs/demo/Ice/wpf/App.xaml b/cs/demo/Ice/wpf/App.xaml new file mode 100644 index 00000000000..1495236cb4e --- /dev/null +++ b/cs/demo/Ice/wpf/App.xaml @@ -0,0 +1,18 @@ +<!--
+// **********************************************************************
+//
+// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+-->
+<Application x:Class="Ice.wpf.client.App"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ StartupUri="HelloWindow.xaml">
+ <Application.Resources>
+
+ </Application.Resources>
+</Application>
diff --git a/cs/demo/Ice/wpf/App.xaml.cs b/cs/demo/Ice/wpf/App.xaml.cs new file mode 100644 index 00000000000..4f42b9a436a --- /dev/null +++ b/cs/demo/Ice/wpf/App.xaml.cs @@ -0,0 +1,25 @@ +// **********************************************************************
+//
+// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Windows;
+
+namespace Ice.wpf.client
+{
+ /// <summary>
+ /// Interaction logic for App.xaml
+ /// </summary>
+ public partial class App : System.Windows.Application
+ {
+ }
+}
diff --git a/cs/demo/Ice/wpf/Hello.ice b/cs/demo/Ice/wpf/Hello.ice new file mode 100644 index 00000000000..b5c9e4a599e --- /dev/null +++ b/cs/demo/Ice/wpf/Hello.ice @@ -0,0 +1,24 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef HELLO_ICE +#define HELLO_ICE + +module Demo +{ + +interface Hello +{ + ["ami"] idempotent void sayHello(int delay); + ["ami"] void shutdown(); +}; + +}; + +#endif diff --git a/cs/demo/Ice/wpf/HelloWindow.xaml b/cs/demo/Ice/wpf/HelloWindow.xaml new file mode 100644 index 00000000000..7202bf843ab --- /dev/null +++ b/cs/demo/Ice/wpf/HelloWindow.xaml @@ -0,0 +1,91 @@ +<!--
+// **********************************************************************
+//
+// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+-->
+<Window x:Class="Ice.wpf.client.HelloWindow"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ Title="Ice - Hello World!" SizeToContent="WidthAndHeight" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
+ Loaded="Window_Loaded" Closed="Window_Closed" Width="300" Height="190" MinWidth="300" MinHeight="190">
+ <Grid Margin="10">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+
+ <Grid Grid.Row="0" Grid.Column="0">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*"/>
+ <ColumnDefinition Width="2*"/>
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" MinHeight="23" />
+ <RowDefinition Height="Auto" MinHeight="23" />
+ <RowDefinition Height="Auto" MinHeight="28" />
+ <RowDefinition Height="Auto" MinHeight="23" />
+ </Grid.RowDefinitions>
+ <Label Grid.Row="0" Grid.Column="0" Name="label4" VerticalAlignment="Top" HorizontalAlignment="Left" Width="70" >Hostname</Label>
+ <Label Grid.Row="1" Grid.Column="0" Name="label2" VerticalAlignment="Top" HorizontalAlignment="Left" Width="70">Mode</Label>
+ <Label Grid.Row="2" Grid.Column="0" Name="label1" Height="28" HorizontalAlignment="Left" VerticalAlignment="Top" Width="70">Timeout</Label>
+ <Label Grid.Row="3" Grid.Column="0" Name="label3" VerticalAlignment="Top" HorizontalAlignment="Left" Width="70">Delay</Label>
+
+ <TextBox Grid.Row="0" Grid.Column="1" Name="hostname" VerticalAlignment="Top">127.0.0.1</TextBox>
+ <ComboBox Grid.Row="1" Grid.Column="1" Name="deliveryMode" VerticalAlignment="Top" IsReadOnly="True" SelectedIndex="0">
+ <ComboBoxItem>Twoway</ComboBoxItem>
+ <ComboBoxItem>Twoway Secure</ComboBoxItem>
+ <ComboBoxItem>Oneway</ComboBoxItem>
+ <ComboBoxItem>Oneway Batch</ComboBoxItem>
+ <ComboBoxItem>Oneway Secure</ComboBoxItem>
+ <ComboBoxItem>Oneway Secure Batch</ComboBoxItem>
+ <ComboBoxItem>Datagram</ComboBoxItem>
+ <ComboBoxItem>Datagram Batch</ComboBoxItem>
+ </ComboBox>
+ <Grid Grid.Row="2" Grid.Column="1">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="4*"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+ <Slider Grid.Row="0" Grid.Column="0" Name="timeoutSlider" VerticalAlignment="Top" Maximum="5000" Height="22" ValueChanged="timeoutSlider_ValueChanged" />
+ <Label Grid.Row="0" Grid.Column="1" Name="timeoutLabel" VerticalAlignment="Top" HorizontalAlignment="Left">0.0</Label>
+ </Grid>
+ <Grid Grid.Row="3" Grid.Column="1">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="4*"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+ <Slider Grid.Row="0" Grid.Column="0" Name="delaySlider" VerticalAlignment="Top" Maximum="5000" Height="22" ValueChanged="delaySlider_ValueChanged" />
+ <Label Grid.Row="0" Grid.Column="1" Name="delayLabel" VerticalAlignment="Top" HorizontalAlignment="Left">0.0</Label>
+ </Grid>
+ </Grid>
+ <Grid Grid.Row="1" Grid.Column="0" Margin="0 10 0 5">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*"/>
+ <ColumnDefinition Width="*"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+ <Button Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center" Name="sayHello" Click="sayHello_Click">Hello World!</Button>
+ <Button Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" Name="shutdown" Click="shutdown_Click">Shutdown</Button>
+ <Button Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center" Name="flush" Click="flush_Click">Flush</Button>
+ </Grid>
+ <Label Grid.Row="2" Grid.Column="0" Name="status">Ready</Label>
+ </Grid>
+</Window>
diff --git a/cs/demo/Ice/wpf/HelloWindow.xaml.cs b/cs/demo/Ice/wpf/HelloWindow.xaml.cs new file mode 100644 index 00000000000..ed71cad4e14 --- /dev/null +++ b/cs/demo/Ice/wpf/HelloWindow.xaml.cs @@ -0,0 +1,358 @@ +// **********************************************************************
+//
+// Copyright(c) 2003-2009 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using System.Windows.Threading;
+using System.Diagnostics;
+
+namespace Ice.wpf.client
+{
+ /// <summary>
+ /// Interaction logic for HelloWindow.xaml
+ /// </summary>
+ public partial class HelloWindow : Window
+ {
+ public HelloWindow()
+ {
+ InitializeComponent();
+ locateOnScreen(this);
+ }
+
+ static String TWOWAY = "Twoway";
+ static String TWOWAY_SECURE = "Twoway Secure";
+ static String ONEWAY = "Oneway";
+ static String ONEWAY_BATCH = "Oneway Batch";
+ static String ONEWAY_SECURE = "Oneway Secure";
+ static String ONEWAY_SECURE_BATCH = "Oneway Secure Batch";
+ static String DATAGRAM = "Datagram";
+ static String DATAGRAM_BATCH = "Datagram Batch";
+
+ private void Window_Loaded(object sender, EventArgs e)
+ {
+ try
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.properties = Ice.Util.createProperties();
+ initData.properties.load("config.client");
+ _communicator = Ice.Util.initialize(initData);
+ }
+ catch(Ice.LocalException ex)
+ {
+ handleException(ex);
+ }
+ }
+
+ private void Window_Closed(object sender, EventArgs e)
+ {
+ if(_communicator == null)
+ {
+ return;
+ }
+
+ _communicator.destroy();
+ _communicator = null;
+ }
+
+ private bool deliveryModeIsBatch()
+ {
+ return deliveryMode.Text.Equals(ONEWAY_BATCH) ||
+ deliveryMode.Text.Equals(ONEWAY_SECURE_BATCH) ||
+ deliveryMode.Text.Equals(DATAGRAM_BATCH);
+ }
+
+ private Ice.ObjectPrx deliveryModeApply(Ice.ObjectPrx prx)
+ {
+ if(deliveryMode.Text.Equals(TWOWAY))
+ {
+ prx = prx.ice_twoway();
+ }
+ else if(deliveryMode.Text.Equals(TWOWAY_SECURE))
+ {
+ prx = prx.ice_twoway().ice_secure(true);
+ }
+ else if(deliveryMode.Text.Equals(ONEWAY))
+ {
+ prx = prx.ice_oneway();
+ }
+ else if(deliveryMode.Text.Equals(ONEWAY_BATCH))
+ {
+ prx = prx.ice_batchOneway();
+ }
+ else if(deliveryMode.Text.Equals(ONEWAY_SECURE))
+ {
+ prx = prx.ice_oneway().ice_secure(true);
+ }
+ else if(deliveryMode.Text.Equals(ONEWAY_SECURE_BATCH))
+ {
+ prx = prx.ice_batchOneway().ice_secure(true);
+ }
+ else if(deliveryMode.Text.Equals(DATAGRAM))
+ {
+ prx = prx.ice_datagram();
+ }
+ else if(deliveryMode.Text.Equals(DATAGRAM_BATCH))
+ {
+ prx = prx.ice_batchDatagram();
+ }
+
+ return prx;
+ }
+
+ class SayHelloI : Demo.AMI_Hello_sayHello, Ice.AMISentCallback
+ {
+ public SayHelloI(HelloWindow window)
+ {
+ _window = window;
+ }
+
+ public override void ice_response()
+ {
+ lock(this)
+ {
+ Debug.Assert(!_response);
+ _response = true;
+ _window.Dispatcher.BeginInvoke(DispatcherPriority.Normal,(Action)delegate()
+ {
+ _window.status.Content = "Ready";
+ });
+ }
+ }
+
+ public override void ice_exception(Exception ex)
+ {
+ lock(this)
+ {
+ Debug.Assert(!_response);
+ _response = true;
+ _window.Dispatcher.BeginInvoke(DispatcherPriority.Normal,(Action)delegate()
+ {
+ _window.handleException(ex);
+ });
+ }
+ }
+
+ #region AMISentCallback Members
+
+ public void ice_sent()
+ {
+ lock(this)
+ {
+ if(_response)
+ {
+ return;
+ }
+ _window.Dispatcher.BeginInvoke(DispatcherPriority.Normal,(Action)delegate()
+ {
+ if(_window.deliveryMode.Text.Equals(TWOWAY) || _window.deliveryMode.Text.Equals(TWOWAY_SECURE))
+ {
+ _window.status.Content = "Waiting for response";
+ }
+ else
+ {
+ _window.status.Content = "Ready";
+ }
+ });
+ }
+ }
+
+ #endregion
+
+ private bool _response = false;
+ private HelloWindow _window;
+ }
+
+ private void sayHello_Click(object sender, RoutedEventArgs e)
+ {
+ Demo.HelloPrx hello = createProxy();
+ if(hello == null)
+ {
+ return;
+ }
+
+ int delay =(int)delaySlider.Value;
+ try
+ {
+ if(!deliveryModeIsBatch())
+ {
+ if(hello.sayHello_async(new SayHelloI(this), delay))
+ {
+ if(deliveryMode.Text.Equals(TWOWAY) || deliveryMode.Text.Equals(TWOWAY_SECURE))
+ {
+ status.Content = "Waiting for response";
+ }
+ }
+ else
+ {
+ status.Content = "Sending request";
+ }
+ }
+ else
+ {
+ flush.IsEnabled = true;
+ hello.sayHello(delay);
+ status.Content = "Queued sayHello request";
+ }
+ }
+ catch(Ice.LocalException ex)
+ {
+ handleException(ex);
+ }
+ }
+
+ private void handleException(Exception ex)
+ {
+ this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,(Action)delegate()
+ {
+ status.Content = ex.GetType();
+ });
+ }
+
+ class ShutdownI : Demo.AMI_Hello_shutdown
+ {
+ public ShutdownI(HelloWindow window)
+ {
+ _window = window;
+ }
+
+ public override void ice_response()
+ {
+ lock(this)
+ {
+ _window.Dispatcher.BeginInvoke(DispatcherPriority.Normal,(Action)delegate()
+ {
+ _window.status.Content = "Ready";
+ });
+ }
+ }
+
+ public override void ice_exception(Exception ex)
+ {
+ lock(this)
+ {
+ _window.Dispatcher.BeginInvoke(DispatcherPriority.Normal,(Action)delegate()
+ {
+ _window.handleException(ex);
+ });
+ }
+ }
+
+ private HelloWindow _window;
+ }
+
+ private void shutdown_Click(object sender, RoutedEventArgs e)
+ {
+ Demo.HelloPrx hello = createProxy();
+ if(hello == null)
+ {
+ return;
+ }
+
+ int delay =(int)delaySlider.Value;
+
+ try
+ {
+ if(!deliveryModeIsBatch())
+ {
+ if(hello.shutdown_async(new ShutdownI(this)))
+ {
+ if(deliveryMode.Text.Equals("Twoway") || deliveryMode.Text.Equals("Twoway Secure"))
+ {
+ status.Content = "Waiting for response";
+ }
+ }
+ else
+ {
+ status.Content = "Sending request";
+ }
+ }
+ else
+ {
+ flush.IsEnabled = true;
+ hello.shutdown();
+ status.Content = "Queued shutdown request";
+ }
+ }
+ catch(Ice.LocalException ex)
+ {
+ handleException(ex);
+ }
+ }
+
+ private void flush_Click(object sender, RoutedEventArgs e)
+ {
+ new System.Threading.Thread(new System.Threading.ThreadStart(delegate()
+ {
+ try
+ {
+ _communicator.flushBatchRequests();
+ }
+ catch(Ice.LocalException ex)
+ {
+ this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,(Action)delegate()
+ {
+ handleException(ex);
+ });
+ }
+ })).Start();
+ flush.IsEnabled = false;
+ status.Content = "Flushed batch requests";
+ }
+
+ Demo.HelloPrx
+ createProxy()
+ {
+ String host = hostname.Text.Trim();
+ if(host.Length == 0)
+ {
+ status.Content = "No hostname";
+ return null;
+ }
+
+ String s = "hello:tcp -h " + host + " -p 10000:ssl -h " + host + " -p 10001:udp -h " + host + " -p 10000";
+ Ice.ObjectPrx prx = _communicator.stringToProxy(s);
+ prx = deliveryModeApply(prx);
+ int timeout =(int)timeoutSlider.Value;
+ if(timeout != 0)
+ {
+ prx = prx.ice_timeout(timeout);
+ }
+ return Demo.HelloPrxHelper.uncheckedCast(prx);
+ }
+
+ private void timeoutSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
+ {
+ timeoutLabel.Content =(timeoutSlider.Value / 1000.0).ToString("F1");
+ }
+
+ private void delaySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
+ {
+ delayLabel.Content =(delaySlider.Value / 1000.0).ToString("F1");
+ }
+
+ static private void locateOnScreen(System.Windows.Window window)
+ {
+ window.Left =(System.Windows.SystemParameters.PrimaryScreenWidth - window.Width) / 2;
+ window.Top =(System.Windows.SystemParameters.PrimaryScreenHeight - window.Height) / 2;
+ }
+
+ private Ice.Communicator _communicator = null;
+ }
+}
diff --git a/cs/demo/Ice/wpf/Ice.wpf.client.csproj b/cs/demo/Ice/wpf/Ice.wpf.client.csproj new file mode 100644 index 00000000000..8332c86fbf4 --- /dev/null +++ b/cs/demo/Ice/wpf/Ice.wpf.client.csproj @@ -0,0 +1,154 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{1EB710F0-E760-499B-BFD6-24E3B7A132E8}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Ice.wpf.client</RootNamespace>
+ <AssemblyName>client</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <WarningLevel>4</WarningLevel>
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>.\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Ice, Version=3.4.51.0, Culture=neutral, PublicKeyToken=1f998c50fec78381, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\bin\Ice.dll</HintPath>
+ </Reference>
+ <Reference Include="IceSSL, Version=3.4.51.0, Culture=neutral, PublicKeyToken=1f998c50fec78381, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\bin\IceSSL.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ <Reference Include="WindowsBase" />
+ <Reference Include="PresentationCore" />
+ <Reference Include="PresentationFramework" />
+ </ItemGroup>
+ <ItemGroup>
+ <ApplicationDefinition Include="App.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </ApplicationDefinition>
+ <Page Include="HelloWindow.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Compile Include="App.xaml.cs">
+ <DependentUpon>App.xaml</DependentUpon>
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="HelloWindow.xaml.cs">
+ <DependentUpon>HelloWindow.xaml</DependentUpon>
+ <SubType>Code</SubType>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Hello.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ <None Include="Hello.ice" />
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ <AppDesigner Include="Properties\" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ProjectExtensions>
+ <VisualStudio>
+ <UserProperties ZerocIce_Home="..\..\..\.." ZerocIce_HomeExpanded="..\..\..\.." ZerocIce_Enabled="True" />
+ </VisualStudio>
+ </ProjectExtensions>
+</Project>
\ No newline at end of file diff --git a/cs/demo/Ice/wpf/Properties/AssemblyInfo.cs b/cs/demo/Ice/wpf/Properties/AssemblyInfo.cs new file mode 100755 index 00000000000..83b624aa550 --- /dev/null +++ b/cs/demo/Ice/wpf/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Ice.wpf.client")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Ice.wpf.client")]
+[assembly: AssemblyCopyright("Copyright © 2009")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
+//inside a <PropertyGroup>. For example, if you are using US english
+//in your source files, set the <UICulture> to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/cs/demo/Ice/wpf/Properties/Resources.Designer.cs b/cs/demo/Ice/wpf/Properties/Resources.Designer.cs new file mode 100755 index 00000000000..f40e7d965b2 --- /dev/null +++ b/cs/demo/Ice/wpf/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.1433
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Ice.wpf.client.Properties
+{
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Ice.wpf.client.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/cs/demo/Ice/wpf/Properties/Resources.resx b/cs/demo/Ice/wpf/Properties/Resources.resx new file mode 100755 index 00000000000..ffecec851ab --- /dev/null +++ b/cs/demo/Ice/wpf/Properties/Resources.resx @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root>
\ No newline at end of file diff --git a/cs/demo/Ice/wpf/Properties/Settings.Designer.cs b/cs/demo/Ice/wpf/Properties/Settings.Designer.cs new file mode 100755 index 00000000000..f3bff7a3a95 --- /dev/null +++ b/cs/demo/Ice/wpf/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.1433
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Ice.wpf.client.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/cs/demo/Ice/wpf/Properties/Settings.settings b/cs/demo/Ice/wpf/Properties/Settings.settings new file mode 100755 index 00000000000..8f2fd95d626 --- /dev/null +++ b/cs/demo/Ice/wpf/Properties/Settings.settings @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile>
\ No newline at end of file diff --git a/cs/demo/Ice/wpf/config.client b/cs/demo/Ice/wpf/config.client new file mode 100644 index 00000000000..35fc5c8b060 --- /dev/null +++ b/cs/demo/Ice/wpf/config.client @@ -0,0 +1,45 @@ +# +# The client reads this property to create the reference to the +# "hello" object in the server. +# +Hello.Proxy=hello:tcp -p 10000:udp -p 10000:ssl -p 10001 + +# +# Warn about connection exceptions. +# +Ice.Warn.Connections=1 + +# +# Network Tracing +# +# 0 = no network tracing +# 1 = trace connection establishment and closure +# 2 = like 1, but more detailed +# 3 = like 2, but also trace data transfer +# +#Ice.Trace.Network=1 + +# +# Protocol Tracing +# +# 0 = no protocol tracing +# 1 = trace protocol messages +# +#Ice.Trace.Protocol=1 + +# +# Security Tracing +# +# 0 = no security tracing +# 1 = trace messages +# +#IceSSL.Trace.Security=1 + +# +# SSL Configuration +# +Ice.Plugin.IceSSL=IceSSL:IceSSL.PluginFactory +IceSSL.DefaultDir=../../../../certs +IceSSL.ImportCert.CurrentUser.Root=cacert.pem +IceSSL.CertFile=c_rsa1024.pfx +IceSSL.Password=password diff --git a/cs/demo/demo.sln b/cs/demo/demo.sln index 0e56951020e..898f59a661c 100755 --- a/cs/demo/demo.sln +++ b/cs/demo/demo.sln @@ -169,6 +169,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ice.plugin.server", "Ice\pl EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ice.plugin.hello", "Ice\plugin\Ice.plugin.hello.csproj", "{8D371651-BFA4-43C9-B143-77F0CCEEBB10}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ice.wpf.client", "Ice\wpf\Ice.wpf.client.csproj", "{1EB710F0-E760-499B-BFD6-24E3B7A132E8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Glacier2.chat.client", "Glacier2\chat\Glacier2.chat.client.csproj", "{53DCED47-A722-48EF-86D8-A10AD0594F21}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -363,6 +367,14 @@ Global {8D371651-BFA4-43C9-B143-77F0CCEEBB10}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D371651-BFA4-43C9-B143-77F0CCEEBB10}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D371651-BFA4-43C9-B143-77F0CCEEBB10}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1EB710F0-E760-499B-BFD6-24E3B7A132E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1EB710F0-E760-499B-BFD6-24E3B7A132E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1EB710F0-E760-499B-BFD6-24E3B7A132E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1EB710F0-E760-499B-BFD6-24E3B7A132E8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {53DCED47-A722-48EF-86D8-A10AD0594F21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {53DCED47-A722-48EF-86D8-A10AD0594F21}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {53DCED47-A722-48EF-86D8-A10AD0594F21}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {53DCED47-A722-48EF-86D8-A10AD0594F21}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/cs/src/Glacier2/Application.cs b/cs/src/Glacier2/Application.cs new file mode 100644 index 00000000000..a082f943af0 --- /dev/null +++ b/cs/src/Glacier2/Application.cs @@ -0,0 +1,508 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +using System; +using System.Diagnostics; +using System.Collections.Generic; +using System.Threading; + +namespace Glacier2 +{ + +/// <sumary> +/// Utility base class that makes it easy to to correctly initialize and finalize +/// the Ice run time, as well as handle signals. Unless the application specifies +/// a logger, Application installs a per-process logger that logs to the standard +/// error output. +/// +/// Applications must create a derived class that implements the {@link #run} method. +/// +/// A program can contain only one instance of this class. +/// </sumary> +public abstract class Application : Ice.Application +{ + /// <sumary> + /// This exception is raised if the session should be restarted. + /// </sumary> + public class RestartSessionException : System.Exception + { + } + + /// <sumary> + /// Initializes an instance that calls Communicator.shutdown if + /// a signal is received. + /// </sumary> + public + Application() + { + } + + /// <sumary> + /// Initializes an instance that handles signals according to the signal + /// policy. + /// </sumary> + /// <param name="signalPolicy">@param signalPolicy Determines how to + /// respond to signals.</param> + public + Application(Ice.SignalPolicy signalPolicy) : base(signalPolicy) + { + } + + + /// <sumary> + /// Called once the communicator has been initialized and the Glacier2 session + /// has been established. A derived class must implement <code>runWithSession</code>, + /// which is the application's starting method. + /// </sumary> + /// <param name="args"> The argument vector for the application. Application + /// scans the argument vector passed to <code>main</code> for options that are + /// specific to the Ice run time and removes them; therefore, the vector passed + /// to <code>run</code> is free from Ice-related options and contains only options + /// and arguments that are application-specific.</param> + /// + /// <returns> The runWithSession method should return zero for successful + /// termination, and non-zero otherwise. Application.main returns the + /// value returned by runWithSession.</returns> + /// + public abstract int + runWithSession(string[] args); + + /// <sumary> + /// Run should not be overridden for Glacier2.Application. Instead + /// runWithSession should be used. + /// </sumary> + public override int + run(string[] args) + { + // This shouldn't be called. + Debug.Assert(false); + return 0; + } + + /// <sumary> + /// Called to restart the application's Glacier2 session. This + /// method never returns. + /// </sumary> + /// <returns>throws RestartSessionException This exception is + /// always thrown.</returns> + /// + public void + restart() + { + throw new RestartSessionException(); + } + + /// <sumary> + /// Creates a new Glacier2 session. A call to createSession always + /// precedes a call to runWithSession. If Ice.LocalException is thrown + /// from this method, the application is terminated. + /// </sumary> + /// <returns> The Glacier2 session.</returns> + public abstract Glacier2.SessionPrx + createSession(); + + /// <sumary> + /// Called when the base class detects that the session has been destroyed. + /// A subclass can override this method to take action after the loss of + /// connectivity with the Glacier2 router. + /// </sumary> + public virtual void + sessionDestroyed() + { + } + + /// <sumary> + /// Returns the Glacier2 router proxy + /// </sumary> + /// <returns>The router proxy.</returns> + public static Glacier2.RouterPrx + router() + { + return _router; + } + + /// <sumary> + /// Returns the Glacier2 session proxy + /// </sumary> + /// <returns>The session proxy.</returns> + public static Glacier2.SessionPrx + session() + { + return _session; + } + + /// <sumary> + /// Returns the category to be used in the identities of all of the client's + /// callback objects. Clients must use this category for the router to + /// forward callback requests to the intended client. + /// Throws SessionNotExistException if no session exists. + /// </sumary> + /// <returns>The category.</returns> + public string + categoryForClient() + { + if(_router == null) + { + throw new SessionNotExistException(); + } + return router().getCategoryForClient(); + } + + /// <sumary> + /// Create a new Ice identity for callback objects with the given + /// identity name field. + /// </sumary> + /// <returns>The identity.</returns> + public Ice.Identity + createCallbackIdentity(string name) + { + return new Ice.Identity(name, categoryForClient()); + } + + /// <sumary> + /// Adds a servant to the callback object adapter's Active Servant Map with a UUID. + /// </sumary> + /// <param name="servant">The servant to add.</param> + /// <returns>The proxy for the servant.</returns> + public Ice.ObjectPrx + addWithUUID(Ice.Object servant) + { + return objectAdapter().add(servant, createCallbackIdentity(Guid.NewGuid().ToString())); + } + + /// <sumary> + /// Creates an object adapter for callback objects. + /// </sumary> + /// <returns>The object adapter.</returns> + public Ice.ObjectAdapter + objectAdapter() + { + lock(this) + { + if(_adapter == null) + { + if(_router == null) + { + throw new SessionNotExistException(); + } + // TODO: Depending on the resolution of + // http://bugzilla/bugzilla/show_bug.cgi?id=4264 the OA + // name could be an empty string. + _adapter = communicator().createObjectAdapterWithRouter(Guid.NewGuid().ToString(), _router); + _adapter.activate(); + } + return _adapter; + } + } + + private class SessionPingThread + { + public SessionPingThread(Application app, Glacier2.RouterPrx router, long period) + { + _app = app; + _router = router; + _period = period; + _done = false; + } + + private class AMI_Router_refreshSessionI : Glacier2.AMI_Router_refreshSession + { + public AMI_Router_refreshSessionI(Application app, SessionPingThread ping) + { + _app = app; + _ping = ping; + } + + public override void + ice_response() + { + } + + public override void + ice_exception(Ice.Exception ex) + { + // Here the session has gone. The thread + // terminates, and we notify the + // application that the session has been + // destroyed. + _ping.done(); + _app.sessionDestroyed(); + } + + private SessionPingThread _ping; + private Application _app; + } + + public void + run() + { + lock(this) + { + while(!_done) + { + _router.refreshSession_async(new AMI_Router_refreshSessionI(_app, this)); + if(!_done) + { + Monitor.Wait(this, (int)_period); + } + } + } + } + + public void + done() + { + lock(this) + { + if(!_done) + { + _done = true; + Monitor.PulseAll(this); + } + } + } + + private Application _app; + private Glacier2.RouterPrx _router; + private long _period; + private bool _done = false; + } + + protected override int + doMain(string[] originArgs, Ice.InitializationData initData) + { + // Set the default properties for all Glacier2 applications. + initData.properties.setProperty("Ice.ACM.Client", "0"); + initData.properties.setProperty("Ice.RetryIntervals", "-1"); + + bool restart; + int ret = 0; + do + { + // A copy of the initialization data and the string seq + // needs to be passed to doMainInternal, as these can be + // changed by the application. + Ice.InitializationData id = (Ice.InitializationData)initData.Clone(); + id.properties = id.properties.ice_clone_(); + string[] args = (string[]) originArgs.Clone(); + + restart = doMain(args, id, out ret); + } + while(restart); + return ret; + } + + private bool + doMain(string[] args, Ice.InitializationData initData, out int status) + { + // Reset internal state variables from Ice.Application. The + // remainder are reset at the end of this method. + callbackInProgress__ = false; + destroyed__ = false; + interrupted__ = false; + + bool restart = false; + status = 0; + + SessionPingThread ping = null; + Thread pingThread = null; + try + { + communicator__ = Ice.Util.initialize(ref args, initData); + + _router = Glacier2.RouterPrxHelper.uncheckedCast(communicator().getDefaultRouter()); + if(_router == null) + { + Ice.Util.getProcessLogger().error(appName__ + ": no glacier2 router configured"); + status = 1; + } + else + { + // + // The default is to destroy when a signal is received. + // + if(signalPolicy__ == Ice.SignalPolicy.HandleSignals) + { + destroyOnInterrupt(); + } + + // If createSession throws, we're done. + try + { + _session = createSession(); + _createdSession = true; + } + catch(Ice.LocalException ex) + { + Ice.Util.getProcessLogger().error(ex.ToString()); + status = 1; + } + + if(_createdSession) + { + ping = new SessionPingThread(this, _router, (_router.getSessionTimeout() * 1000) / 2); + pingThread = new Thread(new ThreadStart(ping.run)); + pingThread.Start(); + status = runWithSession(args); + } + } + } + // We want to restart on those exceptions which indicate a + // break down in communications, but not those exceptions that + // indicate a programming logic error (ie: marshal, protocol + // failure, etc). + catch(RestartSessionException ex) + { + Ice.Util.getProcessLogger().error(ex.ToString()); + restart = true; + } + catch(Ice.ConnectionRefusedException ex) + { + Ice.Util.getProcessLogger().error(ex.ToString()); + restart = true; + } + catch(Ice.ConnectionLostException ex) + { + Ice.Util.getProcessLogger().error(ex.ToString()); + restart = true; + } + catch(Ice.UnknownLocalException ex) + { + Ice.Util.getProcessLogger().error(ex.ToString()); + restart = true; + } + catch(Ice.RequestFailedException ex) + { + Ice.Util.getProcessLogger().error(ex.ToString()); + restart = true; + } + catch(Ice.TimeoutException ex) + { + Ice.Util.getProcessLogger().error(ex.ToString()); + restart = true; + } + catch(Ice.LocalException ex) + { + Ice.Util.getProcessLogger().error(ex.ToString()); + status = 1; + } + catch(System.Exception ex) + { + Ice.Util.getProcessLogger().error("unknown exception" + ex.ToString()); + status = 1; + } + + // + // Don't want any new interrupt. And at this point + // (post-run), it would not make sense to release a held + // signal to run shutdown or destroy. + // + if(signalPolicy__ == Ice.SignalPolicy.HandleSignals) + { + ignoreInterrupt(); + } + + lock(mutex__) + { + while(callbackInProgress__) + { + Monitor.Wait(mutex__); + } + + if(destroyed__) + { + communicator__ = null; + } + else + { + destroyed__ = true; + // + // And communicator__ != null, meaning will be + // destroyed next, destroyed__ = true also ensures that + // any remaining callback won't do anything + // + } + } + + if(ping != null) + { + ping.done(); + ping = null; + while(true) + { + try + { + pingThread.Join(); + break; + } + catch(ThreadInterruptedException) + { + } + } + pingThread = null; + } + + if(_createdSession && _router != null) + { + try + { + _router.destroySession(); + } + catch(Ice.ConnectionLostException) + { + // Expected: the router closed the connection. + } + catch(Glacier2.SessionNotExistException) + { + // This can also occur. + } + catch(System.Exception ex) + { + // Not expected. + Ice.Util.getProcessLogger().error("unexpected exception when destroying the session" + ex.ToString()); + } + _router = null; + } + + if(communicator__ != null) + { + try + { + communicator__.destroy(); + } + catch(Ice.LocalException ex) + { + Ice.Util.getProcessLogger().error(ex.ToString()); + status = 1; + } + catch(System.Exception ex) + { + Ice.Util.getProcessLogger().error("unknown exception " + ex.ToString()); + status = 1; + } + communicator__ = null; + } + + // Reset internal state. We cannot reset the Application state + // here, since destroyed__ must remain true until we re-run + // this method. + _adapter = null; + _router = null; + _session = null; + _createdSession = false; + + return restart; + } + + private static Ice.ObjectAdapter _adapter; + private static Glacier2.RouterPrx _router; + private static Glacier2.SessionPrx _session; + private static bool _createdSession = false; +} +}
\ No newline at end of file diff --git a/cs/src/Glacier2/Makefile b/cs/src/Glacier2/Makefile index 02031b947ef..f82d108bf6e 100644 --- a/cs/src/Glacier2/Makefile +++ b/cs/src/Glacier2/Makefile @@ -14,7 +14,8 @@ LIBNAME = $(PKG).dll TARGETS = $(bindir)/$(LIBNAME) POLICY_TARGET = $(POLICY).dll -SRCS = AssemblyInfo.cs +SRCS = AssemblyInfo.cs \ + Application.cs SLICE_SRCS = $(SDIR)/PermissionsVerifier.ice \ $(SDIR)/Router.ice \ diff --git a/cs/src/Glacier2/Makefile.mak b/cs/src/Glacier2/Makefile.mak index e89d2930bfe..8876f7e9336 100644 --- a/cs/src/Glacier2/Makefile.mak +++ b/cs/src/Glacier2/Makefile.mak @@ -14,7 +14,10 @@ LIBNAME = $(PKG).dll TARGETS = $(bindir)\$(LIBNAME)
POLICY_TARGET = $(POLICY).dll
-SRCS = AssemblyInfo.cs
+SRCS = SessionFactoryHelper.cs \
+ SessionHelper.cs \
+ Application.cs \
+ AssemblyInfo.cs
GEN_SRCS = $(GDIR)\PermissionsVerifier.cs \
$(GDIR)\Router.cs \
@@ -28,7 +31,7 @@ GDIR = generated MCSFLAGS = $(MCSFLAGS) -target:library -out:$(TARGETS) -warnaserror-
MCSFLAGS = $(MCSFLAGS) -keyfile:$(KEYFILE)
-MCSFLAGS = $(MCSFLAGS) /doc:$(bindir)\$(PKG).xml /nowarn:1591
+MCSFLAGS = $(MCSFLAGS) /doc:$(bindir)\$(PKG).xml /nowarn:1591 -r:WindowsBase.dll
SLICE2CSFLAGS = $(SLICE2CSFLAGS) -I$(slicedir)
diff --git a/cs/src/Glacier2/SessionFactoryHelper.cs b/cs/src/Glacier2/SessionFactoryHelper.cs new file mode 100644 index 00000000000..1f939a27422 --- /dev/null +++ b/cs/src/Glacier2/SessionFactoryHelper.cs @@ -0,0 +1,360 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +using System; +using System.Text; + +namespace Glacier2 +{ + +/// <sumary> +/// A helper class for using Glacier2 with GUI applications. +/// +/// Applications should create a session factory for each Glacier2 router to which the application will +/// connect. To connect with the Glacier2 router, call SessionFactory.connect. The callback object is +/// notified of the various life cycle events. Once the session is torn down for whatever reason, the application +/// can use the session factory to create another connection. +/// </sumary> +public class SessionFactoryHelper +{ + /// <sumary> + /// A callback class to get notifications of status changes in the Glacier2 session. + /// All callbacks on the <code>Callback</code> interface occur in the main swing thread. + /// </sumary> + public interface Callback + { + /// <sumary> + /// Notifies the application that the communicator was created. + /// </sumary> + /// <param name="session">The Glacier2 session.</param> + void + createdCommunicator(SessionHelper session); + + /// <sumary> + /// Notifies the application that the Glacier2 session has been established. + /// </sumary> + /// <param name="session">The established session.</param> + void + connected(SessionHelper session); + + /// <sumary> + /// Notifies the application that the Glacier2 session has been disconnected. + /// </sumary> + /// <param name="session">The disconnected session.</param> + void + disconnected(SessionHelper session); + + /// <sumary> + /// Notifies the application that the Glacier2 session establishment failed. + /// </sumary> + /// <param name="session">The session reporting the connection failure.</param> + /// <param name="ex">The exception.</param> + void + connectFailed(SessionHelper session, Exception ex); + + System.Windows.Threading.Dispatcher + getDispatcher(); + } + + /// <sumary> + /// Creates a SessionFactory object. + /// </sumary> + /// <param name="callback">The callback object for notifications.</param> + public + SessionFactoryHelper(Callback callback) + { + _callback = callback; + _initData = new Ice.InitializationData(); + _initData.properties = Ice.Util.createProperties(); + setDefaultProperties(); + } + + /// <sumary> + /// Creates a SessionFactory object. + /// </sumary> + /// <param name="initData">The initialization data to use when creating the communicator.</param> + /// <param name="callback">The callback object for notifications.</param> + public + SessionFactoryHelper(Ice.InitializationData initData, Callback callback) + { + _callback = callback; + _initData = initData; + setDefaultProperties(); + } + + /// <sumary> + /// Creates a SessionFactory object. + /// </sumary> + /// <param name="properties">The properties to use when creating the communicator.</param> + /// <param name="callback">The callback object for notifications.</param> + public + SessionFactoryHelper(Ice.Properties properties, Callback callback) + { + _callback = callback; + _initData = new Ice.InitializationData(); + _initData.properties = properties; + setDefaultProperties(); + } + + /// <sumary> + /// Set the router object identity. + /// </sumary> + public void + setRouterIdentity(Ice.Identity identity) + { + lock(this) + { + _identity = identity; + } + } + + /// <sumary> + /// Returns the object identity of the Glacier2 router. + /// </sumary> + /// <returns> The Glacier2 router's identity.</returns> + public Ice.Identity + getRouterIdentity() + { + lock(this) + { + return _identity; + } + } + + /// <sumary> + /// Sets the host on which the Glacier2 router runs. + /// </sumary> + /// <param name="hostname">The host name (or IP address) of the router host.</param> + public void + setRouterHost(string hostname) + { + lock(this) + { + _routerHost = hostname; + } + } + + /// <sumary> + /// Returns the host on which the Glacier2 router runs. + /// </sumary> + /// <returns>The Glacier2 router host.</returns> + public string + getRouterHost() + { + lock(this) + { + return _routerHost; + } + } + + /// <sumary> + /// Sets whether to connect with the Glacier2 router securely. + /// </sumary> + /// <param name="secure">If true, the client connects to the router + /// via SSL; otherwise, the client connects via TCP.</param> + public void + setSecure(bool secure) + { + lock(this) + { + _secure = secure; + } + } + + /// <sumary> + /// Returns whether the session factory will establish a secure connection to the Glacier2 router. + /// </sumary> + /// <returns>The secure flag.</returns> + public bool + getSecure() + { + lock(this) + { + return _secure; + } + } + + /// <sumary> + /// Sets the connect and connection timeout for the Glacier2 router. + /// </sumary> + /// <param name="timeoutMillisecs">The timeout in milliseconds. A zero + /// or negative timeout value indicates that the router proxy has no + /// associated timeout.</param> + public void + setTimeout(int timeoutMillisecs) + { + lock(this) + { + _timeout = timeoutMillisecs; + } + } + + /// <sumary> + /// Returns the connect and connection timeout associated with the Glacier2 router. + /// </sumary> + /// <returns>The timeout.</returns> + public int + getTimeout() + { + lock(this) + { + return _timeout; + } + } + + /// <sumary> + /// Sets the Glacier2 router port to connect to. + /// </sumary> + /// <param name="port">The port. If 0, then the default port (4063 for TCP or + /// 4064 for SSL) is used.</param> + public void + setPort(int port) + { + lock(this) + { + _port = port; + } + } + + /// <sumary> + /// Returns the Glacier2 router port to connect to. + /// </sumary> + /// <returns>The port.</returns> + public int + getPort() + { + lock(this) + { + return _port == 0 ? (_secure ? GLACIER2_TCP_PORT : GLACIER2_SSL_PORT) : _port; + } + } + + /** + * Returns the initialization data used to initialize the communicator. + * + * @return The initialization data. + */ + public Ice.InitializationData + getInitializationData() + { + lock(this) + { + return _initData; + } + } + + /// <sumary> + /// Connects to the Glacier2 router using the associated SSL credentials. + /// + /// Once the connection is established, Callback.connected is called on + /// the callback object; upon failure, Callback.connectFailed is called + /// with the exception. + /// </sumary> + /// <returns>The connected session.</returns> + public SessionHelper + connect() + { + lock(this) + { + SessionHelper session = new SessionHelper(_callback, createInitData()); + session.connect(); + return session; + } + } + + /// <sumary> + /// Connect the Glacier2 session using user name and password credentials. + /// + /// Once the connection is established, Callback.connected is called on + /// the callback object; upon failure, Callback.connectFailed is called + /// with the exception. + /// </sumary> + /// <param name="username">The user name.</param> + /// <param name="password">The password.</param> + /// <returns>The connected session.</returns> + public SessionHelper + connect( string username, string password) + { + lock(this) + { + SessionHelper session = new SessionHelper(_callback, createInitData()); + session.connect(username, password); + return session; + } + } + + private Ice.InitializationData + createInitData() + { + // Clone the initialization data and properties. + Ice.InitializationData initData = (Ice.InitializationData)_initData.Clone(); + initData.properties = initData.properties.ice_clone_(); + + if(initData.properties.getProperty("Ice.Default.Router").Length == 0) + { + StringBuilder sb = new StringBuilder(); + sb.Append("\""); + sb.Append(Ice.Util.identityToString(_identity)); + sb.Append("\""); + sb.Append(":"); + if(_secure) + { + sb.Append("ssl -p "); + } + else + { + sb.Append("tcp -p "); + } + if(_port != 0) + { + sb.Append(_port); + } + else + { + if(_secure) + { + sb.Append(GLACIER2_SSL_PORT); + } + else + { + sb.Append(GLACIER2_TCP_PORT); + } + } + + sb.Append(" -h "); + sb.Append(_routerHost); + if(_timeout > 0) + { + sb.Append(" -t "); + sb.Append(_timeout); + } + initData.properties.setProperty("Ice.Default.Router", sb.ToString()); + } + return initData; + } + + private void + setDefaultProperties() + { + _initData.properties.setProperty("Ice.ACM.Client", "0"); + _initData.properties.setProperty("Ice.RetryIntervals", "-1"); + } + + private Callback _callback; + private string _routerHost = "127.0.0.1"; + private Ice.InitializationData _initData; + private Ice.Identity _identity = new Ice.Identity("router", "Glacier2"); + private bool _secure = true; + private int _port = 0; + private int _timeout = 10000; + private static int GLACIER2_SSL_PORT = 4064; + private static int GLACIER2_TCP_PORT = 4063; +} + +} diff --git a/cs/src/Glacier2/SessionHelper.cs b/cs/src/Glacier2/SessionHelper.cs new file mode 100644 index 00000000000..9cb8d4e3803 --- /dev/null +++ b/cs/src/Glacier2/SessionHelper.cs @@ -0,0 +1,485 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +using System; +using System.Diagnostics; +using System.Threading; +using System.Windows.Threading; + +namespace Glacier2 +{ + +/// <sumary> +/// A helper class for using Glacier2 with GUI applications. +/// </sumary> +public class SessionHelper +{ + private class SessionRefreshThread + { + private class RefreshI : Glacier2.AMI_Router_refreshSession + { + public + RefreshI(SessionHelper helper, SessionRefreshThread thread) + { + _thread = thread; + _helper = helper; + } + + public override void ice_response() + { + } + + public override void ice_exception(Ice.Exception ex) + { + _thread.done(); + _helper.destroy(); + } + + public void ice_exception(Ice.UserException ex) + { + _thread.done(); + _helper.destroy(); + } + + SessionRefreshThread _thread; + SessionHelper _helper; + } + + public SessionRefreshThread(SessionHelper session, Glacier2.RouterPrx router, int period) + { + _session = session; + _router = router; + _period = period; + _done = false; + } + + public void + run() + { + lock(this) + { + while(true) + { + _router.refreshSession_async(new RefreshI(_session, this)); + if(!_done) + { + try + { + System.Threading.Monitor.Wait(this, _period); + } + catch(ThreadInterruptedException) + { + } + } + if(_done) + { + break; + } + } + } + } + + public void + done() + { + lock(this) + { + if(!_done) + { + _done = true; + System.Threading.Monitor.Pulse(this); + } + } + } + + private SessionHelper _session; + private Glacier2.RouterPrx _router; + private int _period; + private bool _done = false; + } + + /// <sumary> + /// Creates a Glacier2 session. + /// </sumary> + /// <param name="callback">The callback for notifications about session + /// establishment.</param> + /// <param name="initData">The Ice.InitializationData for initializing + /// the communicator.</param> + public SessionHelper(SessionFactoryHelper.Callback callback, Ice.InitializationData initData) + { + _callback = callback; + _initData = initData; + } + + /// <sumary> + /// Destroys the Glacier2 session. + /// + /// Once the session has been destroyed, Callback.disconnected is + /// called on the associated callback object. + /// </sumary> + public void + destroy() + { + lock(this) + { + if(_destroy) + { + return; + } + _destroy = true; + + if(_sessionRefresh == null) + { + // In this case a connecting session is being + // destroyed. The communicator and session will be + // destroyed when the connection establishment has + // completed. + return; + } + _session = null; + + // Run the destroyInternal in a thread. This is because it + // destroyInternal makes remote invocations. + Thread t = new Thread(new ThreadStart(destroyInternal)); + t.Start(); + } + } + + /// <sumary> + /// Returns the session's communicator object. + /// </sumary> + /// <returns>The communicator.</returns> + public Ice.Communicator + communicator() + { + lock(this) + { + return _communicator; + } + } + + /// <sumary> + /// Returns the category to be used in the identities of all of + /// the client's callback objects. Clients must use this category + /// for the router to forward callback requests to the intended + /// client. + /// </sumary> + /// <returns>The category. Throws SessionNotExistException + /// No session exists</returns> + public string + categoryForClient() + { + lock(this) + { + if(_router == null) + { + throw new SessionNotExistException(); + } + + return _router.getCategoryForClient(); + } + } + + /// <sumary> + /// Adds a servant to the callback object adapter's Active Servant + /// Map with a UUID. + /// </sumary> + /// <param name="servant">The servant to add.</param> + /// <returns>The proxy for the servant. Throws SessionNotExistException + /// if no session exists.</returns> + public Ice.ObjectPrx + addWithUUID(Ice.Object servant) + { + lock(this) + { + if(_router == null) + { + throw new SessionNotExistException(); + } + + return internalObjectAdapter().add(servant, new Ice.Identity(Guid.NewGuid().ToString(), + _router.getCategoryForClient())); + } + } + + /// <sumary> + /// Returns the Glacier2 session proxy. If the session hasn't been + /// established yet, or the session has already been destroyed, + /// throws SessionNotExistException. + /// </sumary> + /// <returns>The session proxy, or throws SessionNotExistException + /// if no session exists.</returns> + public Glacier2.SessionPrx + session() + { + lock(this) + { + if(_session == null) + { + throw new SessionNotExistException(); + } + return _session; + } + } + + /// <sumary> + /// Returns true if there is an active session, otherwise returns false. + /// </sumary> + /// <returns>true if session exists or false if no session exists.</returns> + public bool + isConnected() + { + lock(this) + { + return _connected; + } + } + + /// <sumary> + /// Creates an object adapter for callback objects. + /// </sumary> + /// <return>The object adapter. throws SessionNotExistException + /// if no session exists.</return> + public Ice.ObjectAdapter + objectAdapter() + { + return internalObjectAdapter(); + } + + // Only call this method when the calling thread owns the lock + private Ice.ObjectAdapter + internalObjectAdapter() + { + lock(this) + { + if(_router == null) + { + throw new SessionNotExistException(); + } + if(_adapter == null) + { + // TODO: Depending on the resolution of + // http://bugzilla/bugzilla/show_bug.cgi?id=4264 the OA + // name could be an empty string. + _adapter = _communicator.createObjectAdapterWithRouter(Guid.NewGuid().ToString(), _router); + _adapter.activate(); + } + return _adapter; + } + } + + /// <sumary> + /// Connects to the Glacier2 router using the associated SSL credentials. + /// + /// Once the connection is established, Callback.connected} is called on + /// the callback object; upon failure, Callback.exception is called with + /// the exception. + /// </sumary> + public void + connect() + { + lock(this) + { + connectImpl(delegate(RouterPrx router) + { + return router.createSessionFromSecureConnection(); + }); + } + } + + /// <sumary> + /// Connects a Glacier2 session using user name and password credentials. + /// + /// Once the connection is established, {@link Callback#connected} is called on the callback object; + /// upon failure {@link Callback.exception} is called with the exception. + /// </sumary> + /// <param name="username">The user name.</param> + /// <param name="password">The password.</param> + public void + connect(string username, string password) + { + lock(this) + { + connectImpl(delegate(RouterPrx router) + { + return router.createSession(username, password); + }); + } + } + + private void + connected(RouterPrx router, SessionPrx session) + { + lock(this) + { + _router = router; + + if(_destroy) + { + destroyInternal(); + return; + } + + // Assign the session after _destroy is checked. + _session = session; + _connected = true; + + Debug.Assert(_sessionRefresh == null); + _sessionRefresh = new SessionRefreshThread(this, _router, (int)(_router.getSessionTimeout() * 1000)/2); + _refreshThread = new Thread(new ThreadStart(_sessionRefresh.run)); + _refreshThread.Start(); + + + _callback.getDispatcher().Invoke(DispatcherPriority.Normal, + (Action)delegate() + { + try + { + _callback.connected(this); + } + catch(Glacier2.SessionNotExistException) + { + destroy(); + } + }); + } + } + + private void + destroyInternal() + { + lock(this) + { + Debug.Assert(_destroy); + + try + { + _router.destroySession(); + } + catch(Ice.ConnectionLostException) + { + // Expected + } + catch(SessionNotExistException) + { + // This can also occur. + } + catch(Exception e) + { + // Not expected. + _communicator.getLogger().warning("SessionHelper: unexpected exception when destroying the session:\n" + + e); + } + _router = null; + _connected = false; + if(_sessionRefresh != null) + { + _sessionRefresh.done(); + while(true) + { + try + { + _refreshThread.Join(); + break; + } + catch(ThreadInterruptedException) + { + } + } + _sessionRefresh = null; + _refreshThread = null; + } + + try + { + _communicator.destroy(); + } + catch(Exception) + { + } + _communicator = null; + + // Notify the callback that the session is gone. + _callback.getDispatcher().BeginInvoke(DispatcherPriority.Normal, + (Action)delegate() + { + _callback.disconnected(this); + }); + } + } + + delegate Glacier2.SessionPrx + ConnectStrategy(Glacier2.RouterPrx router); + + private void + connectImpl(ConnectStrategy factory) + { + Debug.Assert(!_destroy); + + try + { + _communicator = Ice.Util.initialize(_initData); + } + catch(Ice.LocalException ex) + { + _destroy = true; + _callback.getDispatcher().BeginInvoke(DispatcherPriority.Normal, (Action)delegate() + { + _callback.connectFailed(this, ex); + }); + return; + } + + new Thread(new ThreadStart(delegate() + { + try + { + _callback.getDispatcher().BeginInvoke(DispatcherPriority.Normal, + (Action)delegate() + { + _callback.createdCommunicator(this); + }); + + Glacier2.RouterPrx routerPrx = Glacier2.RouterPrxHelper.uncheckedCast( + _communicator.getDefaultRouter()); + Glacier2.SessionPrx session = factory(routerPrx); + connected(routerPrx, session); + } + catch (Exception ex) + { + try + { + _communicator.destroy(); + } + catch(Exception) + { + } + + _callback.getDispatcher().BeginInvoke(DispatcherPriority.Normal, (Action)delegate() + { + _callback.connectFailed(this, ex); + }); + } + })).Start(); + } + + private Ice.InitializationData _initData; + private Ice.Communicator _communicator; + private Ice.ObjectAdapter _adapter; + private Glacier2.RouterPrx _router; + private Glacier2.SessionPrx _session; + private bool _connected = false; + + private SessionRefreshThread _sessionRefresh; + private Thread _refreshThread; + private SessionFactoryHelper.Callback _callback; + private bool _destroy = false; +} + +} diff --git a/cs/src/Ice/Application.cs b/cs/src/Ice/Application.cs index 9aacbf0888b..5192916adca 100644 --- a/cs/src/Ice/Application.cs +++ b/cs/src/Ice/Application.cs @@ -82,7 +82,7 @@ namespace Ice /// <param name="signalPolicy">Determines how to respond to signals.</param> public Application(SignalPolicy signalPolicy) { - _signalPolicy = signalPolicy; + signalPolicy__ = signalPolicy; } /// <summary> @@ -122,7 +122,7 @@ namespace Ice { if(Util.getProcessLogger() is ConsoleLoggerI) { - Util.setProcessLogger(new ConsoleLoggerI(_appName)); + Util.setProcessLogger(new ConsoleLoggerI(appName__)); } InitializationData initData = new InitializationData(); @@ -165,10 +165,10 @@ namespace Ice { if(Util.getProcessLogger() is ConsoleLoggerI) { - Util.setProcessLogger(new ConsoleLoggerI(_appName)); + Util.setProcessLogger(new ConsoleLoggerI(appName__)); } - if(_communicator != null) + if(communicator__ != null) { Util.getProcessLogger().error("only one instance of the Application class can be used"); return 1; @@ -176,7 +176,7 @@ namespace Ice int status; - if(_signalPolicy == SignalPolicy.HandleSignals) + if(signalPolicy__ == SignalPolicy.HandleSignals) { if(IceInternal.AssemblyUtil.platform_ == IceInternal.AssemblyUtil.Platform.Windows) { @@ -188,13 +188,13 @@ namespace Ice } _signals.register(_handler); - status = mainInternal(args, initData); + status = doMain(args, initData); _signals = null; } else { - status = mainInternal(args, initData); + status = doMain(args, initData); } return status; @@ -209,7 +209,7 @@ namespace Ice /// <returns>The name of the application.</returns> public static string appName() { - return _appName; + return appName__; } /// <summary> @@ -220,7 +220,7 @@ namespace Ice /// <returns>The communicator for the application.</returns> public static Communicator communicator() { - return _communicator; + return communicator__; } /// <summary> @@ -229,14 +229,14 @@ namespace Ice /// </summary> public static void destroyOnInterrupt() { - if(_signalPolicy == SignalPolicy.HandleSignals) + if(signalPolicy__ == SignalPolicy.HandleSignals) { - lock(_mutex) + lock(mutex__) { if(_callback == _holdCallback) { - _released = true; - Monitor.Pulse(_mutex); + released__ = true; + Monitor.Pulse(mutex__); } _callback = _destroyCallback; } @@ -253,14 +253,14 @@ namespace Ice /// </summary> public static void shutdownOnInterrupt() { - if(_signalPolicy == SignalPolicy.HandleSignals) + if(signalPolicy__ == SignalPolicy.HandleSignals) { - lock(_mutex) + lock(mutex__) { if(_callback == _holdCallback) { - _released = true; - Monitor.Pulse(_mutex); + released__ = true; + Monitor.Pulse(mutex__); } _callback = _shutdownCallback; } @@ -277,14 +277,14 @@ namespace Ice /// </summary> public static void ignoreInterrupt() { - if(_signalPolicy == SignalPolicy.HandleSignals) + if(signalPolicy__ == SignalPolicy.HandleSignals) { - lock(_mutex) + lock(mutex__) { if(_callback == _holdCallback) { - _released = true; - Monitor.Pulse(_mutex); + released__ = true; + Monitor.Pulse(mutex__); } _callback = null; } @@ -302,14 +302,14 @@ namespace Ice /// </summary> public static void callbackOnInterrupt() { - if(_signalPolicy == SignalPolicy.HandleSignals) + if(signalPolicy__ == SignalPolicy.HandleSignals) { - lock(_mutex) + lock(mutex__) { if(_callback == _holdCallback) { - _released = true; - Monitor.Pulse(_mutex); + released__ = true; + Monitor.Pulse(mutex__); } _callback = _userCallback; } @@ -326,14 +326,14 @@ namespace Ice /// </summary> public static void holdInterrupt() { - if(_signalPolicy == SignalPolicy.HandleSignals) + if(signalPolicy__ == SignalPolicy.HandleSignals) { - lock(_mutex) + lock(mutex__) { if(_callback != _holdCallback) { _previousCallback = _callback; - _released = false; + released__ = false; _callback = _holdCallback; } // else, we were already holding signals @@ -352,22 +352,22 @@ namespace Ice /// </summary> public static void releaseInterrupt() { - if(_signalPolicy == SignalPolicy.HandleSignals) + if(signalPolicy__ == SignalPolicy.HandleSignals) { - lock(_mutex) + lock(mutex__) { if(_callback == _holdCallback) { // // Note that it's very possible no signal is held; // in this case the callback is just replaced and - // setting _released to true and signalling _mutex + // setting released__ to true and signalling mutex__ // do no harm. // - _released = true; + released__ = true; _callback = _previousCallback; - Monitor.Pulse(_mutex); + Monitor.Pulse(mutex__); } // Else nothing to release. } @@ -386,13 +386,13 @@ namespace Ice /// <returns>True if a signal caused the communicator to shut down; false otherwise.</returns> public static bool interrupted() { - lock(_mutex) + lock(mutex__) { - return _interrupted; + return interrupted__; } } - private int mainInternal(string[] args, InitializationData initializationData) + protected virtual int doMain(string[] args, InitializationData initializationData) { int status = 0; @@ -423,17 +423,17 @@ namespace Ice } _application = this; - _communicator = Util.initialize(ref args, initData); - _destroyed = false; + communicator__ = Util.initialize(ref args, initData); + destroyed__ = false; - Properties props = _communicator.getProperties(); - _nohup = props.getPropertyAsInt("Ice.Nohup") > 0; - _appName = props.getPropertyWithDefault("Ice.ProgramName", _appName); + Properties props = communicator__.getProperties(); + nohup__ = props.getPropertyAsInt("Ice.Nohup") > 0; + appName__ = props.getPropertyWithDefault("Ice.ProgramName", appName__); // // The default is to destroy when a signal is received. // - if(_signalPolicy == SignalPolicy.HandleSignals) + if(signalPolicy__ == SignalPolicy.HandleSignals) { destroyOnInterrupt(); } @@ -456,38 +456,38 @@ namespace Ice // (post-run), it would not make sense to release a held // signal to run shutdown or destroy. // - if(_signalPolicy == SignalPolicy.HandleSignals) + if(signalPolicy__ == SignalPolicy.HandleSignals) { ignoreInterrupt(); } - lock(_mutex) + lock(mutex__) { - while(_callbackInProgress) + while(callbackInProgress__) { - Monitor.Wait(_mutex); + Monitor.Wait(mutex__); } - if(_destroyed) + if(destroyed__) { - _communicator = null; + communicator__ = null; } else { - _destroyed = true; + destroyed__ = true; // - // _communicator != null means that it will be destroyed - // next; _destroyed == true ensures that any + // communicator__ != null means that it will be destroyed + // next; destroyed__ == true ensures that any // remaining callback won't do anything // } _application = null; } - if(_communicator != null) + if(communicator__ != null) { try { - _communicator.destroy(); + communicator__.destroy(); } catch(Ice.Exception ex) { @@ -499,7 +499,7 @@ namespace Ice Util.getProcessLogger().error("unknown exception:\n" + ex); status = 1; } - _communicator = null; + communicator__ = null; } return status; @@ -511,7 +511,7 @@ namespace Ice private static void signalHandler(int sig) { Callback callback; - lock(_mutex) + lock(mutex__) { callback = _callback; } @@ -534,14 +534,14 @@ namespace Ice private static void holdInterruptCallback(int sig) { Callback callback = null; - lock(_mutex) + lock(mutex__) { - while(!_released) + while(!released__) { - Monitor.Wait(_mutex); + Monitor.Wait(mutex__); } - if(_destroyed) + if(destroyed__) { // // Being destroyed by main thread @@ -563,86 +563,86 @@ namespace Ice // private static void destroyOnInterruptCallback(int sig) { - lock(_mutex) + lock(mutex__) { - if(_destroyed) + if(destroyed__) { // // Being destroyed by main thread // return; } - if(_nohup && sig == SIGHUP) + if(nohup__ && sig == SIGHUP) { return; } - Debug.Assert(!_callbackInProgress); - _callbackInProgress = true; - _interrupted = true; - _destroyed = true; + Debug.Assert(!callbackInProgress__); + callbackInProgress__ = true; + interrupted__ = true; + destroyed__ = true; } try { - Debug.Assert(_communicator != null); - _communicator.destroy(); + Debug.Assert(communicator__ != null); + communicator__.destroy(); } catch(System.Exception ex) { Util.getProcessLogger().error("(while destroying in response to signal " + sig + "):\n" + ex); } - lock(_mutex) + lock(mutex__) { - _callbackInProgress = false; - Monitor.Pulse(_mutex); + callbackInProgress__ = false; + Monitor.Pulse(mutex__); } } private static void shutdownOnInterruptCallback(int sig) { - lock(_mutex) + lock(mutex__) { - if(_destroyed) + if(destroyed__) { // // Being destroyed by main thread // return; } - if(_nohup && sig == SIGHUP) + if(nohup__ && sig == SIGHUP) { return; } - Debug.Assert(!_callbackInProgress); - _callbackInProgress = true; - _interrupted = true; + Debug.Assert(!callbackInProgress__); + callbackInProgress__ = true; + interrupted__ = true; } try { - Debug.Assert(_communicator != null); - _communicator.shutdown(); + Debug.Assert(communicator__ != null); + communicator__.shutdown(); } catch(System.Exception ex) { Util.getProcessLogger().error("(while shutting down in response to signal " + sig + "):\n" + ex); } - lock(_mutex) + lock(mutex__) { - _callbackInProgress = false; - Monitor.Pulse(_mutex); + callbackInProgress__ = false; + Monitor.Pulse(mutex__); } } private static void userCallbackOnInterruptCallback(int sig) { - lock(_mutex) + lock(mutex__) { - if(_destroyed) + if(destroyed__) { // // Being destroyed by main thread @@ -651,9 +651,9 @@ namespace Ice } // For SIGHUP the user callback is always called. It can // decide what to do. - Debug.Assert(!_callbackInProgress); - _callbackInProgress = true; - _interrupted = true; + Debug.Assert(!callbackInProgress__); + callbackInProgress__ = true; + interrupted__ = true; } try @@ -666,21 +666,21 @@ namespace Ice Util.getProcessLogger().error("(while interrupting in response to signal " + sig + "):\n" + ex); } - lock(_mutex) + lock(mutex__) { - _callbackInProgress = false; - Monitor.Pulse(_mutex); + callbackInProgress__ = false; + Monitor.Pulse(mutex__); } } - private static readonly object _mutex = new object(); + protected static readonly object mutex__ = new object(); - private static bool _callbackInProgress = false; - private static bool _destroyed = false; - private static bool _interrupted = false; - private static bool _released = false; - private static bool _nohup = false; - private static SignalPolicy _signalPolicy = SignalPolicy.HandleSignals; + protected static bool callbackInProgress__ = false; + protected static bool destroyed__ = false; + protected static bool interrupted__ = false; + protected static bool released__ = false; + protected static bool nohup__ = false; + protected static SignalPolicy signalPolicy__ = SignalPolicy.HandleSignals; private delegate void Callback(int sig); private static readonly Callback _destroyCallback = new Callback(destroyOnInterruptCallback); @@ -695,8 +695,8 @@ namespace Ice // We use FriendlyName instead of Process.GetCurrentProcess().ProcessName because the latter // is terribly slow. (It takes around 1 second!) // - private static string _appName = AppDomain.CurrentDomain.FriendlyName; - private static Communicator _communicator; + protected static string appName__ = AppDomain.CurrentDomain.FriendlyName; + protected static Communicator communicator__; private static Application _application; private static int SIGHUP; diff --git a/demoscript/Glacier2/callback.py b/demoscript/Glacier2/callback.py index f0058a813ba..7ef1b36a2f5 100755 --- a/demoscript/Glacier2/callback.py +++ b/demoscript/Glacier2/callback.py @@ -11,7 +11,7 @@ import sys, time, signal from scripts import Expect -def run(client, server, sessionserver, glacier2): +def run(client, server, glacier2): print "testing ", sys.stdout.flush() client.expect('user id:') @@ -19,9 +19,6 @@ def run(client, server, sessionserver, glacier2): client.expect('password:') client.sendline("foo") - sessionserver.expect('verified user') - sessionserver.expect('creating session') - client.expect("==>") print "twoway", @@ -29,14 +26,14 @@ def run(client, server, sessionserver, glacier2): client.sendline('t') server.expect('initiating callback to') client.expect('received callback') - glacier2.expect('_fwd/t \\]') + #glacier2.expect('_fwd/t \\]') print "oneway", sys.stdout.flush() client.sendline('o') server.expect('initiating callback to') client.expect('received callback') - glacier2.expect('_fwd/o \\]') + #glacier2.expect('_fwd/o \\]') print "batch", sys.stdout.flush() @@ -47,14 +44,14 @@ def run(client, server, sessionserver, glacier2): pass client.sendline('O') client.sendline('f') - glacier2.expect('_fwd/O \\]') + #glacier2.expect('_fwd/O \\]') print "ok" print "testing override context field...", sys.stdout.flush() client.sendline('v') client.sendline('t') - glacier2.expect('_fwd/t, _ovrd/some_value') + #glacier2.expect('_fwd/t, _ovrd/some_value') server.expect('initiating callback to') client.expect('received callback') print "ok" @@ -71,21 +68,11 @@ def run(client, server, sessionserver, glacier2): pass print "ok" - print "testing session timeout...", - sys.stdout.flush() - time.sleep(6) - glacier2.expect('expiring session') - sessionserver.expect('destroying session for user') - print "ok" # SessionNotExist client.sendline('x') - client.expect('SessionNotExistException') client.waitTestSuccess() - sessionserver.kill(signal.SIGINT) - sessionserver.waitTestSuccess() - server.kill(signal.SIGINT) server.waitTestSuccess() diff --git a/java/config/common.xml b/java/config/common.xml index 88776ad1cb6..b3f8c1b4434 100644 --- a/java/config/common.xml +++ b/java/config/common.xml @@ -84,7 +84,7 @@ </condition> <condition property="ice.dir" value="${ice.top.dir}/ice"> <and> - <!-- Don't just look for ${ice.top.dir}/../java - we want to make sure we are really + <!-- Don't just look for ${ice.top.dir}/ice/java - we want to make sure we are really in a source distribution. --> <not><isset property="ice.dir"/></not> <available file="${ice.top.dir}/ice/java/src/Ice/Util.java"/> diff --git a/java/demo/Glacier2/build.xml b/java/demo/Glacier2/build.xml index cfb2c825c15..1081e09a996 100644 --- a/java/demo/Glacier2/build.xml +++ b/java/demo/Glacier2/build.xml @@ -13,10 +13,12 @@ <target name="all"> <ant dir="callback"/> + <ant dir="chat"/> </target> <target name="clean"> <ant dir="callback" target="clean"/> + <ant dir="chat" target="clean"/> </target> </project> diff --git a/java/demo/Glacier2/callback/Client.java b/java/demo/Glacier2/callback/Client.java index 399d6eab481..9dcf50085be 100644 --- a/java/demo/Glacier2/callback/Client.java +++ b/java/demo/Glacier2/callback/Client.java @@ -9,57 +9,8 @@ import Demo.*; -public class Client extends Ice.Application +public class Client extends Glacier2.Application { - - static private class SessionRefreshThread extends Thread - { - SessionRefreshThread(Glacier2.RouterPrx router, long timeout) - { - _router = router; - _timeout = timeout; - } - - synchronized public void - run() - { - while(!_terminated) - { - try - { - wait(_timeout); - } - catch(InterruptedException e) - { - } - if(!_terminated) - { - try - { - _router.refreshSession(); - } - catch(Glacier2.SessionNotExistException ex) - { - } - catch(Ice.LocalException ex) - { - } - } - } - } - - synchronized private void - terminate() - { - _terminated = true; - notify(); - } - - final private Glacier2.RouterPrx _router; - final private long _timeout; - private boolean _terminated = false; - } - class ShutdownHook extends Thread { public void @@ -88,118 +39,118 @@ public class Client extends Ice.Application "v: set/reset override context field\n" + "F: set/reset fake category\n" + "s: shutdown server\n" + + "r: restart the session\n" + "x: exit\n" + "?: help\n"); } - public int - run(String[] args) + public void sessionDestroyed() { - if(args.length > 0) - { - System.err.println(appName() + ": too many arguments"); - return 1; - } - - // - // Since this is an interactive demo we want to clear the - // Application installed interrupt callback and install our - // own shutdown hook. - // - setInterruptHook(new ShutdownHook()); - - Ice.RouterPrx defaultRouter = communicator().getDefaultRouter(); - if(defaultRouter == null) - { - System.err.println("no default router set"); - return 1; - } - - Glacier2.RouterPrx router = Glacier2.RouterPrxHelper.checkedCast(defaultRouter); - if(router == null) - { - System.err.println("configured router is not a Glacier2 router"); - return 1; - } + System.out.println("The Glacier2 session has been destroyed."); + } - java.io.BufferedReader in = new java.io.BufferedReader(new java.io.InputStreamReader(System.in)); + public Glacier2.SessionPrx createSession() + { + Glacier2.SessionPrx session; while(true) { + java.io.BufferedReader in = new java.io.BufferedReader(new java.io.InputStreamReader(System.in)); System.out.println("This demo accepts any user-id / password combination."); + String id; + String pw; try { - String id; System.out.print("user id: "); System.out.flush(); id = in.readLine(); - - String pw; + System.out.print("password: "); System.out.flush(); pw = in.readLine(); - - try - { - router.createSession(id, pw); - break; - } - catch(Glacier2.PermissionDeniedException ex) - { - System.out.println("permission denied:\n" + ex.reason); - } - catch(Glacier2.CannotCreateSessionException ex) - { - System.out.println("cannot create session:\n" + ex.reason); - } } catch(java.io.IOException ex) { ex.printStackTrace(); + continue; + } + + try + { + session = router().createSession(id, pw); + break; + } + catch(Glacier2.PermissionDeniedException ex) + { + System.out.println("permission denied:\n" + ex.reason); + } + catch(Glacier2.CannotCreateSessionException ex) + { + System.out.println("cannot create session:\n" + ex.reason); } } + return session; + } - SessionRefreshThread refresh = new SessionRefreshThread(router, router.getSessionTimeout() * 500); - refresh.start(); + public int + runWithSession(String[] args) + throws RestartSessionException + { + if(args.length > 0) + { + System.err.println(appName() + ": too many arguments"); + return 1; + } - String category = router.getCategoryForClient(); - Ice.Identity callbackReceiverIdent = new Ice.Identity(); - callbackReceiverIdent.name = "callbackReceiver"; - callbackReceiverIdent.category = category; - Ice.Identity callbackReceiverFakeIdent = new Ice.Identity(); - callbackReceiverFakeIdent.name = "callbackReceiver"; - callbackReceiverFakeIdent.category = "fake"; + // + // Since this is an interactive demo we want to clear the + // Application installed interrupt callback and install our + // own shutdown hook. + // + setInterruptHook(new ShutdownHook()); - Ice.ObjectPrx base = communicator().propertyToProxy("Callback.Proxy"); - CallbackPrx twoway = CallbackPrxHelper.checkedCast(base); - CallbackPrx oneway = CallbackPrxHelper.uncheckedCast(twoway.ice_oneway()); - CallbackPrx batchOneway = CallbackPrxHelper.uncheckedCast(twoway.ice_batchOneway()); + try + { + Ice.Identity callbackReceiverIdent = createCallbackIdentity("callbackReceiver"); + Ice.Identity callbackReceiverFakeIdent = new Ice.Identity("fake", "callbackReceiver"); - Ice.ObjectAdapter adapter = communicator().createObjectAdapterWithRouter("Callback.Client", defaultRouter); - adapter.add(new CallbackReceiverI(), callbackReceiverIdent); - adapter.add(new CallbackReceiverI(), callbackReceiverFakeIdent); - adapter.activate(); + Ice.ObjectPrx base = communicator().propertyToProxy("Callback.Proxy"); + CallbackPrx twoway = CallbackPrxHelper.checkedCast(base); + CallbackPrx oneway = CallbackPrxHelper.uncheckedCast(twoway.ice_oneway()); + CallbackPrx batchOneway = CallbackPrxHelper.uncheckedCast(twoway.ice_batchOneway()); - CallbackReceiverPrx twowayR = CallbackReceiverPrxHelper.uncheckedCast( - adapter.createProxy(callbackReceiverIdent)); - CallbackReceiverPrx onewayR = CallbackReceiverPrxHelper.uncheckedCast(twowayR.ice_oneway()); + objectAdapter().add(new CallbackReceiverI(), callbackReceiverFakeIdent); - menu(); + CallbackReceiverPrx twowayR = CallbackReceiverPrxHelper.uncheckedCast( + objectAdapter().add(new CallbackReceiverI(), callbackReceiverIdent)); + CallbackReceiverPrx onewayR = CallbackReceiverPrxHelper.uncheckedCast(twowayR.ice_oneway()); - String line = null; - String override = null; - boolean fake = false; - do - { - try + + menu(); + + String line = null; + String override = null; + boolean fake = false; + java.io.BufferedReader in = new java.io.BufferedReader(new java.io.InputStreamReader(System.in)); + do { System.out.print("==> "); System.out.flush(); - line = in.readLine(); + try + { + line = in.readLine(); + } + catch(java.io.IOException ex) + { + ex.printStackTrace(); + line = null; + } + if(line == null) { break; } + if(line.equals("t")) { java.util.Map<String, String> context = new java.util.HashMap<String, String>(); @@ -250,7 +201,7 @@ public class Client extends Ice.Application else if(line.equals("F")) { fake = !fake; - + if(fake) { twowayR = CallbackReceiverPrxHelper.uncheckedCast( @@ -265,14 +216,18 @@ public class Client extends Ice.Application onewayR = CallbackReceiverPrxHelper.uncheckedCast( onewayR.ice_identity(callbackReceiverIdent)); } - + System.out.println("callback receiver identity: " + - communicator().identityToString(twowayR.ice_getIdentity())); + communicator().identityToString(twowayR.ice_getIdentity())); } else if(line.equals("s")) { twoway.shutdown(); } + else if(line.equals("r")) + { + restart(); + } else if(line.equals("x")) { // Nothing to do @@ -287,45 +242,12 @@ public class Client extends Ice.Application menu(); } } - catch(java.io.IOException ex) - { - ex.printStackTrace(); - } - catch(Ice.LocalException ex) - { - ex.printStackTrace(); - } - } - while(!line.equals("x")); - - // - // The refresher thread must be terminated before the session - // is destroyed, otherwise it might get - // ObjectNotExistException. - // - refresh.terminate(); - try - { - refresh.join(); - } - catch(InterruptedException e) - { - } - refresh = null; - - try - { - router.destroySession(); + while(!line.equals("x")); } catch(Glacier2.SessionNotExistException ex) { - ex.printStackTrace(); - } - catch(Ice.ConnectionLostException ex) - { - // - // Expected: the router closed the connection. - // + System.err.println(appName() + ": " + ex.toString()); + return 1; } return 0; diff --git a/java/demo/Glacier2/callback/README b/java/demo/Glacier2/callback/README index c6caff987c1..954ca715d52 100644 --- a/java/demo/Glacier2/callback/README +++ b/java/demo/Glacier2/callback/README @@ -16,10 +16,9 @@ In a separate window, start the client: $ java Client -If you plan to run this demo using clients on different hosts than -the router, you must first modify the configuration. You need to -change the Glacier2.Client.Endpoints property in config.glacier2 and -the Ice.Default.Router and Callback.Client.Router properties in -config.client. In all cases you must replace the "-h 127.0.0.1" -parameter with the actual external address of the machine on which -glacier2router is running. +If you plan to run this demo using clients on different hosts than the +router, you must first modify the configuration. You need to change +the Glacier2.Client.Endpoints property in config.glacier2 and the +Ice.Default.Router properties in config.client. In all cases you must +replace the "-h 127.0.0.1" parameter with the actual external address +of the machine on which glacier2router is running. diff --git a/java/demo/Glacier2/callback/config.client b/java/demo/Glacier2/callback/config.client index 174bc7f23e7..bbfb87538b3 100644 --- a/java/demo/Glacier2/callback/config.client +++ b/java/demo/Glacier2/callback/config.client @@ -5,31 +5,12 @@ Ice.Default.Router=DemoGlacier2/router:ssl -p 4064 -h 127.0.0.1 # -# We don't need any endpoints for the client if we use a -# router. Incoming requests are received through connections -# established from the client to the router. -# -Callback.Client.Endpoints= - -# # This must match the value of Callback.Server.Endpoints in # config.server. # Callback.Proxy=callback:tcp -h 127.0.0.1 -p 10000 # -# No active connection management is permitted with Glacier2. -# Connections must remain established. -# -Ice.ACM.Client=0 - -# -# Connection retry is not possible with Glacier2. Connections must -# remain established. -# -Ice.RetryIntervals=-1 - -# # Warn about connection exceptions # #Ice.Warn.Connections=1 diff --git a/java/demo/Glacier2/callback/expect.py b/java/demo/Glacier2/callback/expect.py index 224a9a8e193..adcd6cc7866 100755 --- a/java/demo/Glacier2/callback/expect.py +++ b/java/demo/Glacier2/callback/expect.py @@ -24,8 +24,6 @@ from demoscript.Glacier2 import callback server = Util.spawn('java Server --Ice.PrintAdapterReady') server.expect('.* ready') -sessionserver = Util.spawn('java SessionServer --Ice.PrintAdapterReady') -sessionserver.expect('.* ready') glacier2 = Util.spawn('glacier2router --Ice.Config=config.glacier2 --Ice.PrintAdapterReady --Glacier2.SessionTimeout=5') glacier2.expect('Glacier2.Client ready') @@ -33,4 +31,4 @@ glacier2.expect('Glacier2.Server ready') client = Util.spawn('java Client') -callback.run(client, server, sessionserver, glacier2) +callback.run(client, server, glacier2) diff --git a/java/demo/Glacier2/chat/Chat.ice b/java/demo/Glacier2/chat/Chat.ice new file mode 100644 index 00000000000..d55ec11be98 --- /dev/null +++ b/java/demo/Glacier2/chat/Chat.ice @@ -0,0 +1,31 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef CHAT_ICE +#define CHAT_ICE + +#include <Glacier2/Session.ice> + +module Demo +{ + +interface ChatCallback +{ + void message(string data); +}; + +interface ChatSession extends Glacier2::Session +{ + ["ami"] void setCallback(ChatCallback* callback); + ["ami"] void say(string data); +}; + +}; + +#endif diff --git a/java/demo/Glacier2/chat/Client.java b/java/demo/Glacier2/chat/Client.java new file mode 100644 index 00000000000..f0ab1aa53cf --- /dev/null +++ b/java/demo/Glacier2/chat/Client.java @@ -0,0 +1,544 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.BoxLayout; +import javax.swing.JDialog; +import javax.swing.AbstractAction; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JPopupMenu; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JSeparator; +import javax.swing.JSplitPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultEditorKit; +import javax.swing.text.Document; +import javax.swing.text.Element; + +import Glacier2.SessionFactoryHelper; +import Glacier2.SessionHelper; +import Glacier2.SessionNotExistException; +import Ice.Current; +import Ice.LocalException; +import Ice.StringSeqHolder; +import Ice.Util; + +// TODO: Simplify the callbacks when http://bugzilla/bugzilla/show_bug.cgi?id=4193 is fixed. + +@SuppressWarnings("serial") +public class Client extends JFrame +{ + public static void + main(final String[] args) + { + SwingUtilities.invokeLater(new Runnable() + { + public void + run() + { + try + { + // + // Create and set up the window. + // + new Client(args); + } + catch(Ice.LocalException e) + { + JOptionPane.showMessageDialog(null, + e.toString(), + "Initialization failed", + JOptionPane.ERROR_MESSAGE); + } + } + }); + } + + + Client(String[] args) + { + // Build the JTextArea that shows the chat conversation. + _output = new JTextArea(""); + _output.setLineWrap(true); + _output.setEditable(false); + + final JPopupMenu textMenu = new JPopupMenu(); + textMenu.add(new DefaultEditorKit.CopyAction()); + textMenu.pack(); + + _output.addMouseListener(new MouseAdapter() + { + public void + mousePressed(MouseEvent e) + { + if(e.isPopupTrigger()) + { + textMenu.show(_output, e.getX(), e.getY()); + } + } + }); + + // Build the JTextArea where the user writes input messages. + _input = new JTextArea(""); + _input.setLineWrap(true); + _input.setEditable(true); + _input.addKeyListener( new KeyListener() + { + public void + keyTyped(KeyEvent e) + { + if(e.getKeyChar() == KeyEvent.VK_ENTER) + { + Document doc = _input.getDocument(); + try + { + String msg = doc.getText(0, doc.getLength()).trim(); + if(msg.length() > 0) + { + _chat.say_async(new Demo.AMI_ChatSession_say() + { + @Override + public void + ice_exception(final LocalException ex) + { + SwingUtilities.invokeLater(new Runnable() { + + public void + run() + { + appendMessage("<system-message> - " + ex); + } + }); + } + + @Override + public void + ice_response() + { + } + }, msg); + } + } + catch(BadLocationException e1) + { + } + + _input.setText(""); + } + } + + public void + keyPressed(KeyEvent e) + { + } + + public void + keyReleased(KeyEvent e) + { + } + }); + + _outputScroll = new JScrollPane(_output); + _outputScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + _outputScroll.setBorder(null); + + _outputScroll.setMinimumSize(new Dimension(100, 100)); + _outputScroll.setPreferredSize(new Dimension(100, 100)); + + JSplitPane verticalSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + verticalSplit.setTopComponent(_outputScroll); + + JScrollPane conversationInputScroll = new JScrollPane(_input); + conversationInputScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + conversationInputScroll.setBorder(null); + + conversationInputScroll.setMinimumSize(new Dimension(100, 100)); + conversationInputScroll.setPreferredSize(new Dimension(100, 100)); + verticalSplit.setBottomComponent(conversationInputScroll); + + verticalSplit.setResizeWeight(0.9); + + _output.addComponentListener(new ComponentListener() + { + public void + componentResized(ComponentEvent e) + { + JScrollBar vertivalScrollbar = _outputScroll.getVerticalScrollBar(); + vertivalScrollbar.setValue(vertivalScrollbar.getMaximum()); + } + public void + componentHidden(ComponentEvent e) + { + } + + public void + componentMoved(ComponentEvent e) + { + } + + public void + componentShown(ComponentEvent e) + { + } + }); + + add(verticalSplit, BorderLayout.CENTER); + + JPanel statusPanel = new JPanel(); + JSeparator statusPanelSeparator = new JSeparator(); + _status = new JLabel(); + _status.setText("Disconnected"); + + statusPanel.add(statusPanelSeparator, BorderLayout.NORTH); + statusPanel.add(_status, BorderLayout.SOUTH); + + add(statusPanel, BorderLayout.SOUTH); + + JMenuBar menuBar = new JMenuBar(); + JMenu connectMenu = new JMenu("Connect"); + + _login = new AbstractAction("Login") + { + public void + actionPerformed(ActionEvent e) + { + login(); + } + }; + + _logout = new AbstractAction("Logout") + { + public void + actionPerformed(ActionEvent e) + { + setEnabled(false); + _status.setText("Disconnecting"); + + destroySession(); + _chat = null; + } + }; + _logout.setEnabled(false); + + _exit = new AbstractAction("Exit") + { + public void + actionPerformed(ActionEvent e) + { + exit(); + } + }; + + connectMenu.add(_login); + connectMenu.add(_logout); + if(!System.getProperty("os.name").startsWith("Mac OS")) + { + connectMenu.add(_exit); + } + + menuBar.add(connectMenu); + + setJMenuBar(menuBar); + + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + + addWindowListener(new WindowAdapter() + { + public void + windowClosing(WindowEvent e) + { + exit(); + } + }); + + pack(); + setSize(640, 480); + locateOnScreen(this); + setVisible(true); + + // Create the labels and text fields. + JLabel hostLabel = new JLabel("Host: ", JLabel.RIGHT); + _hostField = new JTextField("", 12); + _hostField.setText("127.0.0.1"); + JLabel userNameLabel = new JLabel("Username: ", JLabel.RIGHT); + _userNameField = new JTextField("", 12); + _userNameField.setText("test"); + JLabel passwordLabel = new JLabel("Password: ", JLabel.RIGHT); + _passwordField = new JPasswordField("", 12); + _connectionPanel = new JPanel(false); + _connectionPanel.setLayout(new BoxLayout(_connectionPanel, BoxLayout.X_AXIS)); + + JPanel labelPanel = new JPanel(false); + labelPanel.setLayout(new GridLayout(0, 1)); + labelPanel.add(hostLabel); + labelPanel.add(userNameLabel); + labelPanel.add(passwordLabel); + JPanel fieldPanel = new JPanel(false); + fieldPanel.setLayout(new GridLayout(0, 1)); + fieldPanel.add(_hostField); + fieldPanel.add(_userNameField); + fieldPanel.add(_passwordField); + _connectionPanel.add(labelPanel); + _connectionPanel.add(fieldPanel); + + _input.setEnabled(false); + Ice.Properties properties = Ice.Util.createProperties(); + properties.load("config.client"); + StringSeqHolder argHolder = new StringSeqHolder(args); + properties = Util.createProperties(argHolder, properties); + _factory = new SessionFactoryHelper(properties, new SessionFactoryHelper.Callback() + { + // The session helper callbacks are all called from the + // GUI thread. + public void + connected(SessionHelper session) + throws SessionNotExistException + { + // If the session has been reassigned avoid the + // spurious callback. + if(session != _session) + { + return; + } + + // The chat callback servant. We use an anonymous + // inner class since the implementation is very + // simple. + Demo._ChatCallbackDisp servant = new Demo._ChatCallbackDisp() + { + public void + message(final String data, Current current) + { + SwingUtilities.invokeLater(new Runnable() + { + public void + run() + { + appendMessage(data); + } + }); + } + }; + Demo.ChatCallbackPrx callback = Demo.ChatCallbackPrxHelper.uncheckedCast( + _session.addWithUUID(servant)); + + _chat = Demo.ChatSessionPrxHelper.uncheckedCast(_session.session()); + _chat.setCallback_async(new Demo.AMI_ChatSession_setCallback() + { + @Override + public void + ice_exception(LocalException ex) + { + SwingUtilities.invokeLater(new Runnable() + { + + public void + run() + { + destroySession(); + } + }); + } + + @Override + public void + ice_response() + { + SwingUtilities.invokeLater(new Runnable() + { + public void + run() + { + assert _loginDialog != null; + _loginDialog.dispose(); + + _login.setEnabled(false); + _logout.setEnabled(true); + + _input.setEnabled(true); + + _status.setText("Connected with " + _hostField.getText()); + } + }); + } + + }, callback); + } + + public void + disconnected(SessionHelper session) + { + // If the session has been reassigned avoid the + // spurious callback. + if(session != _session) + { + return; + } + + if(_loginDialog != null) + { + _loginDialog.dispose(); + } + + _session = null; + _chat = null; + + _login.setEnabled(true); + _logout.setEnabled(false); + + _input.setEnabled(false); + + _status.setText("Disconnected"); + } + + public void + connectFailed(SessionHelper session, Throwable ex) + { + // If the session has been reassigned avoid the + // spurious callback. + if(session != _session) + { + return; + } + + if(_loginDialog != null) + { + _loginDialog.dispose(); + } + _status.setText(ex.getClass().getName()); + } + + public void + createdCommunicator(SessionHelper session) + { + } + }); + _factory.setRouterIdentity(new Ice.Identity("router", "DemoGlacier2")); + + login(); + } + + protected void + login() + { + String[] options = {"Login", "Cancel" }; + // Show Login Dialog. + int option = JOptionPane.showOptionDialog(this, _connectionPanel, "Login", JOptionPane.OK_CANCEL_OPTION, + JOptionPane.INFORMATION_MESSAGE, null, options, options[0]); + + if(option == 0) + { + _factory.setRouterHost(_hostField.getText()); + // Connect to Glacier2 using SessionFactoryHelper + _session = _factory.connect(_userNameField.getText(), _passwordField.getText()); + String[] cancel = {"Cancel" }; + + // Show Connecting Dialog + JOptionPane pane = new JOptionPane("Please wait while connecting...", JOptionPane.INFORMATION_MESSAGE, + JOptionPane.DEFAULT_OPTION, null, cancel, cancel[0]); + _loginDialog = pane.createDialog(this, "Connecting"); + _loginDialog.setVisible(true); + + // User pressed cancel. + if(pane.getValue() != JOptionPane.UNINITIALIZED_VALUE) + { + // Destroy session + destroySession(); + } + } + } + + private void + destroySession() + { + if(_session != null) + { + _session.destroy(); + _session = null; + } + } + + private void + exit() + { + destroySession(); + dispose(); + Runtime.getRuntime().exit(0); + } + + public void + appendMessage(String message) + { + Document doc = (Document) _output.getDocument(); + Element e = doc.getDefaultRootElement(); + AttributeSet attr = e.getAttributes().copyAttributes(); + try + { + doc.insertString(doc.getLength(), message + "\n", attr); + } + catch(BadLocationException ex) + { + } + _output.setCaretPosition(doc.getLength()); + } + + private static void + locateOnScreen(Component component) + { + Dimension paneSize = component.getSize(); + Dimension screenSize = component.getToolkit().getScreenSize(); + component.setLocation((screenSize.width - paneSize.width) / 2, (screenSize.height - paneSize.height) / 2); + } + + private JLabel _status; + private JTextArea _output; + private JTextArea _input; + private JScrollPane _outputScroll; + + // Login/Logout actions. + private AbstractAction _login; + private AbstractAction _logout; + private AbstractAction _exit; + + // Login dialog + private JDialog _loginDialog; + private JTextField _userNameField; + private JTextField _passwordField; + private JTextField _hostField; + private JPanel _connectionPanel; + + // The session factory and current session. + private SessionFactoryHelper _factory; + private SessionHelper _session; + private Demo.ChatSessionPrx _chat; +} diff --git a/java/demo/Glacier2/chat/README b/java/demo/Glacier2/chat/README new file mode 100644 index 00000000000..1333ed77b7e --- /dev/null +++ b/java/demo/Glacier2/chat/README @@ -0,0 +1 @@ +TODO diff --git a/java/demo/Glacier2/chat/build.xml b/java/demo/Glacier2/chat/build.xml new file mode 100644 index 00000000000..23469f61a21 --- /dev/null +++ b/java/demo/Glacier2/chat/build.xml @@ -0,0 +1,47 @@ +<!-- + ********************************************************************** + + Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. + + This copy of Ice is licensed to you under the terms described in the + ICE_LICENSE file included in this distribution. + + ********************************************************************** +--> + +<project name="demo_Glacier2_chat" default="all" basedir="."> + + <!-- set global properties for this build --> + <property name="top.dir" value="../../.."/> + + <!-- import common definitions --> + <import file="${top.dir}/config/common.xml"/> + + <target name="generate" depends="init"> + <!-- Create the output directory for generated code --> + <mkdir dir="${generated.dir}"/> + <slice2java outputdir="${generated.dir}"> + <includepath> + <pathelement path="${slice.dir}"/> + </includepath> + <fileset dir="." includes="Chat.ice"/> + </slice2java> + </target> + + <target name="compile" depends="generate"> + <mkdir dir="${class.dir}"/> + <javac srcdir=".:${generated.dir}" destdir="${class.dir}" debug="${debug}"> + <exclude name="${generated.dir}/**"/> + <classpath refid="ice.classpath"/> + <compilerarg value="${javac.lint}"/> + </javac> + </target> + + <target name="all" depends="compile"/> + + <target name="clean"> + <delete dir="${generated.dir}"/> + <delete dir="${class.dir}"/> + </target> + +</project> diff --git a/java/demo/Glacier2/chat/config.client b/java/demo/Glacier2/chat/config.client new file mode 100644 index 00000000000..0e7d29d4e67 --- /dev/null +++ b/java/demo/Glacier2/chat/config.client @@ -0,0 +1,39 @@ +# +# Warn about connection exceptions +# +#Ice.Warn.Connections=1 + +# +# Network Tracing +# +# 0 = no network tracing +# 1 = trace connection establishment and closure +# 2 = like 1, but more detailed +# 3 = like 2, but also trace data transfer +# +#Ice.Trace.Network=1 + +# +# Protocol Tracing +# +# 0 = no protocol tracing +# 1 = trace protocol messages +# +#Ice.Trace.Protocol=1 + +# +# Security Tracing +# +# 0 = no security tracing +# 1 = trace messages +# +#IceSSL.Trace.Security=1 + +# +# SSL Configuration +# +Ice.Plugin.IceSSL=IceSSL.PluginFactory +IceSSL.DefaultDir=../../../../certs +IceSSL.Keystore=client.jks +IceSSL.Password=password +IceSSL.Truststore=certs.jks diff --git a/java/demo/Ice/README b/java/demo/Ice/README index 4e430133137..73587d81b47 100644 --- a/java/demo/Ice/README +++ b/java/demo/Ice/README @@ -66,6 +66,11 @@ Demos in this directory: This demo shows how to use sessions to clean up client-specific resources in a server after the client shuts down or crashes. +- swing + + A swing application that shows how to use Asynchronous Method + Invocation (AMI) in a graphical client. + - throughput A simple throughput demo that allows you to send sequences of diff --git a/java/demo/Ice/build.xml b/java/demo/Ice/build.xml index f6313e055bc..2f078a57998 100644 --- a/java/demo/Ice/build.xml +++ b/java/demo/Ice/build.xml @@ -25,6 +25,7 @@ <ant dir="plugin"/> <ant dir="serialize"/> <ant dir="session"/> + <ant dir="swing"/> <ant dir="throughput"/> <ant dir="value"/> </target> @@ -43,6 +44,7 @@ <ant dir="plugin" target="clean"/> <ant dir="serialize" target="clean"/> <ant dir="session" target="clean"/> + <ant dir="swing" target="clean"/> <ant dir="throughput" target="clean"/> <ant dir="value" target="clean"/> </target> diff --git a/java/demo/Ice/swing/.gitignore b/java/demo/Ice/swing/.gitignore new file mode 100644 index 00000000000..e5786e5ddd4 --- /dev/null +++ b/java/demo/Ice/swing/.gitignore @@ -0,0 +1 @@ +Hello.jar diff --git a/java/demo/Ice/swing/Client.java b/java/demo/Ice/swing/Client.java new file mode 100644 index 00000000000..0333548d285 --- /dev/null +++ b/java/demo/Ice/swing/Client.java @@ -0,0 +1,659 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; + +public class Client extends JFrame +{ + public static void main(final String[] args) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + try + { + // + // Create and set up the window. + // + new Client(args); + } + catch(Ice.LocalException e) + { + JOptionPane.showMessageDialog(null, e.toString(), "Initialization failed", + JOptionPane.ERROR_MESSAGE); + } + } + }); + } + + private void destroyCommunicator() + { + if(_communicator == null) + { + return; + } + + // + // Destroy the Ice communicator. + // + try + { + _communicator.destroy(); + } + catch(Throwable ex) + { + ex.printStackTrace(); + } + finally + { + _communicator = null; + } + } + + Client(String[] args) + { + // + // Initialize an Ice communicator. + // + try + { + Ice.InitializationData initData = new Ice.InitializationData(); + initData.properties = Ice.Util.createProperties(); + initData.properties.load("config.client"); + _communicator = Ice.Util.initialize(args, initData); + } + catch(Throwable ex) + { + handleException(ex); + } + + Container cp = this; + + JLabel l1 = new JLabel("Hostname"); + _hostname = new JTextField(); + JLabel l2 = new JLabel("Mode"); + _mode = new JComboBox(); + JLabel l3 = new JLabel("Timeout"); + _timeoutSlider = new JSlider(0, MAX_TIME); + _timeoutLabel = new JLabel("0.0"); + JLabel l4 = new JLabel("Delay"); + _delaySlider = new JSlider(0, MAX_TIME); + _delayLabel = new JLabel("0.0"); + JPanel buttonPanel = new JPanel(); + _hello = new JButton("Hello World!"); + _shutdown = new JButton("Shutdown"); + _flush = new JButton("Flush"); + _flush.setEnabled(false); + JPanel statusPanel = new JPanel(); + JSeparator statusPanelSeparator = new JSeparator(); + _status = new JLabel(); + _status.setText("Ready"); + + // + // Default to localhost. + // + _hostname.setText("127.0.0.1"); + + final String[] modes = new String[] + { + "Twoway", "Twoway Secure", "Oneway", "Oneway Batch", "Oneway Secure", "Oneway Secure Batch", "Datagram", + "Datagram Batch" + }; + _mode.setModel(new DefaultComboBoxModel(modes)); + + _hello.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + sayHello(); + } + }); + _shutdown.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + shutdown(); + } + }); + _flush.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + flush(); + } + }); + _mode.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + changeDeliveryMode(_mode.getSelectedIndex()); + } + }); + changeDeliveryMode(_mode.getSelectedIndex()); + + _timeoutSlider.addChangeListener(new SliderListener(_timeoutSlider, _timeoutLabel)); + _timeoutSlider.setValue(0); + _delaySlider.addChangeListener(new SliderListener(_delaySlider, _delayLabel)); + _delaySlider.setValue(0); + + GridBagConstraints gridBagConstraints; + + cp.setMaximumSize(null); + cp.setPreferredSize(null); + cp.setLayout(new GridBagLayout()); + + l1.setText("Hostname"); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.insets = new Insets(5, 5, 5, 5); + cp.add(l1, gridBagConstraints); + + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + gridBagConstraints.insets = new Insets(5, 0, 5, 5); + cp.add(_hostname, gridBagConstraints); + + l2.setText("Mode"); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.insets = new Insets(0, 5, 5, 0); + cp.add(l2, gridBagConstraints); + + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + gridBagConstraints.insets = new Insets(0, 0, 5, 5); + cp.add(_mode, gridBagConstraints); + + l3.setText("Timeout"); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.insets = new Insets(0, 5, 5, 0); + cp.add(l3, gridBagConstraints); + + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = GridBagConstraints.WEST; + cp.add(_timeoutSlider, gridBagConstraints); + + _timeoutLabel.setMinimumSize(new Dimension(20, 17)); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.insets = new Insets(0, 5, 5, 5); + cp.add(_timeoutLabel, gridBagConstraints); + + l4.setText("Delay"); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 3; + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.insets = new Insets(0, 5, 5, 0); + cp.add(l4, gridBagConstraints); + + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = GridBagConstraints.WEST; + cp.add(_delaySlider, gridBagConstraints); + + _delayLabel.setMinimumSize(new Dimension(20, 17)); + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 3; + gridBagConstraints.anchor = GridBagConstraints.WEST; + gridBagConstraints.insets = new Insets(0, 5, 5, 5); + cp.add(_delayLabel, gridBagConstraints); + + _hello.setText("Hello World!"); + buttonPanel.add(_hello); + + _shutdown.setText("Shutdown"); + buttonPanel.add(_shutdown); + + _flush.setText("Flush"); + buttonPanel.add(_flush); + + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 4; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.ipady = 5; + cp.add(buttonPanel, gridBagConstraints); + + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 5; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + gridBagConstraints.insets = new Insets(0, 5, 5, 5); + cp.add(statusPanelSeparator, gridBagConstraints); + + gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 6; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.fill = GridBagConstraints.HORIZONTAL; + gridBagConstraints.insets = new Insets(0, 5, 5, 5); + cp.add(_status, gridBagConstraints); + + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + + _shutdownHook = new Thread("Shutdown hook") + { + public void run() + { + destroyCommunicator(); + } + }; + + try + { + Runtime.getRuntime().addShutdownHook(_shutdownHook); + } + catch(IllegalStateException e) + { + // + // Shutdown in progress, ignored + // + } + + addWindowListener(new WindowAdapter() + { + public void windowClosing(WindowEvent e) + { + destroyCommunicator(); + Runtime.getRuntime().removeShutdownHook(_shutdownHook); + dispose(); + Runtime.getRuntime().exit(0); + } + }); + + + setTitle("Ice - Hello World!"); + pack(); + locateOnScreen(this); + setVisible(true); + } + + private enum DeliveryMode + { + TWOWAY, + TWOWAY_SECURE, + ONEWAY, + ONEWAY_BATCH, + ONEWAY_SECURE, + ONEWAY_SECURE_BATCH, + DATAGRAM, + DATAGRAM_BATCH; + + Ice.ObjectPrx apply(Ice.ObjectPrx prx) + { + switch (this) + { + case TWOWAY: + { + prx = prx.ice_twoway(); + break; + } + case TWOWAY_SECURE: + { + prx = prx.ice_twoway().ice_secure(true); + break; + } + case ONEWAY: + { + prx = prx.ice_oneway(); + break; + } + case ONEWAY_BATCH: + { + prx = prx.ice_batchOneway(); + break; + } + case ONEWAY_SECURE: + { + prx = prx.ice_oneway().ice_secure(true); + break; + } + case ONEWAY_SECURE_BATCH: + { + prx = prx.ice_batchOneway().ice_secure(true); + break; + } + case DATAGRAM: + { + prx = prx.ice_datagram(); + break; + } + case DATAGRAM_BATCH: + { + prx = prx.ice_batchDatagram(); + break; + } + } + return prx; + } + + public boolean isBatch() + { + return this == ONEWAY_BATCH || this == DATAGRAM_BATCH || this == ONEWAY_SECURE_BATCH; + } + } + + private Demo.HelloPrx createProxy() + { + String host = _hostname.getText().toString().trim(); + if(host.length() == 0) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + _status.setText("No hostname"); + } + }); + return null; + } + + String s = "hello:tcp -h " + host + " -p 10000:ssl -h " + host + " -p 10001:udp -h " + host + " -p 10000"; + Ice.ObjectPrx prx = _communicator.stringToProxy(s); + prx = _deliveryMode.apply(prx); + int timeout = _timeoutSlider.getValue(); + if(timeout != 0) + { + prx = prx.ice_timeout(timeout); + } + return Demo.HelloPrxHelper.uncheckedCast(prx); + } + + class SayHelloI extends Demo.AMI_Hello_sayHello implements Ice.AMISentCallback + { + synchronized public void ice_exception(final Ice.LocalException ex) + { + assert (!_response); + _response = true; + + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + handleException(ex); + } + }); + } + + synchronized public void ice_sent() + { + if(_response) + { + return; + } + + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + if(_deliveryMode == DeliveryMode.TWOWAY || _deliveryMode == DeliveryMode.TWOWAY_SECURE) + { + _status.setText("Waiting for response"); + } + else + { + _status.setText("Ready"); + } + } + }); + } + + synchronized public void ice_response() + { + assert (!_response); + _response = true; + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + _status.setText("Ready"); + } + }); + } + + private boolean _response = false; + } + + private void sayHello() + { + Demo.HelloPrx hello = createProxy(); + if(hello == null) + { + return; + } + + int delay = _delaySlider.getValue(); + try + { + if(!_deliveryMode.isBatch()) + { + if(hello.sayHello_async(new SayHelloI(), delay)) + { + if(_deliveryMode == DeliveryMode.TWOWAY || _deliveryMode == DeliveryMode.TWOWAY_SECURE) + { + _status.setText("Waiting for response"); + } + } + else + { + _status.setText("Sending request"); + } + } + else + { + _flush.setEnabled(true); + hello.sayHello(delay); + _status.setText("Queued sayHello request"); + } + } + catch(Ice.LocalException ex) + { + handleException(ex); + } + } + + private void shutdown() + { + Demo.HelloPrx hello = createProxy(); + if(hello == null) + { + return; + } + + try + { + if(!_deliveryMode.isBatch()) + { + hello.shutdown_async(new Demo.AMI_Hello_shutdown() + { + public void ice_exception(final Ice.LocalException ex) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + handleException(ex); + } + }); + } + + public void ice_response() + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + _status.setText("Ready"); + } + }); + } + }); + if(_deliveryMode == DeliveryMode.TWOWAY || _deliveryMode == DeliveryMode.TWOWAY_SECURE) + { + _status.setText("Waiting for response"); + } + } + else + { + _flush.setEnabled(true); + hello.shutdown(); + _status.setText("Queued shutdown request"); + } + } + catch(Ice.LocalException ex) + { + handleException(ex); + } + } + + private void flush() + { + new Thread(new Runnable() + { + public void run() + { + try + { + _communicator.flushBatchRequests(); + } + catch(final Ice.LocalException ex) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + handleException(ex); + } + }); + } + } + }).start(); + + _flush.setEnabled(false); + _status.setText("Flushed batch requests"); + } + + private void changeDeliveryMode(long id) + { + switch ((int)id) + { + case 0: + _deliveryMode = DeliveryMode.TWOWAY; + break; + case 1: + _deliveryMode = DeliveryMode.TWOWAY_SECURE; + break; + case 2: + _deliveryMode = DeliveryMode.ONEWAY; + break; + case 3: + _deliveryMode = DeliveryMode.ONEWAY_BATCH; + break; + case 4: + _deliveryMode = DeliveryMode.ONEWAY_SECURE; + break; + case 5: + _deliveryMode = DeliveryMode.ONEWAY_SECURE_BATCH; + break; + case 6: + _deliveryMode = DeliveryMode.DATAGRAM; + break; + case 7: + _deliveryMode = DeliveryMode.DATAGRAM_BATCH; + break; + } + } + + private void handleException(final Throwable ex) + { + // Ignore CommunicatorDestroyedException which could occur on + // shutdown. + if(ex instanceof Ice.CommunicatorDestroyedException) + { + return; + } + ex.printStackTrace(); + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + _status.setText(ex.getClass().getName()); + } + }); + } + + private static class SliderListener implements ChangeListener + { + SliderListener(JSlider slider, JLabel label) + { + _slider = slider; + _label = label; + } + + public void stateChanged(ChangeEvent ce) + { + float value = (float)(_slider.getValue() / 1000.0); + _label.setText(String.format("%.1f", value)); + } + + private JSlider _slider; + private JLabel _label; + } + + private static void locateOnScreen(Component component) + { + Dimension paneSize = component.getSize(); + Dimension screenSize = component.getToolkit().getScreenSize(); + component.setLocation((screenSize.width - paneSize.width) / 2, (screenSize.height - paneSize.height) / 2); + } + + private static final int MAX_TIME = 5000; // 5 seconds + + private JTextField _hostname; + private JComboBox _mode; + private JSlider _timeoutSlider; + private JLabel _timeoutLabel; + private JSlider _delaySlider; + private JLabel _delayLabel; + private JButton _hello; + private JButton _shutdown; + private JButton _flush; + private JLabel _status; + + private Ice.Communicator _communicator; + private DeliveryMode _deliveryMode; + private Thread _shutdownHook; +} diff --git a/java/demo/Ice/swing/Hello.ice b/java/demo/Ice/swing/Hello.ice new file mode 100644 index 00000000000..b5c9e4a599e --- /dev/null +++ b/java/demo/Ice/swing/Hello.ice @@ -0,0 +1,24 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef HELLO_ICE +#define HELLO_ICE + +module Demo +{ + +interface Hello +{ + ["ami"] idempotent void sayHello(int delay); + ["ami"] void shutdown(); +}; + +}; + +#endif diff --git a/java/demo/Ice/swing/README b/java/demo/Ice/swing/README new file mode 100644 index 00000000000..4cd502dda79 --- /dev/null +++ b/java/demo/Ice/swing/README @@ -0,0 +1,12 @@ +This demo illustrates how to write a swing application which invokes +ordinary (twoway) operations, as well as how to make oneway, datagram, +secure, and batched invocations. + +To run the demo, first start the hello server: + +$ cd ../hello +$ java Server + +In a separate window, start the swing client: + +$ java Client diff --git a/java/demo/Ice/swing/build.xml b/java/demo/Ice/swing/build.xml new file mode 100644 index 00000000000..fd6892e81eb --- /dev/null +++ b/java/demo/Ice/swing/build.xml @@ -0,0 +1,44 @@ +<!-- + ********************************************************************** + + Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. + + This copy of Ice is licensed to you under the terms described in the + ICE_LICENSE file included in this distribution. + + ********************************************************************** +--> + +<project name="demo_Ice_swing" default="all" basedir="."> + + <!-- set global properties for this build --> + <property name="top.dir" value="../../.."/> + + <!-- import common definitions --> + <import file="${top.dir}/config/common.xml"/> + + <target name="generate" depends="init"> + <!-- Create the output directory for generated code --> + <mkdir dir="${generated.dir}"/> + <slice2java outputdir="${generated.dir}"> + <fileset dir="." includes="Hello.ice"/> + </slice2java> + </target> + + <target name="compile" depends="generate"> + <mkdir dir="${class.dir}"/> + <javac srcdir=".:${generated.dir}" destdir="${class.dir}" debug="${debug}"> + <exclude name="${generated.dir}/**"/> + <classpath refid="ice.classpath"/> + <compilerarg value="${javac.lint}"/> + </javac> + </target> + + <target name="all" depends="compile"/> + + <target name="clean"> + <delete dir="${generated.dir}"/> + <delete dir="${class.dir}"/> + </target> + +</project> diff --git a/java/demo/Ice/swing/config.client b/java/demo/Ice/swing/config.client new file mode 100644 index 00000000000..45eae32e21f --- /dev/null +++ b/java/demo/Ice/swing/config.client @@ -0,0 +1,26 @@ +# +# Network Tracing +# +# 0 = no network tracing +# 1 = trace connection establishment and closure +# 2 = like 1, but more detailed +# 3 = like 2, but also trace data transfer +# +#Ice.Trace.Network=1 + +# +# Security Tracing +# +# 0 = no security tracing +# 1 = trace messages +# +#IceSSL.Trace.Security=1 + +# +# SSL Configuration +# +Ice.Plugin.IceSSL=IceSSL.PluginFactory +IceSSL.DefaultDir=../../../../certs +IceSSL.Password=password +IceSSL.Keystore=client.jks +IceSSL.Truststore=client.jks diff --git a/java/src/Glacier2/Application.java b/java/src/Glacier2/Application.java new file mode 100644 index 00000000000..fd0812d9958 --- /dev/null +++ b/java/src/Glacier2/Application.java @@ -0,0 +1,552 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package Glacier2; + +/** + * An extension of Ice.Application that makes it easy to write + * Glacier2 applications. + * + * <p> Applications must create a derived class that implements the + * {@link #createSession} and {@link #runWithSession} methods.<p> + * + * The base class invokes {@link #createSession} to create a new + * Glacier2 session and then invokes {@link #runWithSession} in + * which the subclass performs its application logic. The base class + * automatically destroys the session when {@link #runWithSession} + * returns. + * + * If {@link #runWithSession} calls {@link #restart} or raises any of + * the exceptions Ice.ConnectionRefusedException, + * Ice.ConnectionLostException, Ice.UnknownLocalException, + * Ice.RequestFailedException, or Ice.TimeoutException, the base + * class destroys the current session and restarts the application + * with another call to {@link #createSession} followed by + * {@link #runWithSession}. + * + * The application can optionally override the {@link #sessionDestroyed} + * callback method if it needs to take action when connectivity with + * the Glacier2 router is lost. + * + * A program can contain only one instance of this class. + * + * @see Ice.Application + * @see Glacier2.Router + * @see Glacier2.Session + * @see Ice.Communicator + * @see Ice.Logger + * @see #runWithSession + **/ +public abstract class Application extends Ice.Application +{ + /** + * This exception is raised if the session should be restarted. + */ + public class RestartSessionException extends Exception + { + } + + /** + * Initializes an instance that calls {@link Communicator#shutdown} if + * a signal is received. + **/ + public + Application() + { + } + + /** + * Initializes an instance that handles signals according to the signal + * policy. + * + * @param signalPolicy Determines how to respond to signals. + * + * @see SignalPolicy + **/ + public + Application(Ice.SignalPolicy signalPolicy) + { + super(signalPolicy); + } + + + /** + * Called once the communicator has been initialized and the Glacier2 session + * has been established. A derived class must implement <code>runWithSession</code>, + * which is the application's starting method. + * + * @param args The argument vector for the application. <code>Application</code> + * scans the argument vector passed to <code>main</code> for options that are + * specific to the Ice run time and removes them; therefore, the vector passed + * to <code>run</code> is free from Ice-related options and contains only options + * and arguments that are application-specific. + * + * @return The <code>runWithSession</code> method should return zero for successful + * termination, and non-zero otherwise. <code>Application.main</code> returns the + * value returned by <code>runWithSession</code>. + **/ + public abstract int + runWithSession(String[] args) + throws RestartSessionException; + + /** + * Run should not be overridden for Glacier2.Application. Instead + * <code>runWithSession</code> should be used. + */ + final public int + run(String[] args) + { + // This shouldn't be called. + assert false; + return 0; + } + + /** + * Called to restart the application's Glacier2 session. This + * method never returns. + * + * @throws RestartSessionException This exception is always thrown. + **/ + public void + restart() + throws RestartSessionException + { + throw new RestartSessionException(); + } + + /** + * Creates a new Glacier2 session. A call to + * <code>createSession</code> always precedes a call to + * <code>runWithSession</code>. If <code>Ice.LocalException</code> + * is thrown from this method, the application is terminated. + + * @return The Glacier2 session. + **/ + abstract public Glacier2.SessionPrx + createSession(); + + /** + * Called when the base class detects that the session has been destroyed. + * A subclass can override this method to take action after the loss of + * connectivity with the Glacier2 router. + **/ + public void + sessionDestroyed() + { + } + + /** + * Returns the Glacier2 router proxy + * @return The router proxy. + **/ + public static Glacier2.RouterPrx + router() + { + return _router; + } + + /** + * Returns the Glacier2 session proxy + * @return The session proxy. + **/ + public static Glacier2.SessionPrx + session() + { + return _session; + } + + /** + * Returns the category to be used in the identities of all of the client's + * callback objects. Clients must use this category for the router to + * forward callback requests to the intended client. + * @return The category. + * @throws SessionNotExistException No session exists. + **/ + public String + categoryForClient() throws SessionNotExistException + { + if(_router == null) + { + throw new SessionNotExistException(); + } + return _router.getCategoryForClient(); + } + + /** + * Create a new Ice identity for callback objects with the given + * identity name field. + * @return The identity. + * @throws SessionNotExistException No session exists. + **/ + public Ice.Identity + createCallbackIdentity(String name) throws SessionNotExistException + { + return new Ice.Identity(name, categoryForClient()); + } + + /** + * Adds a servant to the callback object adapter's Active Servant Map with a UUID. + * @param servant The servant to add. + * @return The proxy for the servant. + * @throws SessionNotExistException No session exists. + **/ + public Ice.ObjectPrx + addWithUUID(Ice.Object servant) throws SessionNotExistException + { + return objectAdapter().add(servant, createCallbackIdentity(java.util.UUID.randomUUID().toString())); + } + + /** + * Creates an object adapter for callback objects. + * @return The object adapter. + * @throws SessionNotExistException No session exists. + */ + public synchronized Ice.ObjectAdapter + objectAdapter() throws SessionNotExistException + { + if(_adapter == null) + { + if(_router == null) + { + throw new SessionNotExistException(); + } + // TODO: Depending on the resolution of + // http://bugzilla/bugzilla/show_bug.cgi?id=4264 the OA + // name could be an empty string. + String uuid = java.util.UUID.randomUUID().toString(); + _adapter = communicator().createObjectAdapterWithRouter(uuid, _router); + _adapter.activate(); + } + return _adapter; + } + + private class SessionPingThread extends Thread + { + SessionPingThread(Glacier2.RouterPrx router, long period) + { + _router = router; + _period = period; + _done = false; + } + + synchronized public void + run() + { + while(true) + { + _router.refreshSession_async(new Glacier2.AMI_Router_refreshSession() + { + public void + ice_response() + { + } + + public void + ice_exception(Ice.LocalException ex) + { + // Here the session has gone. The thread + // terminates, and we notify the + // application that the session has been + // destroyed. + done(); + sessionDestroyed(); + } + + public void + ice_exception(Ice.UserException ex) + { + // Here the session has gone. The thread + // terminates, and we notify the + // application that the session has been + // destroyed. + done(); + sessionDestroyed(); + } + }); + + if(!_done) + { + try + { + wait(_period); + } + catch(InterruptedException ex) + { + } + } + + if(_done) + { + break; + } + } + } + + public synchronized void + done() + { + if(!_done) + { + _done = true; + notify(); + } + } + + private final Glacier2.RouterPrx _router; + private final long _period; + private boolean _done = false; + } + + protected int + doMain(Ice.StringSeqHolder argHolder, Ice.InitializationData initData) + { + // Set the default properties for all Glacier2 applications. + initData.properties.setProperty("Ice.ACM.Client", "0"); + initData.properties.setProperty("Ice.RetryIntervals", "-1"); + + boolean restart; + Ice.IntHolder ret = new Ice.IntHolder(); + do + { + // A copy of the initialization data and the string seq + // needs to be passed to doMainInternal, as these can be + // changed by the application. + Ice.InitializationData id = (Ice.InitializationData)initData.clone(); + id.properties = id.properties._clone(); + Ice.StringSeqHolder h = new Ice.StringSeqHolder(); + h.value = argHolder.value.clone(); + + restart = doMain(h, id, ret); + } + while(restart); + return ret.value; + } + + private boolean + doMain(Ice.StringSeqHolder argHolder, Ice.InitializationData initData, Ice.IntHolder status) + { + // Reset internal state variables from Ice.Application. The + // remainder are reset at the end of this method. + _callbackInProgress = false; + _destroyed = false; + _interrupted = false; + + boolean restart = false; + status.value = 0; + + SessionPingThread ping = null; + try + { + _communicator = Ice.Util.initialize(argHolder, initData); + + _router = Glacier2.RouterPrxHelper.uncheckedCast(communicator().getDefaultRouter()); + if(_router == null) + { + Ice.Util.getProcessLogger().error("no glacier2 router configured"); + status.value = 1; + } + else + { + // + // The default is to destroy when a signal is received. + // + if(_signalPolicy == Ice.SignalPolicy.HandleSignals) + { + destroyOnInterrupt(); + } + + // If createSession throws, we're done. + try + { + _session = createSession(); + _createdSession = true; + } + catch(Ice.LocalException ex) + { + Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex)); + status.value = 1; + } + + if(_createdSession) + { + ping = new SessionPingThread(_router, (_router.getSessionTimeout() * 1000) / 2); + ping.start(); + status.value = runWithSession(argHolder.value); + } + } + } + // We want to restart on those exceptions which indicate a + // break down in communications, but not those exceptions that + // indicate a programming logic error (ie: marshal, protocol + // failure, etc). + catch(RestartSessionException ex) + { + restart = true; + } + catch(Ice.ConnectionRefusedException ex) + { + Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex)); + restart = true; + } + catch(Ice.ConnectionLostException ex) + { + Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex)); + restart = true; + } + catch(Ice.UnknownLocalException ex) + { + Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex)); + restart = true; + } + catch(Ice.RequestFailedException ex) + { + Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex)); + restart = true; + } + catch(Ice.TimeoutException ex) + { + Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex)); + restart = true; + } + catch(Ice.LocalException ex) + { + Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex)); + status.value = 1; + } + catch(java.lang.Exception ex) + { + Ice.Util.getProcessLogger().error("unknown exception" + IceInternal.Ex.toString(ex)); + status.value = 1; + } + catch(java.lang.Error err) + { + // + // We catch Error to avoid hangs in some non-fatal situations + // + Ice.Util.getProcessLogger().error("Java error " + IceInternal.Ex.toString(err)); + status.value = 1; + } + + // This clears any set interrupt. + if(_signalPolicy == Ice.SignalPolicy.HandleSignals) + { + defaultInterrupt(); + } + + synchronized(_mutex) + { + while(_callbackInProgress) + { + try + { + _mutex.wait(); + } + catch(java.lang.InterruptedException ex) + { + } + } + + if(_destroyed) + { + _communicator = null; + } + else + { + _destroyed = true; + // + // And _communicator != null, meaning will be + // destroyed next, _destroyed = true also ensures that + // any remaining callback won't do anything + // + } + } + + if(ping != null) + { + ping.done(); + while(true) + { + try + { + ping.join(); + break; + } + catch(InterruptedException ex) + { + } + } + ping = null; + } + + if(_createdSession && _router != null) + { + try + { + _router.destroySession(); + } + catch(Ice.ConnectionLostException ex) + { + // Expected: the router closed the connection. + } + catch(Glacier2.SessionNotExistException ex) + { + // This can also occur. + } + catch(Throwable ex) + { + // Not expected. + Ice.Util.getProcessLogger().error("unexpected exception when destroying the session:\n" + + IceInternal.Ex.toString(ex)); + } + _router = null; + } + + if(_communicator != null) + { + try + { + _communicator.destroy(); + } + catch(Ice.LocalException ex) + { + Ice.Util.getProcessLogger().error(IceInternal.Ex.toString(ex)); + status.value = 1; + } + catch(java.lang.Exception ex) + { + Ice.Util.getProcessLogger().error("unknown exception" + IceInternal.Ex.toString(ex)); + status.value = 1; + } + _communicator = null; + } + + synchronized(_mutex) + { + if(_appHook != null) + { + _appHook.done(); + } + } + + // Reset internal state. We cannot reset the Application state + // here, since _destroyed must remain true until we re-run + // this method. + _adapter = null; + _router = null; + _session = null; + _createdSession = false; + + return restart; + } + + private static Ice.ObjectAdapter _adapter; + private static Glacier2.RouterPrx _router; + private static Glacier2.SessionPrx _session; + private static boolean _createdSession = false; +} diff --git a/java/src/Glacier2/SessionFactoryHelper.java b/java/src/Glacier2/SessionFactoryHelper.java new file mode 100644 index 00000000000..ac77170b677 --- /dev/null +++ b/java/src/Glacier2/SessionFactoryHelper.java @@ -0,0 +1,355 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package Glacier2; + +/** + * A helper class for using Glacier2 with GUI applications. + * + * Applications should create a session factory for each Glacier2 router to which the application will + * connect. To connect with the Glacier2 router, call {@link SessionFactory#connect}. The callback object is + * notified of the various life cycle events. Once the session is torn down for whatever reason, the application + * can use the session factory to create another connection. + */ +public class SessionFactoryHelper +{ + /** + * A callback class to get notifications of status changes in the Glacier2 session. + * All callbacks on the <code>Callback</code> interface occur in the main swing thread. + */ + public interface Callback + { + /** + * Notifies the application that the communicator was created. + * + * @param session The Glacier2 session. + */ + void + createdCommunicator(SessionHelper session); + + /** + * Notifies the application that the Glacier2 session has been established. + * + * @param session The established session. + */ + + void + connected(SessionHelper session) + throws SessionNotExistException; + + /** + * Notifies the application that the Glacier2 session has been disconnected. + * + * @param session The disconnected session. + */ + void + disconnected(SessionHelper session); + + /** + * Notifies the application that the Glacier2 session establishment failed. + * + * @param session The session reporting the connection + * failure. + * @param ex The exception. + */ + void + connectFailed(SessionHelper session, Throwable ex); + } + + /** + * Creates a SessionFactory object. + * + * @param callback The callback object for notifications. + * @throws {@link Ice.InitializationException} + */ + public + SessionFactoryHelper(Callback callback) throws Ice.InitializationException + { + initialize(callback, new Ice.InitializationData(), Ice.Util.createProperties()); + } + + /** + * Creates a SessionFactory object. + * + * @param initData The initialization data to use when creating the communicator. + * @param callback The callback object for notifications. + * @throws {@link Ice.InitializationException} + */ + public + SessionFactoryHelper(Ice.InitializationData initData, Callback callback) throws Ice.InitializationException + { + initialize(callback, initData, initData.properties); + } + + /** + * Creates a SessionFactory object. + * + * @param properties The properties to use when creating the communicator. + * @param callback The callback object for notifications. + * @throws {@link Ice.InitializationException} + */ + public + SessionFactoryHelper(Ice.Properties properties, Callback callback) throws Ice.InitializationException + { + initialize(callback, new Ice.InitializationData(), properties); + } + + private void + initialize(Callback callback, Ice.InitializationData initData, Ice.Properties properties) + throws Ice.InitializationException + { + if(callback == null) + { + throw new Ice.InitializationException("Attempt to create a SessionFactoryHelper with a null Callback" + + "argument"); + } + + if(initData == null) + { + throw new Ice.InitializationException("Attempt to create a SessionFactoryHelper with a null " + + "InitializationData argument"); + } + + if(properties == null) + { + throw new Ice.InitializationException("Attempt to create a SessionFactoryHelper with a null Properties " + + "argument"); + } + + _callback = callback; + _initData = initData; + _initData.properties = properties; + + // + // Set default properties; + // + _initData.properties.setProperty("Ice.ACM.Client", "0"); + _initData.properties.setProperty("Ice.RetryIntervals", "-1"); + } + + /** + * Set the router object identity. + * + * @return The Glacier2 router's identity. + */ + synchronized public void + setRouterIdentity(Ice.Identity identity) + { + _identity = identity; + } + + /** + * Returns the object identity of the Glacier2 router. + * + * @return The Glacier2 router's identity. + */ + synchronized public Ice.Identity + getRouterIdentity() + { + return _identity; + } + + /** + * Sets the host on which the Glacier2 router runs. + * + * @param hostname The host name (or IP address) of the router host. + */ + synchronized public void + setRouterHost(String hostname) + { + _routerHost = hostname; + } + + /** + * Returns the host on which the Glacier2 router runs. + * + * @return The Glacier2 router host. + */ + synchronized public String + getRouterHost() + { + return _routerHost; + } + + /** + * Sets whether to connect with the Glacier2 router securely. + * + * @param secure If <code>true</code>, the client connects to the router + * via SSL; otherwise, the client connects via TCP. + */ + synchronized public void + setSecure(boolean secure) + { + _secure = secure; + } + + /** + * Returns whether the session factory will establish a secure connection to the Glacier2 router. + * + * @return The secure flag. + */ + synchronized public boolean + getSecure() + { + return _secure; + } + + /** + * Sets the connect and connection timeout for the Glacier2 router. + * + * @param timeoutMillisecs The timeout in milliseconds. A zero + * or negative timeout value indicates that the router proxy has no associated timeout. + */ + synchronized public void + setTimeout(int timeoutMillisecs) + { + _timeout = timeoutMillisecs; + } + + /** + * Returns the connect and connection timeout associated with the Glacier2 router. + * + * @return The timeout. + */ + synchronized public int + getTimeout() + { + return _timeout; + } + + /** + * Sets the Glacier2 router port to connect to. + * + * @param port The port. If 0, then the default port (4063 for TCP or 4064 for SSL) is used. + */ + synchronized public void + setPort(int port) + { + _port = port; + } + + /** + * Returns the Glacier2 router port to connect to. + * + * @return The port. + */ + synchronized public int + getPort() + { + return _port == 0 ? (_secure ? GLACIER2_TCP_PORT : GLACIER2_SSL_PORT) : _port; + } + + /** + * Returns the initialization data used to initialize the communicator. + * + * @return The initialization data. + */ + synchronized public Ice.InitializationData + getInitializationData() + { + return _initData; + } + + /** + * Connects to the Glacier2 router using the associated SSL credentials. + * + * Once the connection is established, {@link Callback#connected} is called on the callback object; + * upon failure, {@link Callback#connectFailed} is called with the exception. + * + * @return The connected session. + */ + synchronized public SessionHelper + connect() + { + SessionHelper session = new SessionHelper(_callback, createInitData()); + session.connect(); + return session; + } + + /** + * Connect the Glacier2 session using user name and password credentials. + * + * Once the connection is established, {@link Callback#connected} is called on the callback object; + * upon failure, {@link Callback#connectFailed) is called with the exception. + * + * @param username The user name. + * @param password The password. + * @return The connected session. + */ + synchronized public SessionHelper + connect(final String username, final String password) + { + SessionHelper session = new SessionHelper(_callback, createInitData()); + session.connect(username, password); + return session; + } + + private Ice.InitializationData + createInitData() + { + // Clone the initialization data and properties. + Ice.InitializationData initData = (Ice.InitializationData)_initData.clone(); + initData.properties = initData.properties._clone(); + + if(initData.properties.getProperty("Ice.Default.Router").length() == 0) + { + StringBuffer sb = new StringBuffer(); + sb.append("\""); + sb.append(Ice.Util.identityToString(_identity)); + sb.append("\""); + sb.append(":"); + + if(_secure) + { + sb.append("ssl -p "); + } + else + { + sb.append("tcp -p "); + } + + if(_port != 0) + { + sb.append(_port); + } + else + { + if(_secure) + { + sb.append(GLACIER2_SSL_PORT); + } + else + { + sb.append(GLACIER2_TCP_PORT); + } + } + + sb.append(" -h "); + sb.append(_routerHost); + if(_timeout > 0) + { + sb.append(" -t "); + sb.append(_timeout); + } + + initData.properties.setProperty("Ice.Default.Router", sb.toString()); + } + return initData; + } + + private Callback _callback; + private String _routerHost = "127.0.0.1"; + private Ice.InitializationData _initData; + private Ice.Identity _identity = new Ice.Identity("router", "Glacier2"); + private boolean _secure = true; + private int _port = 0; + private int _timeout = 10000; + private static final int GLACIER2_SSL_PORT = 4064; + private static final int GLACIER2_TCP_PORT = 4063; +} diff --git a/java/src/Glacier2/SessionHelper.java b/java/src/Glacier2/SessionHelper.java new file mode 100644 index 00000000000..bea4a5dec15 --- /dev/null +++ b/java/src/Glacier2/SessionHelper.java @@ -0,0 +1,496 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** +package Glacier2; + +import javax.swing.SwingUtilities; + +import Glacier2.SessionFactoryHelper.Callback; + +/** + * A helper class for using Glacier2 with GUI applications. + */ +public class SessionHelper +{ + private class SessionRefreshThread extends Thread + { + SessionRefreshThread(Glacier2.RouterPrx router, long period) + { + _router = router; + _period = period; + _done = false; + } + + synchronized public void + run() + { + while(true) + { + _router.refreshSession_async(new Glacier2.AMI_Router_refreshSession() + { + public void ice_response() + { + } + + public void ice_exception(Ice.LocalException ex) + { + done(); + SessionHelper.this.destroy(); + } + + public void ice_exception(Ice.UserException ex) + { + done(); + SessionHelper.this.destroy(); + } + }); + if(!_done) + { + try + { + wait(_period); + } + catch(InterruptedException ex) + { + } + } + if(_done) + { + break; + } + } + } + + public synchronized void + done() + { + if(!_done) + { + _done = true; + notify(); + } + } + + private final Glacier2.RouterPrx _router; + private final long _period; + private boolean _done = false; + } + + /** + * Creates a Glacier2 session. + * + * @param callback The callback for notifications about session establishment. + * @param initData The {@link Ice.InitializationData} for initializing the communicator. + */ + public SessionHelper(SessionFactoryHelper.Callback callback, Ice.InitializationData initData) + { + _callback = callback; + _initData = initData; + } + + /** + * Destroys the Glacier2 session. + * + * Once the session has been destroyed, {@link Callback.disconnected} is called on + * the associated callback object. + */ + synchronized public void + destroy() + { + if(_destroy) + { + return; + } + _destroy = true; + if(_refreshThread == null) + { + // In this case a connecting session is being + // destroyed. The communicator and session will be + // destroyed when the connection establishment has + // completed. + return; + } + _session = null; + + try + { + Runtime.getRuntime().removeShutdownHook(_shutdownHook); + } + catch(IllegalStateException ex) + { + // Ignore + } + catch(SecurityException ex) + { + // Ignore + } + + // Run the destroyInternal in a thread. This is because it + // destroyInternal makes remote invocations. + new Thread(new Runnable() + { + public void run() + { + destroyInternal(); + } + }).start(); + } + + /** + * Returns the session's communicator object. + * @return The communicator. + */ + synchronized public Ice.Communicator + communicator() + { + return _communicator; + } + + /** + * Returns the category to be used in the identities of all of the client's + * callback objects. Clients must use this category for the router to + * forward callback requests to the intended client. + * @return The category. + * @throws SessionNotExistException No session exists. + **/ + synchronized public String + categoryForClient() + throws SessionNotExistException + { + if(_router == null) + { + throw new SessionNotExistException(); + } + + return _router.getCategoryForClient(); + } + + /** + * Adds a servant to the callback object adapter's Active Servant Map with a UUID. + * @param servant The servant to add. + * @return The proxy for the servant. + * @throws SessionNotExistException No session exists. + **/ + public synchronized Ice.ObjectPrx + addWithUUID(Ice.Object servant) + throws SessionNotExistException + { + if(_router == null) + { + throw new SessionNotExistException(); + } + return internalObjectAdapter().add(servant, new Ice.Identity(java.util.UUID.randomUUID().toString(), + _router.getCategoryForClient())); + } + + /** + * Returns the Glacier2 session proxy. If the session hasn't been established yet, + * or the session has already been destroyed, throws SessionNotExistException. + * @return The session proxy, or throws SessionNotExistException if no session exists. + * @throws SessionNotExistException No session exists. + */ + synchronized public Glacier2.SessionPrx + session() + throws SessionNotExistException + { + if(_session == null) + { + throw new SessionNotExistException(); + } + + return _session; + } + + /** + * Returns true if there is an active session, otherwise returns false. + * @return <code>true</code>if session exists or false if no session exists. + */ + public boolean + isConnected() + { + synchronized(this) + { + return _connected; + } + } + + /** + * Creates an object adapter for callback objects. + * @return The object adapter. + * @throws SessionNotExistException No session exists. + */ + synchronized public Ice.ObjectAdapter + objectAdapter() + throws SessionNotExistException + { + return internalObjectAdapter(); + } + + // Only call this method when the calling thread owns the lock + private Ice.ObjectAdapter + internalObjectAdapter() + throws SessionNotExistException + { + if(_router == null) + { + throw new SessionNotExistException(); + } + if(_adapter == null) + { + // TODO: Depending on the resolution of + // http://bugzilla/bugzilla/show_bug.cgi?id=4264 the OA + // name could be an empty string. + _adapter = _communicator.createObjectAdapterWithRouter(java.util.UUID.randomUUID().toString(), _router); + _adapter.activate(); + } + return _adapter; + } + + private interface ConnectStrategy + { + Glacier2.SessionPrx + connect(Glacier2.RouterPrx router) + throws CannotCreateSessionException, PermissionDeniedException; + } + + /** + * Connects to the Glacier2 router using the associated SSL credentials. + * + * Once the connection is established, {@link Callback#connected} is called on the callback object; + * upon failure, {@link Callback#exception} is called with the exception. + */ + synchronized protected void + connect() + { + connectImpl(new ConnectStrategy() + { + public SessionPrx connect(RouterPrx router) + throws CannotCreateSessionException, PermissionDeniedException + { + return router.createSessionFromSecureConnection(); + } + }); + } + + /** + * Connects a Glacier2 session using user name and password credentials. + * + * Once the connection is established, {@link Callback#connected} is called on the callback object; + * upon failure {@link Callback.exception} is called with the exception. + * + * @param username The user name. + * @param password The password. + */ + synchronized protected void + connect(final String username, final String password) + { + connectImpl(new ConnectStrategy() + { + public SessionPrx connect(RouterPrx router) + throws CannotCreateSessionException, PermissionDeniedException + { + return router.createSession(username, password); + } + }); + } + + synchronized private void + connected(RouterPrx router, SessionPrx session) + { + _router = router; + + if(_destroy) + { + destroyInternal(); + return; + } + + // Assign the session after _destroy is checked. + _session = session; + _connected = true; + + assert _refreshThread == null; + _refreshThread = new SessionRefreshThread(_router, (_router.getSessionTimeout() * 1000)/2); + _refreshThread.start(); + + _shutdownHook = new Thread("Shutdown hook") + { + public void run() + { + SessionHelper.this.destroy(); + } + }; + + try + { + Runtime.getRuntime().addShutdownHook(_shutdownHook); + } + catch(IllegalStateException e) + { + // + // Shutdown in progress, ignored + // + } + catch(SecurityException ex) + { + // Ignore. Unsigned applets cannot registered shutdown + // hooks. + } + + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + try + { + _callback.connected(SessionHelper.this); + } + catch(SessionNotExistException ex) + { + SessionHelper.this.destroy(); + } + } + }); + } + + synchronized private void + destroyInternal() + { + assert _destroy; + + try + { + _router.destroySession(); + } + catch(Ice.ConnectionLostException e) + { + // Expected + } + catch(SessionNotExistException e) + { + // This can also occur. + } + catch(Throwable e) + { + // Not expected. + _communicator.getLogger().warning("SessionHelper: unexpected exception when destroying the session:\n" + e); + } + _router = null; + _connected = false; + + if(_refreshThread != null) + { + _refreshThread.done(); + while(true) + { + try + { + _refreshThread.join(); + break; + } + catch(InterruptedException e) + { + } + } + _refreshThread = null; + } + + try + { + _communicator.destroy(); + } + catch(Throwable ex) + { + } + _communicator = null; + + // Notify the callback that the session is gone. + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + _callback.disconnected(SessionHelper.this); + } + }); + } + + private void + connectImpl(final ConnectStrategy factory) + { + assert !_destroy; + + try + { + _communicator = Ice.Util.initialize(_initData); + } + catch(final Ice.LocalException ex) + { + _destroy = true; + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + _callback.connectFailed(SessionHelper.this, ex); + } + }); + return; + } + + new Thread(new Runnable() + { + public void run() + { + try + { + SwingUtilities.invokeAndWait(new Runnable() + { + public void run() + { + _callback.createdCommunicator(SessionHelper.this); + } + }); + + Glacier2.RouterPrx routerPrx = Glacier2.RouterPrxHelper.uncheckedCast( + _communicator.getDefaultRouter()); + Glacier2.SessionPrx session = factory.connect(routerPrx); + connected(routerPrx, session); + } + catch (final Exception ex) + { + try + { + _communicator.destroy(); + } + catch(Throwable ex1) + { + } + + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + _callback.connectFailed(SessionHelper.this, ex); + } + }); + } + } + }).start(); + } + + private Ice.InitializationData _initData; + private Ice.Communicator _communicator; + private Ice.ObjectAdapter _adapter; + private Glacier2.RouterPrx _router; + private Glacier2.SessionPrx _session; + + private SessionRefreshThread _refreshThread; + private SessionFactoryHelper.Callback _callback; + private boolean _destroy = false; + private boolean _connected = false; + private Thread _shutdownHook; +} diff --git a/java/src/Ice/Application.java b/java/src/Ice/Application.java index 01b42196f8c..6bf0697681c 100644 --- a/java/src/Ice/Application.java +++ b/java/src/Ice/Application.java @@ -177,6 +177,12 @@ public abstract class Application Util.setProcessLogger(new LoggerI(initData.properties.getProperty("Ice.ProgramName"), "")); } + return doMain(argHolder, initData); + } + + protected int + doMain(StringSeqHolder argHolder, Ice.InitializationData initData) + { int status = 0; try @@ -427,7 +433,7 @@ public abstract class Application } /** - * Clears any shutdownn hooks, including any hook established with {@link #destroyOnInterrupt}code> or + * Clears any shutdown hooks, including any hook established with {@link #destroyOnInterrupt}code> or * {@link #shutdownOnInterrupt}. **/ public static void @@ -524,9 +530,10 @@ public abstract class Application } } - static class AppHook extends Thread + // For use by Glacier2.Application + static public class AppHook extends Thread { - void + public void done() { synchronized(_doneMutex) @@ -642,12 +649,12 @@ public abstract class Application private Thread _hook; } - private static String _appName; - private static Communicator _communicator; - private static AppHook _appHook; - private static java.lang.Object _mutex = new java.lang.Object(); - private static boolean _callbackInProgress = false; - private static boolean _destroyed = false; - private static boolean _interrupted = false; - private static SignalPolicy _signalPolicy = SignalPolicy.HandleSignals; + protected static String _appName; + protected static Communicator _communicator; + protected static AppHook _appHook; + protected static java.lang.Object _mutex = new java.lang.Object(); + protected static boolean _callbackInProgress = false; + protected static boolean _destroyed = false; + protected static boolean _interrupted = false; + protected static SignalPolicy _signalPolicy = SignalPolicy.HandleSignals; } diff --git a/java/src/IceInternal/Util.java b/java/src/IceInternal/Util.java index a9eebf126d2..17c53bfa3e6 100644 --- a/java/src/IceInternal/Util.java +++ b/java/src/IceInternal/Util.java @@ -138,14 +138,16 @@ public final class Util loadClass(String className, ClassLoader cl) throws LinkageError { - assert(cl != null); - try - { - return cl.loadClass(className); - } - catch(ClassNotFoundException ex) + if(cl != null) { - // Ignore + try + { + return cl.loadClass(className); + } + catch(ClassNotFoundException ex) + { + // Ignore + } } return null; diff --git a/py/demo/Glacier2/callback/Client.py b/py/demo/Glacier2/callback/Client.py index b8a297f5e59..7342aa378ba 100755 --- a/py/demo/Glacier2/callback/Client.py +++ b/py/demo/Glacier2/callback/Client.py @@ -9,7 +9,6 @@ # ********************************************************************** import sys, threading, Ice, Glacier2 - Ice.loadSlice('Callback.ice') import Demo @@ -27,72 +26,35 @@ x: exit ?: help """ -class SessionRefreshThread(threading.Thread): - def __init__(self, router, timeout): - threading.Thread.__init__(self) - self._router = router - self._timeout = timeout - self._terminated = False - self._cond = threading.Condition() - - def run(self): - self._cond.acquire() - try: - while not self._terminated: - self._cond.wait(self._timeout) - if not self._terminated: - try: - self._router.refreshSession() - except Ice.LocalException, ex: - pass - finally: - self._cond.release() - - def terminate(self): - self._cond.acquire() - try: - self._terminated = True - self._cond.notify() - finally: - self._cond.release() - class CallbackReceiverI(Demo.CallbackReceiver): def callback(self, current=None): print "received callback" -class Client(Ice.Application): - def run(self, args): - if len(args) > 1: - print self.appName() + ": too many arguments" - return 1 - - defaultRouter = self.communicator().getDefaultRouter() - if not defaultRouter: - print self.appName() + ": no default router set" - return 1 +class Client(Glacier2.Application): - router = Glacier2.RouterPrx.checkedCast(defaultRouter) - if not router: - print self.appName() + ": configured router is not a Glacier2 router" - return 1 + def createSession(self): + session = None while True: print "This demo accepts any user-id / password combination." id = raw_input("user id: ") pw = raw_input("password: ") try: - router.createSession(id, pw) + session = self.router().createSession(id, pw) break except Glacier2.PermissionDeniedException, ex: print "permission denied:\n" + ex.reason + except Glacier2.CannotCreateSessionException, ex: + print "cannot create session:\n" + ex.reason + return session - refresh = SessionRefreshThread(router, router.getSessionTimeout() / 2.0) - refresh.start() + def runWithSession(self, args): + if len(args) > 1: + print self.appName() + ": too many arguments" + return 1 + + callbackReceiverIdent = self.createCallbackIdentity("callbackReceiver") - category = router.getCategoryForClient() - callbackReceiverIdent = Ice.Identity() - callbackReceiverIdent.name = "callbackReceiver" - callbackReceiverIdent.category = category callbackReceiverFakeIdent = Ice.Identity() callbackReceiverFakeIdent.name = "callbackReceiver" callbackReceiverFakeIdent.category = "fake" @@ -102,12 +64,11 @@ class Client(Ice.Application): oneway = Demo.CallbackPrx.uncheckedCast(twoway.ice_oneway()) batchOneway = Demo.CallbackPrx.uncheckedCast(twoway.ice_batchOneway()) - adapter = self.communicator().createObjectAdapterWithRouter("Callback.Client", defaultRouter) - adapter.add(CallbackReceiverI(), callbackReceiverIdent) - adapter.add(CallbackReceiverI(), callbackReceiverFakeIdent) - adapter.activate() - twowayR = Demo.CallbackReceiverPrx.uncheckedCast(adapter.createProxy(callbackReceiverIdent)) + self.objectAdapter().add(CallbackReceiverI(), callbackReceiverIdent) + self.objectAdapter().add(CallbackReceiverI(), callbackReceiverFakeIdent) + + twowayR = Demo.CallbackReceiverPrx.uncheckedCast(self.objectAdapter().createProxy(callbackReceiverIdent)) onewayR = Demo.CallbackReceiverPrx.uncheckedCast(twowayR.ice_oneway()) override = '' @@ -169,24 +130,6 @@ class Client(Ice.Application): except EOFError: break - # - # The refresher thread must be terminated before destroy is - # called, otherwise it might get ObjectNotExistException. refresh - # is set to 0 so that if session->destroy() raises an exception - # the thread will not be re-terminated and re-joined. - # - refresh.terminate() - refresh.join() - refresh = None - - try: - router.destroySession() - except Glacier2.SessionNotExistException, ex: - print ex - except Ice.ConnectionLostException: - # Expected: the router closed the connection. - pass - return 0 app = Client() diff --git a/py/demo/Glacier2/callback/expect.py b/py/demo/Glacier2/callback/expect.py index fa2a2c64f20..3daaf09e1e3 100755 --- a/py/demo/Glacier2/callback/expect.py +++ b/py/demo/Glacier2/callback/expect.py @@ -24,8 +24,6 @@ from demoscript.Glacier2 import callback server = Util.spawn('Server.py --Ice.PrintAdapterReady') server.expect('.* ready') -sessionserver = Util.spawn('SessionServer.py --Ice.PrintAdapterReady') -sessionserver.expect('.* ready') glacier2 = Util.spawn('glacier2router --Ice.Config=config.glacier2 --Ice.PrintAdapterReady --Glacier2.SessionTimeout=5') glacier2.expect('Glacier2.Client ready') @@ -33,4 +31,4 @@ glacier2.expect('Glacier2.Server ready') client = Util.spawn('Client.py') -callback.run(client, server, sessionserver, glacier2) +callback.run(client, server, glacier2) diff --git a/py/python/Glacier2.py b/py/python/Glacier2.py new file mode 100644 index 00000000000..61f1294f248 --- /dev/null +++ b/py/python/Glacier2.py @@ -0,0 +1,265 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +""" +Glacier2 module +""" + +import sys, exceptions, string, imp, os, threading, warnings, datetime, traceback, copy + +# +# Import the Python extension. +# +import IcePy +import Ice + +import Glacier2_RouterF_ice +import Glacier2_Router_ice +import Glacier2_Session_ice +import Glacier2_PermissionsVerifierF_ice +import Glacier2_PermissionsVerifier_ice +import Glacier2_SSLInfo_ice + +class SessionNotExistException(Exception): + def __init__(self): + pass + +class RestartSessionException(Exception): + def __init__(self): + pass + +class AMI_Router_refreshSessionI: + + def __init__(self, app, pinger): + self._app = app + self._pinger = pinger + + def ice_response(self): + pass + + def ice_exception(self, ex): + # Here the session has gone. The thread + # terminates, and we notify the + # application that the session has been + # destroyed. + self._pinger.done() + self._app.sessionDestroyed() + + +class SessionPingThread(threading.Thread): + def __init__(self, app, router, timeout): + threading.Thread.__init__(self) + self._router = router + self._app = app + self._timeout = timeout + self._terminated = False + self._cond = threading.Condition() + + def run(self): + self._cond.acquire() + try: + while not self._terminated: + self._cond.wait(self._timeout) + if not self._terminated: + self._router.refreshSession_async(AMI_Router_refreshSessionI(self._app, self)) + finally: + self._cond.release() + + def done(self): + self._cond.acquire() + try: + self._terminated = True + self._cond.notify() + finally: + self._cond.release() + +class Application(Ice.Application): + + def __init__(self, signalPolicy=0): # HandleSignals=0 + '''The constructor accepts an optional argument indicating +whether to handle signals. The value should be either +Application.HandleSignals (the default) or +Application.NoSignalHandling. +''' + self._router = None + self._session = None + self._adapter = None + self._createdSession = False + + if type(self) == Application: + raise RuntimeError("Glacier2.Application is an abstract class") + Ice.Application.__init__(self, signalPolicy) + + def run(self, args): + raise RuntimeError('run should not be called on Galcier2.Application instead runWithSession should be used') + + def runWithSession(self, args): + raise RuntimeError('runWithSession() not implemented') + + def createSession(self, args): + raise RuntimeError('createSession() not implemented') + + def restart(self): + raise RestartException() + + def sessionDestroyed(self): + pass + + def router(self): + return self._router + + def session(self): + return self._session + + def categoryForClient(self): + if self._router == None: + raise SessionNotExistException() + return self._router.getCategoryForClient() + + def createCallbackIdentity(self, name): + return Ice.Identity(name, self.categoryForClient()) + + def addWithUUID(self, servant): + return objectAdapter().add(servant, createCallbackIdentity(Ice.generateUUID())) + + def objectAdapter(self): + if self._adapter == None: + # TODO: Depending on the resolution of + # http://bugzilla/bugzilla/show_bug.cgi?id=4264 the OA + # name could be an empty string. + self._adapter = self.communicator().createObjectAdapterWithRouter(Ice.generateUUID(), self.router()) + self._adapter.activate(); + return self._adapter + + def doMainInternal(self, args, initData, status): + # Reset internal state variables from Ice.Application. The + # remainder are reset at the end of this method. + Ice.Application._callbackInProgress = False + Ice.Application._destroyed = False + Ice.Application._interrupted = False + + restart = False + status = 0 + + ping = None + try: + Ice.Application._communicator = Ice.initialize(args, initData); + self._router = RouterPrx.uncheckedCast(Ice.Application.communicator().getDefaultRouter()) + + if self._router == None: + Ice.getProcessLogger().error("no glacier2 router configured"); + status = 1; + else: + # + # The default is to destroy when a signal is received. + # + if Ice.Application._signalPolicy == Ice.Application.HandleSignals: + Ice.Application.destroyOnInterrupt() + + # If createSession throws, we're done. + try: + self._session = self.createSession() + self._createdSession = True + except Ice.LocalException as (ex): + Ice.getProcessLogger().error(traceback.format_exc()) + status = 1; + + if self._createdSession: + ping = SessionPingThread(self, self._router, self._router.getSessionTimeout() / 2) + ping.start(); + status = self.runWithSession(args) + + # We want to restart on those exceptions which indicate a + # break down in communications, but not those exceptions that + # indicate a programming logic error (ie: marshal, protocol + # failure, etc). + except(RestartSessionException, Ice.ConnectionLostException, Ice.ConnectionLostException, \ + Ice.UnknownLocalException, Ice.RequestFailedException, Ice.TimeoutException) as (ex): + Ice.getProcessLogger().error(traceback.format_exc()) + except: + Ice.getProcessLogger().error(traceback.format_exc()) + status = 1 + + + if self._createdSession and self._router != None: + try: + self._router.destroySession(); + except (Ice.ConnectionLostException, SessionNotExistException): + pass + except: + Ice.getProcessLogger().error(traceback.format_exc()) + + # + # Don't want any new interrupt and at this point (post-run), + # it would not make sense to release a held signal to run + # shutdown or destroy. + # + if Application._signalPolicy == Application.HandleSignals: + Application.ignoreInterrupt() + + Application._condVar.acquire() + while Application._callbackInProgress: + Application._condVar.wait() + if Application._destroyed: + Application._communicator = None + else: + Application._destroyed = True + # + # And _communicator != 0, meaning will be destroyed + # next, _destroyed = true also ensures that any + # remaining callback won't do anything + # + Application._application = None + Application._condVar.release() + + if Application._communicator: + try: + Application._communicator.destroy() + except: + getProcessLogger().error(traceback.format_exc()) + status = 1 + + Application._communicator = None + + # + # Set _ctrlCHandler to 0 only once communicator.destroy() has + # completed. + # + Application._ctrlCHandler.destroy() + Application._ctrlCHandler = None + + if ping != None: + ping.done() + + # Reset internal state. We cannot reset the Application state + # here, since _destroyed must remain true until we re-run + # this method. + self._adapter = None + self._router = None + self._session = None + self._createdSession = False + + return restart + + def doMain(self, args, initData): + initData.properties.setProperty("Ice.ACM.Client", "0"); + initData.properties.setProperty("Ice.RetryIntervals", "-1"); + + restart = True; + ret = 0; + while restart: + # A copy of the initialization data and the string seq + # needs to be passed to doMainInternal, as these can be + # changed by the application. + id = copy.copy(initData) + if id.properties != None: + id.properties = id.properties.clone() + argsCopy = args[:] + restart = self.doMainInternal(argsCopy, initData, ret) + return ret; diff --git a/py/python/Ice.py b/py/python/Ice.py index 500aeb2ae5b..7af0b3de01e 100644 --- a/py/python/Ice.py +++ b/py/python/Ice.py @@ -898,7 +898,7 @@ value is an integer representing the exit status. if Application._signalPolicy == Application.HandleSignals: Application.destroyOnInterrupt() - status = self.run(args) + status = self.doMain(args, initData) except: getProcessLogger().error(traceback.format_exc()) status = 1 @@ -944,6 +944,9 @@ value is an integer representing the exit status. return status + def doMain(self, args, initData): + self.run(args) + def run(self, args): '''This method must be overridden in a subclass. The base class supplies an argument list from which all Ice arguments diff --git a/py/python/Makefile b/py/python/Makefile index 3b713e741e8..15050be830a 100644 --- a/py/python/Makefile +++ b/py/python/Makefile @@ -93,7 +93,7 @@ Ice_%_ice.py: $(slicedir)/Ice/%.ice $(SLICE2PY) --prefix Ice_ --ice --no-package $(SLICE2PYFLAGS) $< Glacier2_%_ice.py: $(slicedir)/Glacier2/%.ice - $(SLICE2PY) --prefix Glacier2_ --checksum $(SLICE2PYFLAGS) $< + $(SLICE2PY) --prefix Glacier2_ --no-package --checksum $(SLICE2PYFLAGS) $< IceBox_%_ice.py: $(slicedir)/IceBox/%.ice $(SLICE2PY) --prefix IceBox_ --ice --checksum $(SLICE2PYFLAGS) $< diff --git a/py/python/Makefile.mak b/py/python/Makefile.mak index 3b892e5f0e4..27241004e12 100644 --- a/py/python/Makefile.mak +++ b/py/python/Makefile.mak @@ -192,22 +192,22 @@ Ice_EndpointTypes_ice.py: $(slicedir)/Ice/EndpointTypes.ice Glacier2_RouterF_ice.py: $(slicedir)/Glacier2/RouterF.ice
- $(SLICE2PY) $(SLICE2PYFLAGS) --prefix Glacier2_ $(slicedir)/Glacier2/RouterF.ice
+ $(SLICE2PY) $(SLICE2PYFLAGS) --prefix Glacier2_ --no-package $(slicedir)/Glacier2/RouterF.ice
Glacier2_Router_ice.py: $(slicedir)/Glacier2/Router.ice
- $(SLICE2PY) $(SLICE2PYFLAGS) --prefix Glacier2_ $(slicedir)/Glacier2/Router.ice
+ $(SLICE2PY) $(SLICE2PYFLAGS) --prefix Glacier2_ --no-package $(slicedir)/Glacier2/Router.ice
Glacier2_Session_ice.py: $(slicedir)/Glacier2/Session.ice
- $(SLICE2PY) $(SLICE2PYFLAGS) --prefix Glacier2_ $(slicedir)/Glacier2/Session.ice
+ $(SLICE2PY) $(SLICE2PYFLAGS) --prefix Glacier2_ --no-package $(slicedir)/Glacier2/Session.ice
Glacier2_PermissionsVerifierF_ice.py: $(slicedir)/Glacier2/PermissionsVerifierF.ice
- $(SLICE2PY) $(SLICE2PYFLAGS) --prefix Glacier2_ $(slicedir)/Glacier2/PermissionsVerifierF.ice
+ $(SLICE2PY) $(SLICE2PYFLAGS) --prefix Glacier2_ --no-package $(slicedir)/Glacier2/PermissionsVerifierF.ice
Glacier2_PermissionsVerifier_ice.py: $(slicedir)/Glacier2/PermissionsVerifier.ice
- $(SLICE2PY) $(SLICE2PYFLAGS) --prefix Glacier2_ $(slicedir)/Glacier2/PermissionsVerifier.ice
+ $(SLICE2PY) $(SLICE2PYFLAGS) --prefix Glacier2_ --no-package $(slicedir)/Glacier2/PermissionsVerifier.ice
Glacier2_SSLInfo_ice.py: $(slicedir)/Glacier2/SSLInfo.ice
- $(SLICE2PY) $(SLICE2PYFLAGS) --prefix Glacier2_ $(slicedir)/Glacier2/SSLInfo.ice
+ $(SLICE2PY) $(SLICE2PYFLAGS) --prefix Glacier2_ --no-package $(slicedir)/Glacier2/SSLInfo.ice
IceBox_IceBox_ice.py: $(slicedir)/IceBox/IceBox.ice
diff --git a/slice/Glacier2/Router.ice b/slice/Glacier2/Router.ice index d8793e2b570..35dd8a3c2c1 100644 --- a/slice/Glacier2/Router.ice +++ b/slice/Glacier2/Router.ice @@ -154,7 +154,7 @@ interface Router extends Ice::Router * for the calling client. * **/ - void refreshSession() + ["ami"] void refreshSession() throws SessionNotExistException; /** |