From f495281a7f30446e6d140d5e157705e0dabc2e88 Mon Sep 17 00:00:00 2001
From: cramakri <cramakri>
Date: Tue, 30 Mar 2010 08:59:21 +0000
Subject: [PATCH] LMS-1465 Skeleton of an implementation of RPC for DSS.

SVN: 15311
---
 .../openbis/dss/rpc/client/DssComponent.java  | 197 ++++++++++++++++++
 .../openbis/dss/rpc/client/IDssComponent.java |  64 ++++++
 .../cisd/openbis/dss/rpc/server/.gitignore    |   0
 .../openbis/dss/rpc/shared/FileInfoDss.java   |  30 +++
 .../openbis/dss/rpc/shared/IDataSetDss.java   |  48 +++++
 .../dss/rpc/shared/IDssServiceRpc.java        |  42 ++++
 .../dss/rpc/shared/IDssServiceRpcV1.java      |  34 +++
 .../dss/rpc/client/DssComponentTest.java      |  97 +++++++++
 8 files changed, 512 insertions(+)
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/client/DssComponent.java
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/client/IDssComponent.java
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/server/.gitignore
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/FileInfoDss.java
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDataSetDss.java
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDssServiceRpc.java
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDssServiceRpcV1.java
 create mode 100644 datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/rpc/client/DssComponentTest.java

diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/client/DssComponent.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/client/DssComponent.java
new file mode 100644
index 00000000000..5931ee076ad
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/client/DssComponent.java
@@ -0,0 +1,197 @@
+/*
+ * 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.rpc.client;
+
+import ch.systemsx.cisd.common.exceptions.AuthorizationFailureException;
+import ch.systemsx.cisd.common.exceptions.InvalidSessionException;
+import ch.systemsx.cisd.common.spring.HttpInvokerUtils;
+import ch.systemsx.cisd.openbis.dss.rpc.shared.IDataSetDss;
+import ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException;
+import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SessionContextDTO;
+
+/**
+ * Implementation of the IDssComponent interface. It is a facade for interacting with openBIS and
+ * multiple DSS servers.
+ * 
+ * @author Chandrasekhar Ramakrishnan
+ */
+public class DssComponent implements IDssComponent
+{
+    final IETLLIMSService service;
+
+    AbstractDssComponentState state;
+
+    SessionContextDTO sessionOrNull;
+
+    /**
+     * Create a DSS component that connects to the openBIS instance specified by the URL.
+     * <p>
+     * The DSS component needs to connect to openBIS to find out which DSS manages a given data set.
+     * Once it has a connection to openBIS, it can figure out how to connect to DSS servers itself.
+     * 
+     * @param openBISURL The url to connect to openBIS
+     */
+    public DssComponent(String openBISURL)
+    {
+        this(HttpInvokerUtils.createServiceStub(IETLLIMSService.class, openBISURL + "/rmi-etl", 5));
+    }
+
+    /**
+     * Internal constructor used for testing.
+     * 
+     * @param service
+     */
+    protected DssComponent(IETLLIMSService service)
+    {
+        this.service = service;
+        this.state = new UnauthenticatedState(service);
+    }
+
+    public void login(String user, String password) throws AuthorizationFailureException
+    {
+        // login and transition to the authenticated state
+        state.login(user, password);
+        state = new AuthenticatedState(service, state.getSession());
+    }
+
+    public void checkSession() throws InvalidSessionException
+    {
+        state.checkSession();
+    }
+
+    public IDataSetDss getDataSet(String code)
+    {
+        return state.getDataSet(code);
+    }
+
+    public void logout()
+    {
+        // logout and transition to the unauthenticated state
+        state.logout();
+        state = new UnauthenticatedState(service);
+    }
+}
+
+/**
+ * Superclass for component states, which make the state machine of the DSS component explicit.
+ * <p>
+ * By default, all methods just throw an exception. Subclasses should override the methods they
+ * accept.
+ * 
+ * @author Chandrasekhar Ramakrishnan
+ */
+abstract class AbstractDssComponentState implements IDssComponent
+{
+    protected final IETLLIMSService service;
+
+    AbstractDssComponentState(IETLLIMSService service)
+    {
+        this.service = service;
+    }
+
+    public void checkSession() throws InvalidSessionException
+    {
+        throw new UserFailureException("Please log in");
+    }
+
+    public IDataSetDss getDataSet(String code)
+    {
+        throw new UserFailureException("Please log in");
+    }
+
+    abstract SessionContextDTO getSession();
+}
+
+/**
+ * An object representing an unauthenticated state. Being in this state implies that the user has
+ * not yet logged in. Only login and logout are allowed in this state.
+ * 
+ * @author Chandrasekhar Ramakrishnan
+ */
+class UnauthenticatedState extends AbstractDssComponentState
+{
+    private SessionContextDTO sessionOrNull;
+
+    UnauthenticatedState(IETLLIMSService service)
+    {
+        super(service);
+    }
+
+    public void login(String user, String password) throws AuthorizationFailureException
+    {
+        sessionOrNull = service.tryToAuthenticate(user, password);
+        if (sessionOrNull == null)
+            throw new AuthorizationFailureException("Login or Password invalid");
+    }
+
+    public void logout()
+    {
+        return;
+    }
+
+    @Override
+    SessionContextDTO getSession()
+    {
+        if (sessionOrNull == null)
+            throw new UserFailureException("Please log in");
+        return sessionOrNull;
+    }
+}
+
+class AuthenticatedState extends AbstractDssComponentState
+{
+
+    final SessionContextDTO session;
+
+    /**
+     * @param service
+     */
+    AuthenticatedState(IETLLIMSService service, SessionContextDTO session)
+    {
+        super(service);
+        this.session = session;
+    }
+
+    @Override
+    SessionContextDTO getSession()
+    {
+        return session;
+    }
+
+    public void login(String user, String password) throws AuthorizationFailureException
+    {
+        throw new UserFailureException("Already logged in.");
+    }
+
+    public void logout()
+    {
+        service.logout(session.getSessionToken());
+    }
+
+    @Override
+    public IDataSetDss getDataSet(String code)
+    {
+        service.tryGetDataSet(session.getSessionToken(), code);
+        // Contact openBIS to find out which DSS server manages the data set
+        // Get an RPC service for the DSS server
+        // Get a proxy to the data set
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/client/IDssComponent.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/client/IDssComponent.java
new file mode 100644
index 00000000000..b451d4536cb
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/client/IDssComponent.java
@@ -0,0 +1,64 @@
+/*
+ * 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.rpc.client;
+
+import ch.systemsx.cisd.common.exceptions.AuthorizationFailureException;
+import ch.systemsx.cisd.common.exceptions.InvalidSessionException;
+import ch.systemsx.cisd.openbis.dss.rpc.shared.IDataSetDss;
+
+/**
+ * A component that manages a connection to openBIS and 1 or more data store servers.
+ * <p>
+ * The component is a kind of state machine. In the initial state, only login is allowed. After
+ * login, other operations may be called. Thus clients should follow the following usage pattern:
+ * <ol>
+ * <li>login</li>
+ * <li>...do stuff...</li>
+ * <li>logout</li>
+ * </ol>
+ * <p>
+ * The IDssComponent itself is designed to be used in a single thread, though it may return objects
+ * that can be used in multiple threads.
+ * 
+ * @author Chandrasekhar Ramakrishnan
+ */
+public interface IDssComponent
+{
+    /**
+     * Authenticates the <code>user</code> with given <code>password</code>.
+     */
+    public void login(final String user, final String password)
+            throws AuthorizationFailureException;
+
+    /**
+     * Checks whether the session is alive.
+     * 
+     * @throws InvalidSessionException If the session is not alive.
+     */
+    public void checkSession() throws InvalidSessionException;
+
+    /**
+     * Get a proxy to the data set designated by the given data set code.
+     */
+    public IDataSetDss getDataSet(String code);
+
+    /**
+     * Logs the current user out.
+     */
+    public void logout();
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/server/.gitignore b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/server/.gitignore
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/FileInfoDss.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/FileInfoDss.java
new file mode 100644
index 00000000000..87c2fe5f5bd
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/FileInfoDss.java
@@ -0,0 +1,30 @@
+/*
+ * 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.rpc.shared;
+
+import java.io.Serializable;
+
+/**
+ * Represents information about a file stored in DSS.
+ * 
+ * @author Chandrasekhar Ramakrishnan
+ */
+public class FileInfoDss implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDataSetDss.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDataSetDss.java
new file mode 100644
index 00000000000..306b402718a
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDataSetDss.java
@@ -0,0 +1,48 @@
+/*
+ * 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.rpc.shared;
+
+import java.io.OutputStream;
+
+import ch.systemsx.cisd.common.exceptions.InvalidSessionException;
+
+/**
+ * The representation of a Data Set managed by a DSS server. It is safe to use instances in multiple
+ * threads.
+ * 
+ * @author Chandrasekhar Ramakrishnan
+ */
+public interface IDataSetDss
+{
+    /**
+     * List files contained in this data set.
+     * 
+     * @param startPath The path for the listing. "/" is the root of the hierarchy for this data
+     *            set.
+     * @param isRecursive If true, the contents of any subdirectories will be listed as well.
+     */
+    public FileInfoDss[] listFiles(String startPath, boolean isRecursive)
+            throws InvalidSessionException;
+
+    /**
+     * Get a file contained in this data set.
+     * 
+     * @param path The path of the file to retrieve.
+     */
+    public OutputStream getFile(String path) throws InvalidSessionException;
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDssServiceRpc.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDssServiceRpc.java
new file mode 100644
index 00000000000..7ccae14d91b
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDssServiceRpc.java
@@ -0,0 +1,42 @@
+/*
+ * 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.rpc.shared;
+
+
+/**
+ * The most generic interface for RPC invocations into DSS.
+ * <p>
+ * This interface defines a minimal interface presented by DSS and is not useful for clients.
+ * Clients should use a versioned interface, e.g., IDssServiceRpcV1.
+ * 
+ * @author Chandrasekhar Ramakrishnan
+ */
+public interface IDssServiceRpc
+{
+    //
+    // Protocol versioning
+    //
+    /** Returns the version of the server side interface. */
+    public int getVersion();
+
+    /**
+     * Returns the minimal version that the client needs to have in order to be able to talk to this
+     * server.
+     */
+    public int getMinClientVersion();
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDssServiceRpcV1.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDssServiceRpcV1.java
new file mode 100644
index 00000000000..30cbca74053
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDssServiceRpcV1.java
@@ -0,0 +1,34 @@
+/*
+ * 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.rpc.shared;
+
+/**
+ * @author Chandrasekhar Ramakrishnan
+ */
+public interface IDssServiceRpcV1 extends IDssServiceRpc
+{
+    //
+    // Protocol versioning
+    //
+    /** The version of this service interface. */
+    public static final int VERSION = 1;
+
+    /**
+     * Get a proxy to the data set object managed by the data store server.
+     */
+    public IDataSetDss getDataSet(String sessionId, String code);
+}
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/rpc/client/DssComponentTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/rpc/client/DssComponentTest.java
new file mode 100644
index 00000000000..09591ae7026
--- /dev/null
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/rpc/client/DssComponentTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.rpc.client;
+
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.testng.AssertJUnit;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.openbis.dss.rpc.client.DssComponent;
+import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SessionContextDTO;
+
+/**
+ * @author Chandrasekhar Ramakrishnan
+ */
+public class DssComponentTest extends AssertJUnit
+{
+    private Mockery context;
+
+    private IETLLIMSService service;
+
+    private DssComponent dssComponent;
+
+    private static final String DUMMY_SESSSION_TOKEN = "DummySessionToken";
+
+    public DssComponentTest()
+    {
+
+    }
+
+    @BeforeMethod
+    public void setUp()
+    {
+        context = new Mockery();
+        service = context.mock(IETLLIMSService.class);
+        dssComponent = new DssComponent(service);
+    }
+
+    @Test
+    public void testLogin()
+    {
+        final SessionContextDTO session = getDummySession();
+
+        context.checking(new Expectations()
+            {
+                {
+                    one(service).tryToAuthenticate("foo", "bar");
+                    will(returnValue(session));
+                }
+            });
+
+        dssComponent.login("foo", "bar");
+    }
+
+    @Test
+    public void testGetDataSet()
+    {
+        final SessionContextDTO session = getDummySession();
+
+        context.checking(new Expectations()
+            {
+                {
+                    one(service).tryToAuthenticate("foo", "bar");
+                    will(returnValue(session));
+                    one(service).tryGetDataSet(DUMMY_SESSSION_TOKEN, "DummyDataSetCode");
+                    will(returnValue(new ExternalData()));
+                }
+            });
+
+        dssComponent.login("foo", "bar");
+        dssComponent.getDataSet("DummyDataSetCode");
+    }
+
+    private SessionContextDTO getDummySession()
+    {
+        final SessionContextDTO session = new SessionContextDTO();
+        session.setSessionToken(DUMMY_SESSSION_TOKEN);
+        return session;
+    }
+}
-- 
GitLab