summaryrefslogtreecommitdiff
path: root/java
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 /java
parentUpdated demo README (diff)
downloadice-1d9f29e281770ecdad4a245271f2b828bd64a32f.tar.bz2
ice-1d9f29e281770ecdad4a245271f2b828bd64a32f.tar.xz
ice-1d9f29e281770ecdad4a245271f2b828bd64a32f.zip
3772. Recovering from Glacier2 / Ice router session failure.
Diffstat (limited to 'java')
-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
24 files changed, 2960 insertions, 211 deletions
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;