/*
VisAD system for interactive analysis and visualization of numerical
data. Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/
package visad.util;
import java.lang.reflect.InvocationTargetException;
import java.rmi.ConnectException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import visad.DataReference;
import visad.DisplayImpl;
import visad.LocalDisplay;
import visad.RemoteDisplay;
import visad.RemoteServer;
import visad.RemoteServerImpl;
import visad.VisADException;
public class ClientServer
{
private static final int maximumWaitTime = 60;
public static RemoteServer connectToServer(String hostName,
String serviceName)
throws RemoteException, VisADException
{
return connectToServer(hostName, serviceName, false);
}
public static RemoteServer connectToServer(String hostName,
String serviceName,
boolean verbose)
throws RemoteException, VisADException
{
RemoteServer client = null;
String domain = "//" + hostName + "/" + serviceName;
int loops = 0;
while (client == null && loops < maximumWaitTime) {
// try to reconnect to the server after the first loop
if (loops > 0) {
try {
client = (RemoteServer )Naming.lookup(domain);
} catch (NotBoundException nbe) {
client = null;
} catch (ConnectException ce) {
client = null;
} catch (Exception e) {
throw new VisADException ("Cannot connect to server on \"" +
hostName + "\" (" +
e.getClass().getName() + ": " +
e.getMessage() + ")");
}
}
// try to get first display from remote server
RemoteDisplay rmtDpy;
try {
if (client != null) {
rmtDpy = client.getDisplay(0);
}
} catch (java.rmi.ConnectException ce) {
client = null;
}
// if we didn't get the display, print a message and wait a bit
if (client == null) {
if (verbose) {
if (loops == 0) {
System.err.print("Client waiting for server ");
} else {
System.err.print(".");
}
}
try { Thread.sleep(1000); } catch (InterruptedException ie) { }
loops++;
}
}
if (loops == maximumWaitTime) {
if (verbose) {
System.err.println(" giving up!");
}
throw new VisADException("Cannot connect to " + hostName +
":" + serviceName);
} else if (loops > 0) {
if (verbose) {
System.err.println(" connected");
}
}
return client;
}
private static LocalDisplay wrapRemoteDisplay(RemoteDisplay rmtDpy)
throws RemoteException, VisADException
{
String className = rmtDpy.getDisplayClassName();
Class dpyClass;
try {
dpyClass = Class.forName(className);
} catch (ClassNotFoundException e) {
throw new VisADException("Couldn't create " + className);
}
java.lang.reflect.Constructor cons;
try {
cons = dpyClass.getConstructor(new Class[] { RemoteDisplay.class });
} catch (NoSuchMethodException e) {
throw new VisADException(className + " has no RemoteDisplay" +
" constructor");
}
DisplayImpl dpy;
Object[] cargs = new Object[1];
cargs[0] = rmtDpy;
try {
dpy = (DisplayImpl )cons.newInstance(cargs);
} catch (InvocationTargetException ite) {
Throwable t = ite.getTargetException();
if (t instanceof VisADException) {
throw (VisADException )t;
} else if (t instanceof ConnectException) {
throw new VisADException("Couldn't create local shadow for " +
rmtDpy + ": Connection refused");
} else {
throw new VisADException("Couldn't create local shadow for " +
rmtDpy + ": " + t.getClass().getName() +
": " + t.getMessage());
}
} catch (Exception e) {
throw new VisADException("Couldn't create local shadow for " +
rmtDpy + ": " + e.getClass().getName() +
": " + e.getMessage());
}
return dpy;
}
public static LocalDisplay getClientDisplay(RemoteServer client, int index)
throws RemoteException, VisADException
{
return getClientDisplay(client, index, null);
}
public static LocalDisplay getClientDisplay(RemoteServer client, int index,
DataReference[] refs)
throws RemoteException, VisADException
{
// fail if there's no remote server
if (client == null) {
return null;
}
RemoteDisplay rmtDpy = null;
int loops = 0;
while (rmtDpy == null && loops < maximumWaitTime) {
try {
rmtDpy = client.getDisplay(index);
} catch (java.rmi.ConnectException ce) {
ce.printStackTrace();
}
// if we didn't get the display, print a message and wait a bit
if (rmtDpy == null) {
if (loops == 0) {
System.err.print("Client waiting for server display #" + index +
" ");
} else {
System.err.print(".");
}
try { Thread.sleep(1000); } catch (InterruptedException ie) { }
loops++;
}
}
if (rmtDpy == null && loops == maximumWaitTime) {
System.err.println(" giving up!");
System.exit(1);
} else if (loops > 0) {
System.err.println(". ready");
}
if (rmtDpy == null) {
return null;
}
LocalDisplay dpy = wrapRemoteDisplay(rmtDpy);
if (dpy != null && refs != null) {
dpy.replaceReferences(rmtDpy, null, refs, null);
}
return dpy;
}
public static LocalDisplay[] getClientDisplays(RemoteServer client)
throws RemoteException, VisADException
{
return getClientDisplays(client, null);
}
public static LocalDisplay[] getClientDisplays(RemoteServer client,
DataReference[] refs)
throws RemoteException, VisADException
{
// fail if there's no remote server
if (client == null) {
return null;
}
RemoteDisplay[] rmtDpys = null;
int loops = 0;
while (rmtDpys == null && loops < maximumWaitTime) {
try {
rmtDpys = client.getDisplays();
} catch (java.rmi.ConnectException ce) {
}
// if we didn't get the display, print a message and wait a bit
if (rmtDpys == null) {
if (loops == 0) {
System.err.print("Client waiting for server displays ");
} else {
System.err.print(".");
}
try { Thread.sleep(1000); } catch (InterruptedException ie) { }
loops++;
}
}
if (rmtDpys == null && loops == maximumWaitTime) {
System.err.println(" giving up!");
System.exit(1);
} else if (loops > 0) {
System.err.println(". ready");
}
if (rmtDpys == null) {
return null;
}
LocalDisplay[] dpys = new LocalDisplay[rmtDpys.length];
for (int i = 0; i < dpys.length; i++) {
dpys[i] = wrapRemoteDisplay(rmtDpys[i]);
if (dpys[i] != null && refs != null) {
dpys[i].replaceReferences(rmtDpys[i], null, refs, null);
}
}
return dpys;
}
public static RemoteServerImpl startServer(String serviceName)
throws RemoteException, VisADException
{
// create new server
RemoteServerImpl server;
boolean registryStarted = false;
while (true) {
boolean success = true;
try {
server = new RemoteServerImpl();
String domain = "///" + serviceName;
Naming.rebind(domain, server);
break;
} catch (java.rmi.ConnectException ce) {
if (!registryStarted) {
LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
registryStarted = true;
} else {
success = false;
}
} catch (Exception e) {
success = false;
}
if (!success) {
throw new VisADException("Cannot set up server" +
" (rmiregistry may not be running)");
}
}
return server;
}
}