package de.mpicbg.knime.scripting.python.srv; import gnu.cajo.invoke.Remote; import gnu.cajo.utils.ItemServer; import java.io.*; import java.util.Arrays; import java.util.Hashtable; /** * A server implementation that exposes the Python-interface for remote clients. * * @author Holger Brandl */ public class PythonServer implements Python { private ServerFileMap map = new ServerFileMap(); public PythonServer(int port) { try { System.out.println("Configuring on port: " + port); Remote.config(null, port, null, 0); System.out.println("Registering with name: " + REGISTRY_NAME); ItemServer.bind(this, REGISTRY_NAME); System.out.println("Python server started..."); } catch (IOException e) { e.printStackTrace(); } } // Construct a server for local use only--does not initialize the client/server framework protected PythonServer(boolean local) { } public File createTempFile(String prefix, String suffix) { File tempFile = null; try { tempFile = File.createTempFile(prefix, suffix); tempFile.deleteOnExit(); } catch (IOException e) { } return tempFile; } public String getFilePath(File file) { return file.getAbsolutePath(); } public boolean deleteFile(File file) { return file != null ? file.delete() : true; } public CommandOutput executeCommand(String[] command) { try { return exec(command); } catch (Throwable t) { throw new RuntimeException(t); } } /** * Run an external command and return any output it generates. * * @param cmd * @return * @throws InterruptedException */ private CommandOutput exec(String[] cmd) throws Exception { Process proc = null; proc = Runtime.getRuntime().exec(cmd); // Create threads to capture output on standard/error streams assert proc != null; StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream()); StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream()); // Kick them off errorGobbler.start(); outputGobbler.start(); // Wait for the command process to complete proc.waitFor(); return new CommandOutput(outputGobbler, errorGobbler); } public int openFile(File file) throws IOException { return map.add(file); } ; public byte[] readFile(int descriptor) throws IOException { ServerFile file = map.get(descriptor); return file.read(); } ; public void writeFile(int descriptor, byte[] bytes) throws IOException { ServerFile file = map.get(descriptor); file.write(bytes); } ; public void closeFile(int descriptor) throws IOException { ServerFile file = map.get(descriptor); file.close(); map.remove(descriptor); } ; public static void main(String[] args) { if (args.length == 0) new PythonServer(DEFAULT_PORT); else { int port = Integer.parseInt(args[0]); new PythonServer(port); } } /** * Maintain a map of descriptors to ServerFile references. */ class ServerFileMap { private int currentDescriptor = 0; private Hashtable<String, ServerFile> map = new Hashtable<String, ServerFile>(); public ServerFile get(int descriptor) { return map.get(Integer.toString(descriptor)); } public int add(File file) { return add(new ServerFile(file)); } public int add(ServerFile file) { String descriptor = Integer.toString(currentDescriptor); map.put(descriptor, file); return currentDescriptor++; } public void remove(int descriptor) { map.remove(Integer.toString(descriptor)); } } /** * Basic open, read, write, close access for a file */ class ServerFile { // Only one of these will be created private InputStream input; private OutputStream output; // Buffer used for read operations private byte[] buffer = new byte[8192]; private File file; public ServerFile(File file) { this.file = file; } public byte[] read() throws IOException { // Create the stream if this is the first file operation if (input == null) input = new BufferedInputStream(new FileInputStream(file)); int n = input.read(buffer); byte[] b = buffer; if (n == -1) b = new byte[0]; else if (n < buffer.length) b = Arrays.copyOf(buffer, n); return b; } public void write(byte[] bytes) throws IOException { // Create the stream if this is the first file operation if (output == null) output = new BufferedOutputStream(new FileOutputStream(file)); output.write(bytes); } public void close() throws IOException { // Close whichever stream was created if (input != null) input.close(); if (output != null) output.close(); } } }