/* Copyright (c) 1997-2004
Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
http://www.math.tu-berlin.de/polymake, mailto:polymake@math.tu-berlin.de
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version: http://www.gnu.org/licenses/gpl.txt.
This program 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 General Public License for more details.
$Project: polymake $$Id: Launcher.java 7531 2006-12-20 16:59:58Z thilosch $
*/
package de.tuberlin.polymake.common;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.Channels;
import java.nio.channels.Pipe;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Vector;
/**
* Launcher for an interactive polymake viewers based on Javaview.
* The calculations are made in a C++ client, which gets and returns
* the data using sockets.
*
* @author Thilo Schröder
* @version 1.0
*/
public class Launcher{
/** usage message of the Launcher */
protected final static String USAGE = "usage: java de.tuberlin.polymake.common.Launcher ControlClass [-client_port <port>] ControlClass [-client_port <port>] ... -ps_port <port>";
/** charset used for communication */
public final static String CHARSET = "ISO-8859-1";
/**
* Creates a new Launcher and if given establishes the connection
* of the control classes to the corresponding c++ clients via
* sockets. It also starts a selector thread which manages the
* communication between polymake's clients/server and the java
* controls.
*
* @param classes control classes for different polymake visualizations which are launched
* @param ports portnumbers of sockets to c++ clients of polymake
* @param polymakeserverPort portnumber of polymake server
* @exception IOException if an error occurs when opening the communication channels
* @exception ClassNotFoundException if a given control class does not exist
* @exception NoSuchMethodException if a method of a control class cannot be found
* @exception InstantiationException if a instance of a control class cannot be created
* @exception Exception if another error occurs
*/
public Launcher(Vector classes, Vector ports,int polymakeserverPort)
throws IOException, ClassNotFoundException, NoSuchMethodException, InstantiationException,Exception {
if(classes.size() != ports.size()) {
System.err.println("classes.size != ports.size");
System.exit(0);
}
InetAddress[] localhostAddresses = InetAddress.getAllByName("localhost");
SocketChannel polymakeserverChannel = SocketChannel.open();
InetSocketAddress psa=null;
for(int i=0; i < localhostAddresses.length ; ++i) {
try {
psa = new InetSocketAddress(localhostAddresses[i],polymakeserverPort);
if(polymakeserverChannel.connect(psa)) {
if(System.getProperty("polymake.debug") != null) {
System.err.println("de.tuberlin.polymake.common.Launcher: Connection to " +
localhostAddresses[i].toString() +":"+polymakeserverPort+" successful.");
}
break;
}
} catch(IOException ex) {
if(i <= localhostAddresses.length - 1) {
if(System.getProperty("polymake.debug") != null) {
System.err.println("de.tuberlin.polymake.common.Launcher: Connection to " +
localhostAddresses[i].toString() +":"+polymakeserverPort+" refused.");
}
polymakeserverChannel = SocketChannel.open();
continue;
} else {
throw new IOException("Connection to polymake server at localhost could not be established.");
}
}
}
polymakeserverChannel.configureBlocking(false);
BufferedReader psReader = new BufferedReader(Channels.newReader(polymakeserverChannel,CHARSET));
SelectorThread selectorThread = new SelectorThread(polymakeserverChannel,CHARSET);
Iterator ci = classes.iterator();
Iterator pi = ports.iterator();
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
//Class embeddedGeometriesClass = classLoader.loadClass("de.tuberlin.polymake.common.EmbeddedGeometries");
//Class socketChannelClass = classLoader.loadClass("java.nio.channels.SocketChannel");
Class bufferedReaderClass = classLoader.loadClass("java.io.BufferedReader");
Class pipeSinkChannelClass = classLoader.loadClass("java.nio.channels.Pipe$SinkChannel");
SocketChannel clientChannel = null;
PolymakeControl staticGeometryControl = null;
while(ci.hasNext()) {
Class controlClass = (Class)ci.next();
int clientPort = ((Integer)pi.next()).intValue();
Constructor constructor = controlClass.getConstructor(
new Class[] {bufferedReaderClass, bufferedReaderClass, pipeSinkChannelClass});
if(clientPort != -1) {
Pipe controlPipe = Pipe.open();
controlPipe.source().configureBlocking(false);
InetSocketAddress csa = new InetSocketAddress(psa.getAddress(),clientPort);
clientChannel = SocketChannel.open();
clientChannel.connect(csa);
clientChannel.configureBlocking(false);
PolymakeControl pControl = (PolymakeControl)constructor.newInstance(
new Object[] {psReader,new BufferedReader(Channels.newReader(clientChannel,CHARSET)),controlPipe.sink()});
selectorThread.registerControl(pControl,clientChannel,controlPipe);
} else {
if(staticGeometryControl == null) {
Pipe controlPipe = Pipe.open();
controlPipe.source().configureBlocking(false);
staticGeometryControl = (PolymakeControl)constructor.newInstance(
new Object[] {psReader,psReader,controlPipe.sink()});
selectorThread.registerControl(staticGeometryControl,controlPipe);
} else {
staticGeometryControl.update();
}
}
}
selectorThread.start();
}
/**
* main() method creating a new Launcher.
* @param args[] a <code>String</code> value containing the
* control classes to be launched and corresponding port numbers
* if needed
*/
public static void main(String args[]) {
try {
Vector classes = new Vector();
Vector ports = new Vector();
int ps_port = -1;
int i = 0;
while(i < args.length) {
if(args[i].equals("-ps_port")) {
ps_port = Integer.parseInt(args[i+1]);
i += 2;
break;
}
String className = args[i];
classes.add(Class.forName(className));
if(i < args.length - 2 && args[i+1].equals("-client_port")) {
ports.add(new Integer(args[i+2]));
i += 3;
} else {
ports.add(new Integer(-1));
i += 1;
}
}
if(i != args.length || ps_port == -1) {
System.err.println(USAGE);
System.exit(0);
}
new Launcher(classes,ports,ps_port);
} catch(ClassNotFoundException e) {
System.err.println(USAGE + "\n"+e.getMessage()+ " not found.");
System.exit(0);
} catch(NumberFormatException e) {
System.err.println(USAGE);
System.exit(0);
} catch (Exception e) {
System.err.println("Launcher: error initializing channels.");
e.printStackTrace(System.err);
System.exit(0);
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1