summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJose <jose@zeroc.com>2009-10-02 02:23:52 +0200
committerJose <jose@zeroc.com>2009-10-02 02:23:52 +0200
commit1d9f29e281770ecdad4a245271f2b828bd64a32f (patch)
treeac083f28b06a444e484c24f8fcf1b12a36202c84
parentUpdated demo README (diff)
downloadice-1d9f29e281770ecdad4a245271f2b828bd64a32f.tar.bz2
ice-1d9f29e281770ecdad4a245271f2b828bd64a32f.tar.xz
ice-1d9f29e281770ecdad4a245271f2b828bd64a32f.zip
3772. Recovering from Glacier2 / Ice router session failure.
-rw-r--r--cpp/demo/Glacier2/callback/Client.cpp118
-rwxr-xr-xcpp/demo/Glacier2/callback/expect.py4
-rw-r--r--cpp/include/Glacier2/Application.h222
-rw-r--r--cpp/include/Ice/Application.h36
-rw-r--r--cpp/src/Glacier2/Application.cpp426
-rw-r--r--cpp/src/Glacier2/Makefile3
-rw-r--r--cpp/src/Glacier2/Makefile.mak5
-rw-r--r--cpp/src/Ice/Application.cpp194
-rw-r--r--cs/demo/Glacier2/callback/Client.cs145
-rw-r--r--cs/demo/Glacier2/callback/Glacier2.callback.client.csproj4
-rwxr-xr-xcs/demo/Glacier2/callback/expect.py4
-rwxr-xr-xcs/demo/Glacier2/chat/App.xaml21
-rwxr-xr-xcs/demo/Glacier2/chat/App.xaml.cs25
-rwxr-xr-xcs/demo/Glacier2/chat/CancelDialog.xaml27
-rwxr-xr-xcs/demo/Glacier2/chat/CancelDialog.xaml.cs49
-rwxr-xr-xcs/demo/Glacier2/chat/Chat.ice31
-rwxr-xr-xcs/demo/Glacier2/chat/ChatCommands.cs58
-rwxr-xr-xcs/demo/Glacier2/chat/ChatWindow.xaml68
-rwxr-xr-xcs/demo/Glacier2/chat/ChatWindow.xaml.cs321
-rwxr-xr-xcs/demo/Glacier2/chat/Glacier2.chat.client.csproj148
-rwxr-xr-xcs/demo/Glacier2/chat/LoginDialog.xaml41
-rwxr-xr-xcs/demo/Glacier2/chat/LoginDialog.xaml.cs63
-rwxr-xr-xcs/demo/Glacier2/chat/Properties/AssemblyInfo.cs55
-rwxr-xr-xcs/demo/Glacier2/chat/Properties/Resources.Designer.cs71
-rwxr-xr-xcs/demo/Glacier2/chat/Properties/Resources.resx117
-rwxr-xr-xcs/demo/Glacier2/chat/Properties/Settings.Designer.cs30
-rwxr-xr-xcs/demo/Glacier2/chat/Properties/Settings.settings7
-rwxr-xr-xcs/demo/Glacier2/chat/config.client39
-rw-r--r--cs/demo/Ice/wpf/App.xaml18
-rw-r--r--cs/demo/Ice/wpf/App.xaml.cs25
-rw-r--r--cs/demo/Ice/wpf/Hello.ice24
-rw-r--r--cs/demo/Ice/wpf/HelloWindow.xaml91
-rw-r--r--cs/demo/Ice/wpf/HelloWindow.xaml.cs358
-rw-r--r--cs/demo/Ice/wpf/Ice.wpf.client.csproj154
-rwxr-xr-xcs/demo/Ice/wpf/Properties/AssemblyInfo.cs55
-rwxr-xr-xcs/demo/Ice/wpf/Properties/Resources.Designer.cs71
-rwxr-xr-xcs/demo/Ice/wpf/Properties/Resources.resx117
-rwxr-xr-xcs/demo/Ice/wpf/Properties/Settings.Designer.cs30
-rwxr-xr-xcs/demo/Ice/wpf/Properties/Settings.settings7
-rw-r--r--cs/demo/Ice/wpf/config.client45
-rwxr-xr-xcs/demo/demo.sln12
-rw-r--r--cs/src/Glacier2/Application.cs508
-rw-r--r--cs/src/Glacier2/Makefile3
-rw-r--r--cs/src/Glacier2/Makefile.mak7
-rw-r--r--cs/src/Glacier2/SessionFactoryHelper.cs360
-rw-r--r--cs/src/Glacier2/SessionHelper.cs485
-rw-r--r--cs/src/Ice/Application.cs198
-rwxr-xr-xdemoscript/Glacier2/callback.py23
-rw-r--r--java/config/common.xml2
-rw-r--r--java/demo/Glacier2/build.xml2
-rw-r--r--java/demo/Glacier2/callback/Client.java248
-rw-r--r--java/demo/Glacier2/callback/README13
-rw-r--r--java/demo/Glacier2/callback/config.client19
-rwxr-xr-xjava/demo/Glacier2/callback/expect.py4
-rw-r--r--java/demo/Glacier2/chat/Chat.ice31
-rw-r--r--java/demo/Glacier2/chat/Client.java544
-rw-r--r--java/demo/Glacier2/chat/README1
-rw-r--r--java/demo/Glacier2/chat/build.xml47
-rw-r--r--java/demo/Glacier2/chat/config.client39
-rw-r--r--java/demo/Ice/README5
-rw-r--r--java/demo/Ice/build.xml2
-rw-r--r--java/demo/Ice/swing/.gitignore1
-rw-r--r--java/demo/Ice/swing/Client.java659
-rw-r--r--java/demo/Ice/swing/Hello.ice24
-rw-r--r--java/demo/Ice/swing/README12
-rw-r--r--java/demo/Ice/swing/build.xml44
-rw-r--r--java/demo/Ice/swing/config.client26
-rw-r--r--java/src/Glacier2/Application.java552
-rw-r--r--java/src/Glacier2/SessionFactoryHelper.java355
-rw-r--r--java/src/Glacier2/SessionHelper.java496
-rw-r--r--java/src/Ice/Application.java29
-rw-r--r--java/src/IceInternal/Util.java16
-rwxr-xr-xpy/demo/Glacier2/callback/Client.py91
-rwxr-xr-xpy/demo/Glacier2/callback/expect.py4
-rw-r--r--py/python/Glacier2.py265
-rw-r--r--py/python/Ice.py5
-rw-r--r--py/python/Makefile2
-rw-r--r--py/python/Makefile.mak12
-rw-r--r--slice/Glacier2/Router.ice2
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;
/**