From 4899a0694b6f34a1fba9eda9fb84f151e7d57c27 Mon Sep 17 00:00:00 2001
From: brinn <brinn>
Date: Wed, 4 Aug 2010 17:56:04 +0000
Subject: [PATCH] add: a way to login to the openBIS server that doesn't leave
 the user's password in the Matlab command history

SVN: 17344
---
 screening/source/java/OpenBISML.java          |  72 +++++-
 .../plugin/screening/client/cli/Login.java    | 221 ++++++++++++++++++
 2 files changed, 286 insertions(+), 7 deletions(-)
 create mode 100644 screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/cli/Login.java

diff --git a/screening/source/java/OpenBISML.java b/screening/source/java/OpenBISML.java
index 4da3088323e..3ea9a7b234b 100644
--- a/screening/source/java/OpenBISML.java
+++ b/screening/source/java/OpenBISML.java
@@ -15,9 +15,11 @@
  */
 
 import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
+import java.io.FileReader;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
@@ -30,6 +32,7 @@ import java.util.Map;
 import ch.systemsx.cisd.openbis.plugin.screening.client.api.v1.IScreeningOpenbisServiceFacade;
 import ch.systemsx.cisd.openbis.plugin.screening.client.api.v1.ScreeningOpenbisServiceFacadeFactory;
 import ch.systemsx.cisd.openbis.plugin.screening.client.api.v1.ScreeningOpenbisServiceFacade.IImageOutputStreamProvider;
+import ch.systemsx.cisd.openbis.plugin.screening.client.cli.Login;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.ExperimentIdentifier;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVectorDatasetReference;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.FeatureVectorWithDescription;
@@ -43,8 +46,8 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.PlateImageRef
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.WellPosition;
 
 /**
- * Simple Matlab interface for openBIS for Screening. It is meant to be used in one Matlab
- * session at a time, i.e. it is <i>not</i> multi-threading safe.
+ * Simple Matlab interface for openBIS for Screening. It is meant to be used in one Matlab session
+ * at a time, i.e. it is <i>not</i> multi-threading safe.
  * <p>
  * While written in Java, the API is idiomatic for Matlab, i.e. values are returned as
  * multi-dimensional arrays. For the <code>get...</code> and <code>load...</code> methods the first
@@ -66,6 +69,11 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.WellPosition;
  * OpenBISML.logout()
  * </pre>
  * 
+ * <i>Note: using this login your password will end up in the Matlab command history. An alternative
+ * that avoids this is to call the
+ * {@link ch.systemsx.cisd.openbis.plugin.screening.client.cli.Login} class. Logging in on the
+ * console will grant this class access to the openBIS server.</i>
+ * 
  * @author Bernd Rinn
  */
 public class OpenBISML
@@ -88,7 +96,7 @@ public class OpenBISML
     {
         // Not to be constructed.
     }
-    
+
     //
     // Versioning
     //
@@ -97,14 +105,14 @@ public class OpenBISML
      * The version of the API.
      */
     public static final String VERSION = "1";
-    
+
     /**
-     * The required version ("major.minor") of the screening API on the openBIS application server. 
+     * The required version ("major.minor") of the screening API on the openBIS application server.
      */
     public static final String REQUIRES_OPENBIS_AS_API = "1.2";
 
     /**
-     * The required version ("major.minor") of the screening API on the openBIS datastore server. 
+     * The required version ("major.minor") of the screening API on the openBIS datastore server.
      */
     public static final String REQUIRES_OPENBIS_DSS_API = "1.1";
 
@@ -132,6 +140,11 @@ public class OpenBISML
         {
             throw new RuntimeException("Login failed.");
         }
+        init();
+    }
+
+    private static void init()
+    {
         experiments = openbis.listExperiments();
         experimentCodeToExperimentMap.clear();
         for (ExperimentIdentifier e : experiments)
@@ -172,6 +185,10 @@ public class OpenBISML
             return;
         }
         openbis.logout();
+        if (Login.OPENBIS_TOKEN_FILE.exists())
+        {
+            Login.OPENBIS_TOKEN_FILE.delete();
+        }
         openbis = null;
     }
 
@@ -944,7 +961,48 @@ public class OpenBISML
     {
         if (openbis == null)
         {
-            throw new RuntimeException("Not logged in.");
+            if (Login.OPENBIS_TOKEN_FILE.exists())
+            {
+                BufferedReader br = null;
+                try
+                {
+                    br = new BufferedReader(new FileReader(Login.OPENBIS_TOKEN_FILE));
+                    final String token = br.readLine();
+                    br.close();
+                    br = new BufferedReader(new FileReader(Login.OPENBIS_SERVER_URL_FILE));
+                    final String serverUrl = br.readLine();
+                    br.close();
+                    br = null;
+                    openbis = ScreeningOpenbisServiceFacadeFactory.tryCreate(token, serverUrl);
+                    if (openbis == null)
+                    {
+                        throw new RuntimeException("Login failed.");
+                    }
+                    init();
+                } catch (IOException ex)
+                {
+                    if (openbis == null)
+                    {
+                        throw new RuntimeException("Login failed.", ex);
+                    }
+                } finally
+                {
+                    if (br != null)
+                    {
+                        try
+                        {
+                            br.close();
+                        } catch (IOException ex)
+                        {
+                            // Silence this.
+                        }
+                    }
+                }
+            }
+            if (openbis == null)
+            {
+                throw new RuntimeException("Not logged in.");
+            }
         }
     }
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/cli/Login.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/cli/Login.java
new file mode 100644
index 00000000000..a433b2c64ad
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/cli/Login.java
@@ -0,0 +1,221 @@
+/*
+ * 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.plugin.screening.client.cli;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.varia.NullAppender;
+
+import jline.ConsoleReader;
+
+import ch.systemsx.cisd.args4j.Argument;
+import ch.systemsx.cisd.args4j.CmdLineParser;
+import ch.systemsx.cisd.args4j.Option;
+import ch.systemsx.cisd.openbis.plugin.screening.client.api.v1.IScreeningOpenbisServiceFacade;
+import ch.systemsx.cisd.openbis.plugin.screening.client.api.v1.ScreeningOpenbisServiceFacadeFactory;
+
+/**
+ * A class to provide a login on an openBIS screening server that can be used by the Matlab API.
+ * 
+ * @author Bernd Rinn
+ */
+public class Login
+{
+    private final static File OPENBIS_DIR = new File(System.getProperty("user.home"), ".openbis");
+
+    public final static File OPENBIS_TOKEN_FILE = new File(OPENBIS_DIR, "session-token");
+
+    public final static File OPENBIS_USER_FILE = new File(OPENBIS_DIR, "user");
+
+    public final static File OPENBIS_SERVER_URL_FILE = new File(OPENBIS_DIR, "server");
+
+    private static class Parameters
+    {
+        private final CmdLineParser parser;
+
+        @Argument()
+        private final List<String> args = new ArrayList<String>();
+
+        @Option(name = "u", longName = "user")
+        private String user;
+
+        @Option(name = "s", longName = "server")
+        private String server;
+
+        Parameters(String[] args)
+        {
+            parser = new CmdLineParser(this);
+            try
+            {
+                parser.parseArgument(args);
+
+                if (server == null)
+                {
+                    if (OPENBIS_SERVER_URL_FILE.exists())
+                    {
+                        BufferedReader br = null;
+                        try
+                        {
+                            br = new BufferedReader(new FileReader(Login.OPENBIS_SERVER_URL_FILE));
+                            server = br.readLine();
+                            br.close();
+                        } finally
+                        {
+                            closeQuietly(br);
+                        }
+                    } else
+                    {
+                        server = new ConsoleReader().readLine("Server URL: ");
+                    }
+                }
+
+                if (user == null)
+                {
+                    if (OPENBIS_USER_FILE.exists())
+                    {
+                        BufferedReader br = null;
+                        try
+                        {
+                            br = new BufferedReader(new FileReader(OPENBIS_USER_FILE));
+                            user = br.readLine();
+                            br.close();
+                        } finally
+                        {
+                            closeQuietly(br);
+                        }
+                    } else
+                    {
+                        user = new ConsoleReader().readLine("User: ");
+                    }
+                }
+            } catch (final Exception ex)
+            {
+                throw new RuntimeException(ex.getMessage(), ex);
+            }
+        }
+
+        @SuppressWarnings("unused")
+        public List<String> getArgs()
+        {
+            return Collections.unmodifiableList(args);
+        }
+
+        public String getUser()
+        {
+            return user;
+        }
+
+        public String getServer()
+        {
+            return server;
+        }
+
+    }
+
+    private static void closeQuietly(Closeable closeable)
+    {
+        if (closeable != null)
+        {
+            try
+            {
+                closeable.close();
+            } catch (IOException ex)
+            {
+                // Silence this.
+            }
+        }
+    }
+
+    private static void write(String server, String user, String token)
+    {
+        BufferedWriter bw = null;
+        try
+        {
+            if (OPENBIS_DIR.exists() == false)
+            {
+                OPENBIS_DIR.mkdir();
+            }
+            bw = new BufferedWriter(new FileWriter(OPENBIS_SERVER_URL_FILE));
+            bw.write(server);
+            bw.close();
+            bw = new BufferedWriter(new FileWriter(OPENBIS_USER_FILE));
+            bw.write(user);
+            bw.close();
+            bw = new BufferedWriter(new FileWriter(OPENBIS_TOKEN_FILE));
+            bw.write(token);
+        } catch (Exception ex)
+        {
+            throw new RuntimeException(ex);
+        } finally
+        {
+            closeQuietly(bw);
+        }
+
+    }
+
+    public static void main(String[] args) throws IOException
+    {
+        BasicConfigurator.configure(new NullAppender());
+        try
+        {
+            final Parameters params = new Parameters(args);
+            if (params.getServer() == null)
+            {
+                throw new RuntimeException("Server not specified (give '-s').");
+            }
+            if (params.getUser() == null)
+            {
+                throw new RuntimeException("User not specified (give '-u').");
+            }
+            final String password =
+                    new ConsoleReader().readLine("Password: ", Character.valueOf('*'));
+            if (password == null || password.length() == 0)
+            {
+                throw new RuntimeException("Password empty.");
+            }
+            final IScreeningOpenbisServiceFacade service =
+                    ScreeningOpenbisServiceFacadeFactory.tryCreate(params.getUser(), password,
+                            params.getServer());
+            if (service == null)
+            {
+                throw new RuntimeException("Login failed.");
+            }
+            final String token = service.getSessionToken();
+            write(params.getServer(), params.getUser(), token);
+        } catch (RuntimeException ex)
+        {
+            String msg = ex.getMessage();
+            if (msg == null && ex.getCause() != null)
+            {
+                msg = ex.getCause().getClass().getSimpleName() + ": " + ex.getMessage();
+            }
+            System.err.println(msg);
+            System.exit(1);
+        }
+    }
+
+}
-- 
GitLab