From 12546eb2e198c9cb5fd9465691e69c23a22d6873 Mon Sep 17 00:00:00 2001
From: cramakri <cramakri>
Date: Wed, 3 Nov 2010 08:56:34 +0000
Subject: [PATCH] LMS-1844 Refactoring of clients to add clearer support for
 result codes.

SVN: 18512
---
 .../dss/client/api/cli/AbstractClient.java    |  40 +++--
 .../api/cli/AbstractDataSetExecutor.java      |   4 +-
 .../dss/client/api/cli/AbstractExecutor.java  |  10 +-
 .../dss/client/api/cli/CommandGet.java        |   3 +-
 .../dss/client/api/cli/CommandHelp.java       |   9 +-
 .../openbis/dss/client/api/cli/CommandLs.java |   3 +-
 .../dss/client/api/cli/CommandPut.java        |  13 +-
 .../openbis/dss/client/api/cli/ICommand.java  |   4 +-
 .../dss/client/api/cli/ResultCode.java        |  38 +++++
 .../dss/client/api/cli/CommandGetTest.java    |   8 +-
 .../dss/client/api/cli/CommandLsTest.java     |   4 +-
 .../dss/client/api/cli/CommandPutTest.java    |   4 +-
 .../api/v1/GeneralInformationService.java     |   2 +-
 .../client/util/cli/AbstractExecutor.java     |  11 +-
 .../util/cli/CommandExperimentLister.java     |   8 +-
 .../util/cli/CommandGenerateSampleCode.java   |   8 +-
 .../client/util/cli/CommandSampleLister.java  |   8 +-
 .../util/cli/CommandExperimentListerTest.java | 160 ++++++++++++++++++
 .../cli/CommandGenerateSampleCodeTest.java    |   9 +-
 .../util/cli/CommandSampleListerTest.java     |   9 +-
 20 files changed, 284 insertions(+), 71 deletions(-)
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/ResultCode.java
 create mode 100644 rtd_cina/sourceTest/java/ch/systemsx/cisd/cina/client/util/cli/CommandExperimentListerTest.java

diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/AbstractClient.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/AbstractClient.java
index 1ff7c2a37e7..eb76c341d55 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/AbstractClient.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/AbstractClient.java
@@ -73,35 +73,36 @@ public class AbstractClient
     protected void runWithArgs(String[] args)
     {
         ICommand command = getCommandOrDie(args);
-    
-        int resultCode = 0;
+
+        int exitCode = 0;
         try
         {
             // Strip the name of the command and pass the rest of the arguments to the command
             String[] cmdArgs = new String[args.length - 1];
             Arrays.asList(args).subList(1, args.length).toArray(cmdArgs);
-            resultCode = command.execute(cmdArgs);
+            ResultCode result = command.execute(cmdArgs);
+            exitCode = result.getValue();
         } catch (final InvalidSessionException ex)
         {
             System.err
                     .println("Your session is no longer valid. Please login again. [server said: '"
                             + ex.getMessage() + "']");
-            resultCode = 1;
+            exitCode = ResultCode.INVALID_SESSION.getValue();
         } catch (final UserFailureException ex)
         {
             System.err.println();
             System.err.println(ex.getMessage());
-            resultCode = 1;
+            exitCode = ResultCode.USER_ERROR.getValue();
         } catch (final EnvironmentFailureException ex)
         {
             System.err.println();
             System.err.println(ex.getMessage() + " (environment failure)");
-            resultCode = 1;
+            exitCode = ResultCode.ENVIRONMENT_ERROR.getValue();
         } catch (final RemoteConnectFailureException ex)
         {
             System.err.println();
             System.err.println("Remote server cannot be reached (environment failure)");
-            resultCode = 1;
+            exitCode = ResultCode.NO_CONNECTION_TO_SERVER.getValue();
         } catch (final RemoteAccessException ex)
         {
             System.err.println();
@@ -113,43 +114,48 @@ public class AbstractClient
                     System.err.println(String.format(
                             "Given host '%s' can not be reached  (environment failure)",
                             cause.getMessage()));
+                    exitCode = ResultCode.NO_CONNECTION_TO_SERVER.getValue();
                 } else if (cause instanceof IllegalArgumentException)
                 {
                     System.err.println(cause.getMessage());
+                    exitCode = ResultCode.UNKNOWN_ERROR.getValue();
                 } else if (cause instanceof SSLHandshakeException)
                 {
                     final String property = "javax.net.ssl.trustStore";
                     System.err.println(String.format(
                             "Validation of SSL certificate failed [%s=%s] (configuration failure)",
                             property, StringUtils.defaultString(System.getProperty(property))));
+                    exitCode = ResultCode.ENVIRONMENT_ERROR.getValue();
                 } else
                 {
                     ex.printStackTrace();
+                    exitCode = ResultCode.UNKNOWN_ERROR.getValue();
                 }
             } else
             {
                 ex.printStackTrace();
+                exitCode = ResultCode.UNKNOWN_ERROR.getValue();
             }
-            resultCode = 1;
+
         } catch (final SystemExitException e)
         {
-            resultCode = 1;
+            exitCode = ResultCode.UNKNOWN_ERROR.getValue();
         } catch (MasqueradingException e)
         {
             System.err.println(e);
-            resultCode = 1;
+            exitCode = ResultCode.UNKNOWN_ERROR.getValue();
         } catch (IllegalArgumentException e)
         {
             System.err.println(e.getMessage());
-            resultCode = 1;
+            exitCode = ResultCode.UNKNOWN_ERROR.getValue();
         } catch (final Exception e)
         {
             System.err.println();
             e.printStackTrace();
-            resultCode = 1;
+            exitCode = ResultCode.UNKNOWN_ERROR.getValue();
         }
-    
-        exitHandler.exit(resultCode);
+
+        exitHandler.exit(exitCode);
     }
 
     private ICommand getCommandOrDie(String[] args)
@@ -160,11 +166,11 @@ public class AbstractClient
             ICommand help = commandFactory.getHelpCommand();
             help.printUsage(System.err);
             exitHandler.exit(1);
-    
+
             // Never gets here
             return null;
         }
-    
+
         String commandName = args[0];
         ICommand command = commandFactory.tryCommandForName(commandName);
         if (null == command)
@@ -172,7 +178,7 @@ public class AbstractClient
             ICommand help = commandFactory.getHelpCommand();
             help.printUsage(System.err);
             exitHandler.exit(1);
-    
+
             // Never gets here
             return null;
         }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/AbstractDataSetExecutor.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/AbstractDataSetExecutor.java
index 7740bcd939c..c157468d1ea 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/AbstractDataSetExecutor.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/AbstractDataSetExecutor.java
@@ -32,12 +32,12 @@ abstract class AbstractDataSetExecutor<A extends DataSetArguments> extends Abstr
     }
 
     @Override
-    protected final int doExecute(IDssComponent component)
+    protected final ResultCode doExecute(IDssComponent component)
     {
         IDataSetDss dataSet = component.getDataSet(arguments.getDataSetCode());
         FileInfoDssDTO[] fileInfos = getFileInfos(dataSet);
         handle(fileInfos, dataSet);
-        return 0;
+        return ResultCode.OK;
     }
 
     private FileInfoDssDTO[] getFileInfos(IDataSetDss dataSet)
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/AbstractExecutor.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/AbstractExecutor.java
index c88fcd6a0bb..dee9e11f598 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/AbstractExecutor.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/AbstractExecutor.java
@@ -37,7 +37,7 @@ abstract class AbstractExecutor<A extends GlobalArguments>
         parser = new CmdLineParser(arguments);
     }
 
-    final int execute(String[] args)
+    final ResultCode execute(String[] args)
     {
         parser.parseArgument(args);
 
@@ -45,14 +45,14 @@ abstract class AbstractExecutor<A extends GlobalArguments>
         if (arguments.isHelp())
         {
             command.printUsage(System.out);
-            return 0;
+            return ResultCode.OK;
         }
 
         // Show usage and exit
         if (arguments.isComplete() == false)
         {
             command.printUsage(System.err);
-            return 1;
+            return ResultCode.INVALID_ARGS;
         }
 
         IDssComponent component = null;
@@ -61,7 +61,7 @@ abstract class AbstractExecutor<A extends GlobalArguments>
             component = command.login(arguments);
             if (null == component)
             {
-                return 1;
+                return ResultCode.INVALID_UNAME_PASS;
             }
             return doExecute(component);
         } finally
@@ -75,5 +75,5 @@ abstract class AbstractExecutor<A extends GlobalArguments>
 
     }
 
-    protected abstract int doExecute(IDssComponent component);
+    protected abstract ResultCode doExecute(IDssComponent component);
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandGet.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandGet.java
index 20a3a2b57c4..19a2a807522 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandGet.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandGet.java
@@ -149,7 +149,8 @@ class CommandGet extends AbstractDssCommand<CommandGet.CommandGetArguments>
         super(new CommandGetArguments());
     }
 
-    public int execute(String[] args) throws UserFailureException, EnvironmentFailureException
+    public ResultCode execute(String[] args) throws UserFailureException,
+            EnvironmentFailureException
     {
         return new CommandGetExecutor(arguments, this).execute(args);
     }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandHelp.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandHelp.java
index 84524fcdf02..bffda17932f 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandHelp.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandHelp.java
@@ -45,24 +45,25 @@ public class CommandHelp extends AbstractCommand<CommandHelp.CommandHelpArgument
         this.programCallString = programCallString;
     }
 
-    public int execute(String[] args) throws UserFailureException, EnvironmentFailureException
+    public ResultCode execute(String[] args) throws UserFailureException,
+            EnvironmentFailureException
     {
         parser.parseArgument(args);
         if (arguments.getArguments().size() < 1)
         {
             printUsage(System.out);
-            return 0;
+            return ResultCode.INVALID_ARGS;
         }
 
         ICommand cmd = commandFactory.tryCommandForName(arguments.getArguments().get(0));
         if (null == cmd)
         {
             printUsage(System.out);
-            return 0;
+            return ResultCode.INVALID_ARGS;
         }
 
         cmd.printUsage(System.out);
-        return 0;
+        return ResultCode.OK;
     }
 
     public String getName()
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandLs.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandLs.java
index e5f6b42afb0..91cedd8540c 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandLs.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandLs.java
@@ -61,7 +61,8 @@ class CommandLs extends AbstractDssCommand<DataSetArguments>
         super(new DataSetArguments());
     }
 
-    public int execute(String[] args) throws UserFailureException, EnvironmentFailureException
+    public ResultCode execute(String[] args) throws UserFailureException,
+            EnvironmentFailureException
     {
         return new CommandLsExecutor(arguments, this).execute(args);
     }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandPut.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandPut.java
index bac42ad4ac6..37c2934d888 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandPut.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandPut.java
@@ -24,6 +24,7 @@ import java.util.HashMap;
 
 import ch.systemsx.cisd.args4j.ExampleMode;
 import ch.systemsx.cisd.args4j.Option;
+import ch.systemsx.cisd.base.exceptions.IOExceptionUnchecked;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss;
@@ -134,7 +135,7 @@ class CommandPut extends AbstractDssCommand<CommandPut.CommandPutArguments>
         }
 
         @Override
-        protected int doExecute(IDssComponent component)
+        protected ResultCode doExecute(IDssComponent component)
         {
             try
             {
@@ -152,17 +153,16 @@ class CommandPut extends AbstractDssCommand<CommandPut.CommandPutArguments>
                     {
                         System.err.println("Data set is empty.");
                     }
-                    return -1;
+                    return ResultCode.INVALID_ARGS;
                 }
                 IDataSetDss dataSet = component.putDataSet(newDataSet, arguments.getFile());
                 System.out.println("Registered new data set " + dataSet.getCode());
             } catch (IOException e)
             {
-                e.printStackTrace();
-                return -1;
+                throw new IOExceptionUnchecked(e);
             }
 
-            return 0;
+            return ResultCode.OK;
         }
 
         private NewDataSetDTO getNewDataSet() throws IOException
@@ -218,7 +218,8 @@ class CommandPut extends AbstractDssCommand<CommandPut.CommandPutArguments>
         super(new CommandPutArguments());
     }
 
-    public int execute(String[] args) throws UserFailureException, EnvironmentFailureException
+    public ResultCode execute(String[] args) throws UserFailureException,
+            EnvironmentFailureException
     {
         return new CommandPutExecutor(arguments, this).execute(args);
     }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/ICommand.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/ICommand.java
index db6192f4376..1d61fa95c2b 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/ICommand.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/ICommand.java
@@ -25,7 +25,7 @@ import ch.systemsx.cisd.common.exceptions.UserFailureException;
  * A <code>ICommand</code> encapsulates one action that gets called on the client side using the
  * prompt or terminal window.
  * 
- * @author Bernd Rinn
+ * @author Chandrasekhar Ramakrishnan
  */
 public interface ICommand
 {
@@ -40,7 +40,7 @@ public interface ICommand
      * 
      * @return exit code, will be used in <code>System.exit()</code>.
      */
-    public int execute(final String[] args) throws UserFailureException,
+    public ResultCode execute(final String[] args) throws UserFailureException,
             EnvironmentFailureException;
 
     /**
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/ResultCode.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/ResultCode.java
new file mode 100644
index 00000000000..8831abdd367
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/ResultCode.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.dss.client.api.cli;
+
+/**
+ * @author Chandrasekhar Ramakrishnan
+ */
+public enum ResultCode
+{
+    OK(0), INVALID_ARGS(-1), INVALID_UNAME_PASS(-2), NO_CONNECTION_TO_SERVER(-3), INVALID_SESSION(
+            -4), USER_ERROR(-5), ENVIRONMENT_ERROR(-6), UNKNOWN_ERROR(-255);
+
+    private final int value;
+
+    private ResultCode(int value)
+    {
+        this.value = value;
+    }
+
+    public int getValue()
+    {
+        return value;
+    }
+}
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandGetTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandGetTest.java
index de9c382e9a0..ed24ed1f030 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandGetTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandGetTest.java
@@ -82,10 +82,10 @@ public class CommandGetTest extends AssertJUnit
             });
         ICommand command = new MockCommandGet();
 
-        int exitCode = command.execute(new String[]
+        ResultCode exitCode = command.execute(new String[]
             { "-s", "url", "-u", "user", "-p", "pswd", "ds1", "root-dir" });
 
-        assertEquals(0, exitCode);
+        assertEquals(ResultCode.OK, exitCode);
         context.assertIsSatisfied();
     }
 
@@ -109,10 +109,10 @@ public class CommandGetTest extends AssertJUnit
             });
         ICommand command = new MockCommandGet();
 
-        int exitCode = command.execute(new String[]
+        ResultCode exitCode = command.execute(new String[]
             { "-s", "url", "-u", "user", "-p", "pswd", "-l", "ds1" });
 
-        assertEquals(0, exitCode);
+        assertEquals(ResultCode.OK, exitCode);
         context.assertIsSatisfied();
     }
 }
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandLsTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandLsTest.java
index 0d0f6f26bac..c185202be85 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandLsTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandLsTest.java
@@ -80,10 +80,10 @@ public class CommandLsTest extends AssertJUnit
             });
         ICommand command = new MockCommandLs();
 
-        int exitCode = command.execute(new String[]
+        ResultCode exitCode = command.execute(new String[]
             { "-s", "url", "-u", "user", "-p", "pswd", "ds1", "root-dir" });
 
-        assertEquals(0, exitCode);
+        assertEquals(ResultCode.OK, exitCode);
         context.assertIsSatisfied();
     }
 }
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandPutTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandPutTest.java
index af420f787ec..fdf7e4514e8 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandPutTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandPutTest.java
@@ -111,12 +111,12 @@ public class CommandPutTest extends AbstractFileSystemTestCase
             });
         ICommand command = new MockCommandPut();
 
-        int exitCode =
+        ResultCode exitCode =
                 command.execute(new String[]
                     { "-s", "url", "-u", "user", "-p", "pswd", "-t", "my_type", "EXPERIMENT",
                             "/s/p/e", dataSetExample.getPath() });
 
-        assertEquals(0, exitCode);
+        assertEquals(ResultCode.OK, exitCode);
         context.assertIsSatisfied();
     }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java
index 8942e9ce8e6..322059c720a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java
@@ -144,7 +144,7 @@ public class GeneralInformationService extends AbstractServer<IGeneralInformatio
 
     public int getMinorVersion()
     {
-        return 1;
+        return 2;
     }
 
     private Map<String, List<RoleAssignmentPE>> getRoleAssignmentsPerSpace()
diff --git a/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/AbstractExecutor.java b/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/AbstractExecutor.java
index b370baa3bbd..e0a7affb4ac 100644
--- a/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/AbstractExecutor.java
+++ b/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/AbstractExecutor.java
@@ -19,6 +19,7 @@ package ch.systemsx.cisd.cina.client.util.cli;
 import ch.systemsx.cisd.args4j.CmdLineParser;
 import ch.systemsx.cisd.cina.client.util.v1.ICinaUtilities;
 import ch.systemsx.cisd.openbis.dss.client.api.cli.GlobalArguments;
+import ch.systemsx.cisd.openbis.dss.client.api.cli.ResultCode;
 
 /**
  * @author Chandrasekhar Ramakrishnan
@@ -38,7 +39,7 @@ abstract class AbstractExecutor<A extends GlobalArguments>
         parser = command.getParser();
     }
 
-    final int execute(String[] args)
+    final ResultCode execute(String[] args)
     {
         parser.parseArgument(args);
 
@@ -46,14 +47,14 @@ abstract class AbstractExecutor<A extends GlobalArguments>
         if (arguments.isHelp())
         {
             command.printUsage(System.out);
-            return 0;
+            return ResultCode.OK;
         }
 
         // Show usage and exit
         if (arguments.isComplete() == false)
         {
             command.printUsage(System.err);
-            return 1;
+            return ResultCode.INVALID_ARGS;
         }
 
         ICinaUtilities component = null;
@@ -62,7 +63,7 @@ abstract class AbstractExecutor<A extends GlobalArguments>
             component = command.login();
             if (null == component)
             {
-                return 1;
+                return ResultCode.INVALID_UNAME_PASS;
             }
             return doExecute(component);
         } finally
@@ -76,5 +77,5 @@ abstract class AbstractExecutor<A extends GlobalArguments>
 
     }
 
-    protected abstract int doExecute(ICinaUtilities component);
+    protected abstract ResultCode doExecute(ICinaUtilities component);
 }
diff --git a/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/CommandExperimentLister.java b/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/CommandExperimentLister.java
index cfbf0577a33..ef59cb78164 100644
--- a/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/CommandExperimentLister.java
+++ b/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/CommandExperimentLister.java
@@ -22,6 +22,7 @@ import ch.systemsx.cisd.cina.client.util.v1.ICinaUtilities;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.dss.client.api.cli.GlobalArguments;
+import ch.systemsx.cisd.openbis.dss.client.api.cli.ResultCode;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment;
 
 /**
@@ -68,7 +69,7 @@ public class CommandExperimentLister extends
         }
 
         @Override
-        protected int doExecute(ICinaUtilities component)
+        protected ResultCode doExecute(ICinaUtilities component)
         {
             List<Experiment> results =
                     component.listVisibleExperiments(arguments.getExperimentTypeCode());
@@ -76,7 +77,7 @@ public class CommandExperimentLister extends
             {
                 System.out.println(experiment.toString());
             }
-            return 0;
+            return ResultCode.OK;
         }
     }
 
@@ -85,7 +86,8 @@ public class CommandExperimentLister extends
         super(new CommandExperimentListerArguments());
     }
 
-    public int execute(String[] args) throws UserFailureException, EnvironmentFailureException
+    public ResultCode execute(String[] args) throws UserFailureException,
+            EnvironmentFailureException
     {
         return new ExperimentListerExecutor(this).execute(args);
     }
diff --git a/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/CommandGenerateSampleCode.java b/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/CommandGenerateSampleCode.java
index 8c52d14992e..dce46cfdf73 100644
--- a/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/CommandGenerateSampleCode.java
+++ b/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/CommandGenerateSampleCode.java
@@ -20,6 +20,7 @@ import ch.systemsx.cisd.cina.client.util.v1.ICinaUtilities;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.dss.client.api.cli.GlobalArguments;
+import ch.systemsx.cisd.openbis.dss.client.api.cli.ResultCode;
 
 /**
  * @author Chandrasekhar Ramakrishnan
@@ -65,12 +66,12 @@ public class CommandGenerateSampleCode extends
         }
 
         @Override
-        protected int doExecute(ICinaUtilities component)
+        protected ResultCode doExecute(ICinaUtilities component)
         {
             String sampleTypeCode = arguments.getSampleTypeCode();
             String result = component.generateSampleCode(sampleTypeCode);
             System.out.println(result);
-            return 0;
+            return ResultCode.OK;
         }
 
     }
@@ -80,7 +81,8 @@ public class CommandGenerateSampleCode extends
         super(new CommandGenerateSampleCodeArguments());
     }
 
-    public int execute(String[] args) throws UserFailureException, EnvironmentFailureException
+    public ResultCode execute(String[] args) throws UserFailureException,
+            EnvironmentFailureException
     {
         return new GenerateSampleIdExecutor(this).execute(args);
     }
diff --git a/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/CommandSampleLister.java b/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/CommandSampleLister.java
index 55c661f33d3..274536e75e4 100644
--- a/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/CommandSampleLister.java
+++ b/rtd_cina/source/java/ch/systemsx/cisd/cina/client/util/cli/CommandSampleLister.java
@@ -23,6 +23,7 @@ import ch.systemsx.cisd.cina.shared.constants.CinaConstants;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.openbis.dss.client.api.cli.GlobalArguments;
+import ch.systemsx.cisd.openbis.dss.client.api.cli.ResultCode;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria.MatchClause;
@@ -44,7 +45,7 @@ public class CommandSampleLister extends AbstractCinaCommand<GlobalArguments>
         }
 
         @Override
-        protected int doExecute(ICinaUtilities component)
+        protected ResultCode doExecute(ICinaUtilities component)
         {
             SearchCriteria searchCriteria = new SearchCriteria();
             searchCriteria.addMatchClause(MatchClause.createAttributeMatch(
@@ -54,7 +55,7 @@ public class CommandSampleLister extends AbstractCinaCommand<GlobalArguments>
             {
                 System.out.println(sample.toString());
             }
-            return 0;
+            return ResultCode.OK;
         }
 
     }
@@ -64,7 +65,8 @@ public class CommandSampleLister extends AbstractCinaCommand<GlobalArguments>
         super(new GlobalArguments());
     }
 
-    public int execute(String[] args) throws UserFailureException, EnvironmentFailureException
+    public ResultCode execute(String[] args) throws UserFailureException,
+            EnvironmentFailureException
     {
         return new SampleListerExecutor(this).execute(args);
     }
diff --git a/rtd_cina/sourceTest/java/ch/systemsx/cisd/cina/client/util/cli/CommandExperimentListerTest.java b/rtd_cina/sourceTest/java/ch/systemsx/cisd/cina/client/util/cli/CommandExperimentListerTest.java
new file mode 100644
index 00000000000..31ade6a1dbb
--- /dev/null
+++ b/rtd_cina/sourceTest/java/ch/systemsx/cisd/cina/client/util/cli/CommandExperimentListerTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.cina.client.util.cli;
+
+import java.util.ArrayList;
+
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.testng.AssertJUnit;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.cina.client.util.v1.ICinaUtilities;
+import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
+import ch.systemsx.cisd.openbis.dss.client.api.cli.ICommand;
+import ch.systemsx.cisd.openbis.dss.client.api.cli.ResultCode;
+import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Role;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SpaceWithProjectsAndRoleAssignments;
+
+/**
+ * @author Chandrasekhar Ramakrishnan
+ */
+public class CommandExperimentListerTest extends AssertJUnit
+{
+    private final class MockCommandExperimentLister extends CommandExperimentLister
+    {
+        @Override
+        protected ICinaUtilities login()
+        {
+            facade =
+                    ch.systemsx.cisd.cina.client.util.v1.impl.CinaUtilitiesFacadeTest.createFacade(
+                            service, openbisService, USER_ID, PASSWORD);
+            return facade;
+        }
+    }
+
+    private final static String USER_ID = "userid";
+
+    private final static String PASSWORD = "password";
+
+    private final static String SESSION_TOKEN = "sessionToken";
+
+    private Mockery context;
+
+    private ICinaUtilities facade;
+
+    private IGeneralInformationService service;
+
+    private IETLLIMSService openbisService;
+
+    @BeforeMethod
+    public void setUp()
+    {
+        context = new Mockery();
+        service = context.mock(IGeneralInformationService.class);
+        openbisService = context.mock(IETLLIMSService.class);
+    }
+
+    @AfterMethod
+    public void tearDown()
+    {
+        // To following line of code should also be called at the end of each test method.
+        // Otherwise one does not known which test failed.
+        context.assertIsSatisfied();
+    }
+
+    @Test
+    public void testCodePath()
+    {
+        context.checking(new Expectations()
+            {
+                {
+                    final ArrayList<Project> projects = new ArrayList<Project>();
+                    Project project = new Project("PROJECT-1", "SPACE-1");
+                    projects.add(project);
+
+                    final ArrayList<Experiment> experiments = new ArrayList<Experiment>();
+
+                    final ArrayList<SpaceWithProjectsAndRoleAssignments> spaces =
+                            new ArrayList<SpaceWithProjectsAndRoleAssignments>();
+                    SpaceWithProjectsAndRoleAssignments space =
+                            new SpaceWithProjectsAndRoleAssignments("SPACE-1");
+                    space.add(project);
+                    space.add("user", new Role("ADMIN", true));
+                    spaces.add(space);
+
+                    one(service).tryToAuthenticateForAllServices(USER_ID, PASSWORD);
+                    will(returnValue(SESSION_TOKEN));
+
+                    one(service).getMinorVersion();
+                    will(returnValue(2));
+
+                    one(service).listSpacesWithProjectsAndRoleAssignments(SESSION_TOKEN, null);
+                    will(returnValue(spaces));
+
+                    one(service).listExperiments(SESSION_TOKEN, projects, "EXP-TYPE");
+                    will(returnValue(experiments));
+
+                    one(service).logout(SESSION_TOKEN);
+                }
+            });
+
+        ICommand command = new MockCommandExperimentLister();
+
+        ResultCode exitCode = command.execute(new String[]
+            { "-s", "url", "-u", USER_ID, "-p", PASSWORD, "EXP-TYPE" });
+
+        assertEquals(ResultCode.OK, exitCode);
+        context.assertIsSatisfied();
+    }
+
+    @Test
+    public void testOldVersion()
+    {
+        context.checking(new Expectations()
+            {
+                {
+                    one(service).tryToAuthenticateForAllServices(USER_ID, PASSWORD);
+                    will(returnValue(SESSION_TOKEN));
+
+                    // The service used wasn't available in version 0
+                    one(service).getMinorVersion();
+                    will(returnValue(1));
+
+                    one(service).logout(SESSION_TOKEN);
+                }
+            });
+
+        ICommand command = new MockCommandExperimentLister();
+
+        try
+        {
+            command.execute(new String[]
+                { "-s", "url", "-u", USER_ID, "-p", PASSWORD, "EXP-TYPE" });
+            fail("Command should throw an exception when run against an older version of the interface.");
+        } catch (EnvironmentFailureException e)
+        {
+            assertEquals("Server does not support this feature.", e.getMessage());
+        }
+    }
+}
diff --git a/rtd_cina/sourceTest/java/ch/systemsx/cisd/cina/client/util/cli/CommandGenerateSampleCodeTest.java b/rtd_cina/sourceTest/java/ch/systemsx/cisd/cina/client/util/cli/CommandGenerateSampleCodeTest.java
index 7d47eb08ba7..fcab38fcba1 100644
--- a/rtd_cina/sourceTest/java/ch/systemsx/cisd/cina/client/util/cli/CommandGenerateSampleCodeTest.java
+++ b/rtd_cina/sourceTest/java/ch/systemsx/cisd/cina/client/util/cli/CommandGenerateSampleCodeTest.java
@@ -25,6 +25,7 @@ import org.testng.annotations.Test;
 
 import ch.systemsx.cisd.cina.client.util.v1.ICinaUtilities;
 import ch.systemsx.cisd.openbis.dss.client.api.cli.ICommand;
+import ch.systemsx.cisd.openbis.dss.client.api.cli.ResultCode;
 import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
@@ -102,10 +103,10 @@ public class CommandGenerateSampleCodeTest extends AssertJUnit
             });
         ICommand command = new MockCommandGenerateSampleCode();
 
-        int exitCode = command.execute(new String[]
+        ResultCode exitCode = command.execute(new String[]
             { "-s", "url", "-u", USER_ID, "-p", PASSWORD, sampleTypeCode });
 
-        assertEquals(0, exitCode);
+        assertEquals(ResultCode.OK, exitCode);
         context.assertIsSatisfied();
     }
 
@@ -120,10 +121,10 @@ public class CommandGenerateSampleCodeTest extends AssertJUnit
             });
         ICommand command = new MockCommandGenerateSampleCode();
 
-        int exitCode = command.execute(new String[]
+        ResultCode exitCode = command.execute(new String[]
             { "-s", "url", "-u", USER_ID, "-p", PASSWORD });
 
-        assertEquals(1, exitCode);
+        assertEquals(ResultCode.INVALID_ARGS, exitCode);
         context.assertIsSatisfied();
     }
 }
diff --git a/rtd_cina/sourceTest/java/ch/systemsx/cisd/cina/client/util/cli/CommandSampleListerTest.java b/rtd_cina/sourceTest/java/ch/systemsx/cisd/cina/client/util/cli/CommandSampleListerTest.java
index fd90d70bf03..c0ee28ceda5 100644
--- a/rtd_cina/sourceTest/java/ch/systemsx/cisd/cina/client/util/cli/CommandSampleListerTest.java
+++ b/rtd_cina/sourceTest/java/ch/systemsx/cisd/cina/client/util/cli/CommandSampleListerTest.java
@@ -30,6 +30,7 @@ import ch.systemsx.cisd.cina.client.util.v1.ICinaUtilities;
 import ch.systemsx.cisd.cina.shared.constants.CinaConstants;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.openbis.dss.client.api.cli.ICommand;
+import ch.systemsx.cisd.openbis.dss.client.api.cli.ResultCode;
 import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Sample;
@@ -111,10 +112,10 @@ public class CommandSampleListerTest extends AssertJUnit
 
         ICommand command = new MockCommandSampleLister();
 
-        int exitCode = command.execute(new String[]
+        ResultCode exitCode = command.execute(new String[]
             { "-s", "url", "-u", USER_ID, "-p", PASSWORD });
 
-        assertEquals(0, exitCode);
+        assertEquals(ResultCode.OK, exitCode);
         context.assertIsSatisfied();
     }
 
@@ -124,10 +125,6 @@ public class CommandSampleListerTest extends AssertJUnit
         context.checking(new Expectations()
             {
                 {
-                    final SearchCriteria searchCriteria = new SearchCriteria();
-                    searchCriteria.addMatchClause(MatchClause.createAttributeMatch(
-                            MatchClauseAttribute.TYPE, CinaConstants.REPLICA_SAMPLE_TYPE_CODE));
-
                     one(service).tryToAuthenticateForAllServices(USER_ID, PASSWORD);
                     will(returnValue(SESSION_TOKEN));
 
-- 
GitLab