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