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