[Remoterengine-commits] r99 - in pkg/RemoteREngine/inst/java_src/src/client: . org org/rosuda org/rosuda/REngine org/rosuda/REngine/remote org/rosuda/REngine/remote/client org/rosuda/REngine/remote/client/callbacks org/rosuda/REngine/remote/client/test

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Mon Sep 7 13:49:31 CEST 2009


Author: romain
Date: 2009-09-07 13:49:30 +0200 (Mon, 07 Sep 2009)
New Revision: 99

Added:
   pkg/RemoteREngine/inst/java_src/src/client/org/
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/RemoteExceptionManager.java
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/RemoteREngine.java
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/callbacks/
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/callbacks/ClientCallbackDispatcher.java
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/AllTests.java
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/DataFrames_Test.java
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/Doubles_Test.java
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/Lists_Test.java
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/RemoteREngineTest.java
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/S3Objects_Test.java
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/Strings_Test.java
   pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/TestEnvironment.java
Log:
restored client code

Added: pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/RemoteExceptionManager.java
===================================================================
--- pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/RemoteExceptionManager.java	                        (rev 0)
+++ pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/RemoteExceptionManager.java	2009-09-07 11:49:30 UTC (rev 99)
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2009, Romain Francois <francoisromain at free.fr>
+ *
+ * This file is part of the RemoteREngine project
+ *
+ * The RemoteREngine project 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 of the License, or
+ * (at your option) any later version.
+ *
+ * The RemoteREngine project 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the RemoteREngine project. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.rosuda.REngine.remote.client ;
+
+import java.rmi.RemoteException;
+
+public class RemoteExceptionManager {
+	public static void send( RemoteException e, String method){
+		// placeholder 
+		System.err.println(method + " triggered an exception - " + e.getClass().getName() + 
+				((e.getMessage() != null && e.getMessage().length() > 0) ? ", " + e.getMessage() : "" ) +
+				" caused by " +	e.getCause().getClass().getName());
+		e.printStackTrace( System.err ) ; 
+	}
+}

Added: pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/RemoteREngine.java
===================================================================
--- pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/RemoteREngine.java	                        (rev 0)
+++ pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/RemoteREngine.java	2009-09-07 11:49:30 UTC (rev 99)
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) 2009, Romain Francois <francoisromain at free.fr>
+ *
+ * This file is part of the RemoteREngine project
+ *
+ * The RemoteREngine project 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 of the License, or
+ * (at your option) any later version.
+ *
+ * The RemoteREngine project 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the RemoteREngine project. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.rosuda.REngine.remote.client ;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+
+import org.rosuda.REngine.REXP;
+import org.rosuda.REngine.REXPMismatchException;
+import org.rosuda.REngine.REXPNull;
+import org.rosuda.REngine.REXPReference;
+import org.rosuda.REngine.REngine;
+import org.rosuda.REngine.REngineException;
+import org.rosuda.REngine.REnginePool;
+import org.rosuda.REngine.remote.client.callbacks.ClientCallbackDispatcher;
+import org.rosuda.REngine.remote.common.JRIEngineGlobalVariables;
+import org.rosuda.REngine.remote.common.RemoteREngineClient;
+import org.rosuda.REngine.remote.common.RemoteREngineConstants;
+import org.rosuda.REngine.remote.common.RemoteREngineInterface;
+import org.rosuda.REngine.remote.common.callbacks.CallbackListener;
+import org.rosuda.REngine.remote.common.callbacks.CallbackResponse;
+import org.rosuda.REngine.remote.common.callbacks.RCallback;
+import org.rosuda.REngine.remote.common.callbacks.RCallbackWithResponse;
+import org.rosuda.REngine.remote.common.exceptions.FileAlreadyExistsException;
+import org.rosuda.REngine.remote.common.exceptions.NotRegisteredException;
+import org.rosuda.REngine.remote.common.exceptions.ServerSideIOException;
+import org.rosuda.REngine.remote.common.files.FileChunk;
+import org.rosuda.REngine.remote.common.files.RemoteFileInputStream;
+import org.rosuda.REngine.remote.common.files.RemoteFileOutputStream;
+
+/**
+ * An implementation of the REngine API that communicates through an 
+ * RMI protocol
+ */
+public class RemoteREngine extends REngine implements RemoteREngineClient {
+
+	/**
+	 * The remote interface through which this client calls the server
+	 */
+	private RemoteREngineInterface engine;
+
+	/** 
+	 * reference to the global environment of the remote engine
+	 */
+	public REXPReference globalEnv ; 
+	
+	/**
+	 * reference to the empty environment of the remote engine
+	 */
+	public REXPReference emptyEnv ; 
+	
+	/**
+	 * Reference to the base environment of the remote engine
+	 */
+	public REXPReference baseEnv ; 
+	
+	/**
+	 * Reference to the NULL value of the remote engine
+	 */
+	public REXPReference nullValueRef;
+
+	/**
+	 * canonical NULL object (obtained from the server)
+	 */
+	public REXPNull nullValue;
+
+	/** 
+	 * the hashcode of the server this shadows
+	 */
+	private int serverHashCode ; 
+	
+	/**
+	 * Is this engine valid ?
+	 */
+	private boolean valid = false; 
+
+	/**
+	 * Shutdown hook for this client
+	 */
+	private RemoteREngineShutdownHook shutdownHook ; 
+	
+	private ClientCallbackDispatcher callbackDispatcher ;
+	
+	/**
+	 * Construct a RemoteREngine
+	 * @param registryHost Name or IP Address of the host containing the RMI registry
+	 * @param name Name of the Remote server registered within the Registry
+	 * @param port port to use to connect to the server
+	 */
+	public RemoteREngine(String name, String registryHost, int port){
+		if (name == null || name.length()==0) {
+			System.err.println("RMI Name of remote engine not defined");
+		}
+		try{
+			Registry reg = LocateRegistry.getRegistry(registryHost, port);
+			engine = (RemoteREngineInterface) reg.lookup(name);
+
+			/* subscribe to the server and populate the fields */
+			/* System.out.println( "subscribe to the server" ) ; */
+			UnicastRemoteObject.exportObject(this) ;
+			JRIEngineGlobalVariables variables = engine.subscribe(this) ;
+			callbackDispatcher = new ClientCallbackDispatcher(this) ;
+			callbackDispatcher.start(); 
+			serverHashCode = variables.hashCode ;
+			globalEnv    = variables.globalEnv ;
+			emptyEnv     = variables.emptyEnv ; 
+			baseEnv      = variables.baseEnv ; 
+			nullValueRef = variables.nullValueRef ;
+			nullValue    = variables.nullValue ; 
+			
+			/* store this engine in the pool */
+			REnginePool.add( this, serverHashCode ); 
+			valid = true; 
+			
+		} catch ( NotBoundException nb) {
+			System.out.println("Unable to locate " + name + " within RMI Registry");
+		} catch( Exception e ){
+			System.out.println( e.getClass().getName() + " creating the RemoteREngine" ) ;
+			e.printStackTrace();
+		}
+		
+		shutdownHook = new RemoteREngineShutdownHook(); 
+		
+		/* let the server know when the jvm of this client closes */
+		Runtime.getRuntime().addShutdownHook( shutdownHook ) ;
+		
+		
+	}
+	
+	/**
+	 * Shutdown hook for the client. This is used when the jvm of the client
+	 * is about to shutdown so that the server is informed and can stop
+	 * sending callbacks to this client
+	 * 
+	 * @see Runtime#addShutdownHook(Thread)
+	 * @author Romain Francois
+	 *
+	 */
+	private class RemoteREngineShutdownHook extends Thread {
+		public void run(){
+			if( isValid() ){
+				close( ) ; 
+			}
+		}
+	}
+
+	/**
+	 * Indicates if this engine is valid
+	 */
+	public boolean isValid(){
+		/* TODO: maybe ping the engine */
+		return valid; 
+	}
+	
+	/**
+	 * Constructor using the default port
+	 * 
+	 * @see RemoteREngineConstants#RMIPORT for the default value
+	 * @param name name of the remote object in the registry
+	 * @param registryHost host name
+	 */
+	public RemoteREngine(String name, String registryHost ){
+		this( name, registryHost, 1099 ) ;
+	}
+
+	/**                                                    
+	 * parse a string into an expression vector         
+	 *
+	 * @param text string to parse
+	 * @param resolve resolve the resulting REXP (<code>true</code>) or just return a reference (<code>false</code>)
+	 * @return parsed expression 
+	 */
+	public REXP parse(String text, boolean resolve) throws REngineException{
+		REXP res = null ; 
+		try{
+			res = engine.parse( text, resolve );
+		} catch( RemoteException e){
+			RemoteExceptionManager.send( e, "parse" ); 
+		}
+		return res ;
+	}
+
+	/** 
+	 * evaluate an expression vector
+	 * @param what an expression (or vector of such) to evaluate
+	 * @param where environment to evaluate in (use <code>null</code> for the global environemnt and/or if environments are not supported by the engine)
+	 * @param resolve resolve the resulting REXP or just return a reference
+	 * @return the result of the evaluation of the last expression 
+	 */
+	public REXP eval(REXP what, REXP where, boolean resolve) throws REngineException, REXPMismatchException{
+		REXP res = null ; 
+		try{
+			res = engine.eval( what, where, resolve );  
+		} catch( RemoteException e){
+			RemoteExceptionManager.send( e, "eval" ); 
+		}
+		return res ;
+	}
+
+	/**
+	 * assign into an environment
+	 *
+	 * @param symbol symbol name
+	 * @param value value to assign
+	 * @param env environment to assign to (use <code>null</code> for the global environemnt and/or if environments are not supported by the engine
+	 */
+	public void assign(String symbol, REXP value, REXP env) throws REngineException, REXPMismatchException{
+		try{
+			engine.assign( symbol, value, env );  
+		} catch( RemoteException e){
+			RemoteExceptionManager.send( e, "assign" ); 
+		}
+	}
+
+	/**
+	 * get a value from an environment
+	 * @param symbol symbol name
+	 * @param env environment (use <code>null</code> for the global environemnt and/or if environments are not supported by the engine)
+	 * @param resolve resolve the resulting REXP or just return a reference		
+	 * @return value
+	 */
+	public REXP get(String symbol, REXP env, boolean resolve) throws REngineException, REXPMismatchException{
+		REXP res = null ; 
+		try{
+			res = engine.get( symbol, env, resolve );  
+		} catch( RemoteException e){
+			RemoteExceptionManager.send( e, "get" ); 
+		}
+		return res ;
+	}
+
+	/** 
+	 * fetch the contents of the given reference. 
+	 * The resulting REXP may never be REXPReference. 
+	 * The engine should raise a {@link #REngineException} exception
+	 * if {@link #supportsReferences()} returns <code>false</code>.
+	 * 
+	 * @param ref reference to resolve
+	 * @return resolved reference
+	 */
+	public REXP resolveReference(REXP ref) throws REngineException, REXPMismatchException{
+		REXP res = null ; 
+		try{
+			res = engine.resolveReference(ref) ;  
+		} catch( RemoteException e){
+			RemoteExceptionManager.send( e, "resolveReference" ); 
+		}
+		return res ;
+	}
+
+	/** 
+	 * create a reference by pushing local data to R and returning a reference to the data. If ref is a reference it is returned as-is. 
+	 * The engine should raise a {@link #REngineException} exception if {@link #supportsReferences()} returns <code>false</code>.
+	 * 
+	 * @param value to create reference to
+	 * @return reference to the value
+	 */
+	public REXP createReference(REXP value) throws REngineException, REXPMismatchException{
+		REXP res = null ; 
+		try{
+			res = engine.createReference( value );    
+		} catch( RemoteException e){
+			RemoteExceptionManager.send( e, "createReference" ); 
+		}
+		return res ;
+	}
+
+	/** 
+	 * removes reference from the R side. This method is called automatically by the finalizer 
+	 * of <code>REXPReference</code> and should never be called directly.
+	 *
+	 * @param ref reference to finalize 
+	 */
+	public void finalizeReference(REXP ref) throws REngineException, REXPMismatchException{
+		try{
+			engine.finalizeReference( ref );     
+		} catch( RemoteException e){
+			RemoteExceptionManager.send( e, "finalizeReference" ); 
+		}
+	}
+
+	/**
+	 * get the parent environemnt of an environment
+	 *
+	 * @param env environment to query
+	 * @param resolve whether to resolve the resulting environment reference
+	 * @return parent environemnt of env
+	 */
+	public REXP getParentEnvironment(REXP env, boolean resolve) throws REngineException, REXPMismatchException{
+		REXP res = null ; 
+		try{
+			res = engine.getParentEnvironment( env, resolve );    
+		} catch( RemoteException e){
+			RemoteExceptionManager.send( e, "getParentEnvironment" ); 
+		}
+		return res ;
+	}
+
+	/**
+	 * create a new environment
+	 *
+	 * @param parent parent environment
+	 * @param resolve whether to resolve the reference to the environemnt (usually <code>false</code> since the returned environment will be empty)
+	 * @return resulting environment
+	 */
+	public REXP newEnvironment(REXP parent, boolean resolve) throws REngineException, REXPMismatchException{
+		REXP res = null ; 
+		try{
+			res = engine.newEnvironment( parent, resolve ) ;    
+		} catch( RemoteException e){
+			RemoteExceptionManager.send( e, "newEnvironment" ); 
+		}
+		return res ;
+	}
+
+	/**
+	 * Convenience method to parse and eval
+	 */
+	public REXP parseAndEval(String text, REXP where, boolean resolve) throws REngineException, REXPMismatchException {
+		REXP res = null; 
+		try{
+			res = engine.parseAndEval( text, where, resolve ) ;
+		} catch( RemoteException e){
+			RemoteExceptionManager.send( e, "parseAndEval" );
+		}
+		return res ; 
+	}
+
+	/**
+	 * Push a file from the client side to the server side
+	 * 
+	 * @param client_file name of the file in the client 
+	 * @param server_file name of the file in the server
+	 * @param must_be_new if true, throw an exception if the file already exists 
+	 */
+	public void pushFile( String client_file, String server_file, boolean must_be_new ) throws IOException, ServerSideIOException, FileAlreadyExistsException {
+		BufferedInputStream client_in = new BufferedInputStream( new FileInputStream( client_file ) ) ;
+		RemoteFileOutputStream server_out = engine.createFile(server_file, must_be_new) ;
+
+		byte [] b = new byte[ RemoteREngineConstants.CHUNKSIZE ];
+
+		/* typical java IO stuff */
+		int c = client_in.read(b) ; 
+		while( c >= 0 ){
+			server_out.write( b, 0, c ) ;
+			c = client_in.read(b) ;
+		}
+		server_out.close();
+		client_in.close(); 
+	}
+
+	/**
+	 * Fetch a file from the server
+	 * 
+	 * @param client_file the name of the file in the client to write into
+	 * @param server_file the name of the server file to fetch
+	 * @param delete delete the file after fetching it ?
+	 * @throws IOException 
+	 */
+	public void fetchFile( String client_file, String server_file, boolean delete ) throws IOException, ServerSideIOException {
+		BufferedOutputStream client_out = new BufferedOutputStream( new FileOutputStream( client_file ) ) ;
+		RemoteFileInputStream server_in = engine.openFile(server_file) ;
+
+		FileChunk chunk = server_in.readNextChunk() ;
+		while( ! chunk.isEmpty() ){
+			client_out.write(chunk.buffer, 0, chunk.size ) ;
+			chunk = server_in.readNextChunk() ;
+		}
+		server_in.close() ;
+		client_out.close(); 
+		if( delete ){
+			server_in.delete(); 
+		}
+	}
+
+	/** 
+	 * References are supported since this mirrors a JRIEngine
+	 */
+	public boolean supportsReferences() { 
+		return true ;
+	}
+
+	/** 
+	 * Environments are supported since this mirrors a JRIEngine
+	 */
+	public boolean supportsEnvironemnts() {
+		return true ;
+	}
+
+	/** 
+	 * REPL is supported since this mirrors a JRIEngine 
+	 */
+	public boolean supportsREPL() {
+		return true ;
+	}
+
+	/* TODO: implement the locking mechanism in the server side */
+	/** 
+	 * locking is supported since this mirrors a JRIEngine
+	 */
+	public boolean supportsLocking() { 
+		return true ; 
+	}
+	
+	/**
+	 * End the subscription of this client with the R engine on the server side
+	 * This method invalidates fields previously set by the subscription mechanism
+	 * and makes this engine useless
+	 */
+	@Override
+	public boolean close() {
+		try{
+			engine.close( this ) ;
+		} catch( NotRegisteredException e){
+			/* TODO: handle NotRegisteredException when closing the client */
+		} catch( RemoteException e){
+			/* TODO: handle RemoteException when closing the client */
+		}
+		invalidate(); 
+		return true;  
+	}
+
+	private void invalidate() {
+		valid = false; 
+		engine = null ; 
+		globalEnv = null; 
+		emptyEnv = null;
+		baseEnv = null ; 
+		nullValueRef = null; 
+		nullValue = null; 
+		serverHashCode = Integer.MIN_VALUE ;
+	}
+	
+	/**
+	 * Receives a callback from the server and dispatchs it to listeners
+	 */
+	public void callback(RCallback callback) throws RemoteException {
+		callbackDispatcher.addToQueue( callback ) ;
+	}
+		
+	/**
+	 * Unregister this client from the server before usual finalization
+	 */
+	@Override
+	protected void finalize() throws Throwable {
+		close() ;
+		super.finalize();
+	}
+
+	/**
+	 * Adds a new callback listener
+	 * 
+	 * @param listener callback listener
+	 * @see ClientCallbackDispatcher#addCallbackListener(CallbackListener)
+	 */
+	public void addCallbackListener( CallbackListener listener){
+		callbackDispatcher.addCallbackListener( listener ) ;
+	}
+	
+	/**
+	 * Removes a callback listener
+	 * @param listener callback listener
+	 * @see ClientCallbackDispatcher#removeCallbackListener(CallbackListener)
+	 */
+	public void removeCallbackListener( CallbackListener listener ){
+		callbackDispatcher.removeCallbackListener( listener ) ;
+	}
+
+	/**
+	 * Send a callback response to the server
+	 * @param response a callback response
+	 */
+	public void sendResponse( CallbackResponse<? extends RCallbackWithResponse> response){
+		try{
+			engine.sendResponse(response) ;
+		} catch( RemoteException re){
+			/*  what */
+		}
+	}
+	
+	/**
+	 * Send a command to the console
+	 * @param command command to send 
+	 */
+	public void sendToConsole( String command ){
+		try {
+			engine.sendToConsole(command, this ) ;
+		} catch (RemoteException e) {
+			/* what now */
+		} 
+	}
+	
+}
+

Added: pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/callbacks/ClientCallbackDispatcher.java
===================================================================
--- pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/callbacks/ClientCallbackDispatcher.java	                        (rev 0)
+++ pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/callbacks/ClientCallbackDispatcher.java	2009-09-07 11:49:30 UTC (rev 99)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2009, Romain Francois <francoisromain at free.fr>
+ *
+ * This file is part of the RemoteREngine project
+ *
+ * The RemoteREngine project 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 of the License, or
+ * (at your option) any later version.
+ *
+ * The RemoteREngine project 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the RemoteREngine project. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.rosuda.REngine.remote.client.callbacks;
+
+import java.util.Vector;
+
+import org.rosuda.REngine.remote.client.RemoteREngine;
+import org.rosuda.REngine.remote.common.callbacks.CallbackListener;
+import org.rosuda.REngine.remote.common.callbacks.RCallback;
+import org.rosuda.REngine.remote.common.tools.StoppableThreadWithSynchronizer;
+
+/**
+ * Dispatches the callback on the client side
+ * @author Romain Francois
+ *
+ */
+public class ClientCallbackDispatcher extends StoppableThreadWithSynchronizer<RCallback> {
+
+	/**
+	 * The client 
+	 */
+	protected RemoteREngine engine; 
+	
+	/**
+	 * List of listeners
+	 */
+	protected Vector<CallbackListener> listeners ; 
+	
+	/**
+	 * Constructor
+	 * @param client
+	 */
+	public ClientCallbackDispatcher(RemoteREngine engine) {
+		super("client callback dispatcher");
+		this.engine = engine  ; 
+		listeners = new Vector<CallbackListener>(); 
+	}
+
+	/**
+	 * Forwards the callback to each listener of the client
+	 */
+	@Override
+	public void dealWith(RCallback callback) {
+		for( CallbackListener listener: listeners ){
+			listener.handleCallback(callback) ;
+		}
+	}
+
+	/**
+	 * Adds a new listener
+	 * @param listener callback listener
+	 */
+	public synchronized void addCallbackListener(CallbackListener listener) {
+		listeners.add( listener ) ;
+	}
+	
+	/**
+	 * Removes a callback listener
+	 * @param listener callback listener to remove
+	 */
+	public synchronized void removeCallbackListener( CallbackListener listener ){
+		listeners.remove( listener ) ;
+	}
+	
+
+}

Added: pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/AllTests.java
===================================================================

Added: pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/DataFrames_Test.java
===================================================================
--- pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/DataFrames_Test.java	                        (rev 0)
+++ pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/DataFrames_Test.java	2009-09-07 11:49:30 UTC (rev 99)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2009, Romain Francois <francoisromain at free.fr>
+ *
+ * This file is part of the RemoteREngine project
+ *
+ * The RemoteREngine project 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 of the License, or
+ * (at your option) any later version.
+ *
+ * The RemoteREngine project 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the RemoteREngine project. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.rosuda.REngine.remote.client.test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.rosuda.REngine.REXP;
+import org.rosuda.REngine.REXPLogical;
+import org.rosuda.REngine.REXPMismatchException;
+import org.rosuda.REngine.REngineException;
+import org.rosuda.REngine.remote.client.RemoteREngine;
+
+/**
+ * Testing pass-though capability for data.frames ...
+ * this test does a pull and push of a data frame. It will fail when the S3 test above failed.
+ * 
+ * @author Romain Francois
+ *
+ */
+public class DataFrames_Test {
+
+	private RemoteREngine r; 
+	
+	@Before
+	public void setR(){
+		r = TestEnvironment.cleanR() ;
+	}
+	
+	@After
+	public void forgetR(){
+		r = null ; 
+	}
+	
+	@Test
+	public void pullAndPush() throws REngineException, REXPMismatchException {
+		REXP df = r.parseAndEval("{data(iris); iris}");
+		int ncols = df.asList().size() ;
+		assertEquals("ncols of pulled data frame", 5, ncols ); 
+		int[] nrows = new int[ncols] ;
+		for( int i=0; i<ncols; i++){
+			nrows[i] = df.asList().at(i).length() ;
+		}
+		int[] expected = {150,150,150,150,150}; 
+		assertArrayEquals("nrows of pulled data frame", nrows, expected ); 
+		
+		r.assign("df", df);
+		assertEquals("ncols of pushed data frame", 5, r.parseAndEval("ncol(df)").asInteger() ) ;
+		assertEquals("nrows of pushed data frame", 150, r.parseAndEval("nrow(df)").asInteger() ) ;
+		boolean identical = ((REXPLogical)r.parseAndEval("identical(df, iris)")).isTRUE()[0] ;
+		assertTrue( "identical( df, iris )", identical ) ;
+	}
+
+}

Added: pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/Doubles_Test.java
===================================================================
--- pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/Doubles_Test.java	                        (rev 0)
+++ pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/Doubles_Test.java	2009-09-07 11:49:30 UTC (rev 99)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2009, Romain Francois <francoisromain at free.fr>
+ *
+ * This file is part of the RemoteREngine project
+ *
+ * The RemoteREngine project 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 of the License, or
+ * (at your option) any later version.
+ *
+ * The RemoteREngine project 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the RemoteREngine project. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.rosuda.REngine.remote.client.test;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.rosuda.REngine.REXPDouble;
+import org.rosuda.REngine.REXPMismatchException;
+import org.rosuda.REngine.REngineException;
+import org.rosuda.REngine.remote.client.RemoteREngine;
+import static org.junit.Assert.*;
+
+public class Doubles_Test {
+
+private RemoteREngine r ; 
+	
+	@Before
+	public void getR(){
+		r = TestEnvironment.cleanR() ;
+	}
+	
+	@After
+	public void forgetR(){
+		r = null; 
+	}
+
+	@Test
+	public void pushNAtoR() throws REngineException, REXPMismatchException {
+		double x[] = { 1.0, 0.5, REXPDouble.NA , Double.NaN, 3.5 };
+		r.assign("x",x);
+		String nas = r.parseAndEval("paste(capture.output(print(x)),collapse='\\n')").asString();
+		assertEquals("testing NA support", "[1] 1.0 0.5  NA NaN 3.5", nas) ;
+	}
+	
+	@Test
+	public void getNAFromR() throws REngineException, REXPMismatchException{
+		double[] y = r.parseAndEval( "c(NA,1.0,NaN,-Inf,Inf)").asDoubles() ;
+		assertTrue( "testing NA values with isNA", REXPDouble.isNA(y[0]) );
+		assertTrue( "testing NaN", Double.isNaN(y[2]) ) ;
+		assertTrue( "testing infinite values + ", Double.isInfinite(y[3]) ) ;
+		assertTrue( "testing infinite values - ", Double.isInfinite(y[4]) ) ;
+	}
+}

Added: pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/Lists_Test.java
===================================================================
--- pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/Lists_Test.java	                        (rev 0)
+++ pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/Lists_Test.java	2009-09-07 11:49:30 UTC (rev 99)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2009, Romain Francois <francoisromain at free.fr>
+ *
+ * This file is part of the RemoteREngine project
+ *
+ * The RemoteREngine project 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 of the License, or
+ * (at your option) any later version.
+ *
+ * The RemoteREngine project 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the RemoteREngine project. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.rosuda.REngine.remote.client.test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.rosuda.REngine.REXP;
+import org.rosuda.REngine.REXPDouble;
+import org.rosuda.REngine.REXPInteger;
+import org.rosuda.REngine.REXPList;
+import org.rosuda.REngine.REXPLogical;
+import org.rosuda.REngine.REXPMismatchException;
+import org.rosuda.REngine.REngineException;
+import org.rosuda.REngine.RList;
+import org.rosuda.REngine.remote.client.RemoteREngine;
+
+public class Lists_Test {
+
+	private RemoteREngine r; 
+	
+	@Before
+	public void setR(){
+		r = TestEnvironment.cleanR() ;
+	}
+	
+	@After
+	public void forgetR(){
+		r = null ; 
+	}
+	
+	@Test
+	public void assignList() throws REngineException, REXPMismatchException {
+		int[] la = new int[]{ 0,1,2,3 } ;
+		double[] lb = new double[]{0.5,1.2,2.3,3.0} ;
+		
+		RList l = new RList();
+		l.put("a",new REXPInteger(la));
+		l.put("b",new REXPDouble(lb));
+		r.assign("x", new REXPList(l));
+		assertTrue( "does the list exist",
+			( (REXPLogical)r.parseAndEval("exists('x') && is.list(x)" ) ).isTRUE()[0] );
+		REXP x = r.parseAndEval("x");
+		assertEquals( "test java class of list" , "REXPList" , x.getClass().getSimpleName() ) ;
+		RList xl = x.asList(); 
+		assertEquals( "test length of list back in java", 2 , xl.size() ) ;
+		assertEquals( "test class of list element (1)", "REXPInteger", xl.at(0).getClass().getSimpleName() ) ;
+		assertArrayEquals("test values of list element (1)", la , xl.at(0).asIntegers() ) ;
+		
+		assertEquals( "test class of list element (2)", "REXPDouble", xl.at(1).getClass().getSimpleName() ) ;
+		assertArrayEquals("test values of list element (2)", lb , xl.at(1).asDoubles(), 0.0 ) ;
+		
+		/* TODO: more tests on lists */
+		
+		/*
+		r.assign("y", new REXPGenericVector(l) );
+		r.assign("z", REXP.createDataFrame(l) );
+		
+		REXP y = r.parseAndEval("y");
+		REXP z = r.parseAndEval("z");
+		
+		assertEquals( "test classes of generic vector" , "REXPList" , x.getClass().getSimpleName() ) ;
+		*/
+		
+	}
+
+}

Added: pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/RemoteREngineTest.java
===================================================================
--- pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/RemoteREngineTest.java	                        (rev 0)
+++ pkg/RemoteREngine/inst/java_src/src/client/org/rosuda/REngine/remote/client/test/RemoteREngineTest.java	2009-09-07 11:49:30 UTC (rev 99)
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2009, Romain Francois <francoisromain at free.fr>
+ *
+ * This file is part of the RemoteREngine project
+ *
+ * The RemoteREngine project 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 of the License, or
+ * (at your option) any later version.
+ *
+ * The RemoteREngine project 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the RemoteREngine project. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.rosuda.REngine.remote.client.test ;
+
+/*{{{ imports */
+import static org.rosuda.REngine.remote.common.RemoteREngineConstants.DEFAULTNAME;
+import static org.rosuda.REngine.remote.common.RemoteREngineConstants.RMIHOSTNAME;
+
+import java.io.File;
+import java.util.Map;
+
+import org.rosuda.REngine.REXP;
+import org.rosuda.REngine.REXPEnvironment;
+import org.rosuda.REngine.REXPFactor;
+import org.rosuda.REngine.REXPLogical;
+import org.rosuda.REngine.REXPMismatchException;
+import org.rosuda.REngine.REXPRaw;
+import org.rosuda.REngine.REXPString;
+import org.rosuda.REngine.REngineException;
+import org.rosuda.REngine.RFactor;
+import org.rosuda.REngine.RList;
+import org.rosuda.REngine.remote.client.RemoteREngine;
+import org.rosuda.REngine.remote.common.CommandLineArgs;
+
+public class RemoteREngineTest {
+
+	/*{{{ main */
+	public static void main(String[] args) {
+
+		/*{{{ security manager */
+		if (System.getSecurityManager() == null) {
+			System.setSecurityManager(new SecurityManager());
+		}
+		/*}}}*/
+
+		try { 
+
+			String name = DEFAULTNAME ;
+			String host = RMIHOSTNAME ;
+			int port = 1099; 
+			
+			
+			Map<String,String> arguments = CommandLineArgs.arguments(args) ;
+			if( arguments.containsKey("host")){
+				host = arguments.get("host") ;
+			}
+			if( arguments.containsKey("name")){
+				name = arguments.get("name");
+			}
+			if( arguments.containsKey("port")){
+				try{
+					port = Integer.parseInt(arguments.get("port")) ;
[TRUNCATED]

To get the complete diff run:
    svnlook diff /svnroot/remoterengine -r 99


More information about the Remoterengine-commits mailing list