diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/AbstractCommand.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/AbstractCommand.java similarity index 91% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/AbstractCommand.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/AbstractCommand.java index cb6c24fe450ab2c10a4e7b76c3e4b0156c463477..9ad21efd50b63cf54a2ce0558b1a25a05c94bada 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/AbstractCommand.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/AbstractCommand.java @@ -14,15 +14,15 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.client.cli; +package ch.systemsx.cisd.openbis.dss.client.api.cli; import java.io.PrintStream; import ch.systemsx.cisd.args4j.CmdLineParser; import ch.systemsx.cisd.args4j.ExampleMode; -import ch.systemsx.cisd.openbis.dss.api.v1.client.DssComponentFactory; -import ch.systemsx.cisd.openbis.dss.api.v1.client.IDataSetDss; -import ch.systemsx.cisd.openbis.dss.api.v1.client.IDssComponent; +import ch.systemsx.cisd.openbis.dss.client.api.v1.DssComponentFactory; +import ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss; +import ch.systemsx.cisd.openbis.dss.client.api.v1.IDssComponent; /** * Superclass for dss command-line client commands. diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/CommandFactory.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandFactory.java similarity index 97% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/CommandFactory.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandFactory.java index 1233e5f4235a98d3cbdd64a869d8b0a84c8bfaa1..69a85b4293c31239858628cc7b3aced7114a08fe 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/CommandFactory.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.client.cli; +package ch.systemsx.cisd.openbis.dss.client.api.cli; import java.util.Arrays; import java.util.List; diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/CommandGet.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandGet.java similarity index 95% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/CommandGet.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandGet.java index 1f07138eb418015df9c0edf4c3478d1d60358989..c121be4bae4fd44b376cfa0cb5a73972a45ea95b 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/CommandGet.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandGet.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.client.cli; +package ch.systemsx.cisd.openbis.dss.client.api.cli; import java.io.File; import java.io.FileOutputStream; @@ -28,9 +28,9 @@ 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.api.v1.client.IDataSetDss; -import ch.systemsx.cisd.openbis.dss.api.v1.client.IDssComponent; -import ch.systemsx.cisd.openbis.dss.api.v1.shared.FileInfoDssDTO; +import ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss; +import ch.systemsx.cisd.openbis.dss.client.api.v1.IDssComponent; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO; /** * Comand that lists files in the data set. diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/CommandHelp.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandHelp.java similarity index 97% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/CommandHelp.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandHelp.java index 9d08c9e4b198d65b0bd1afcf8648aa60a89b91fd..c322746882e4809200ed6c211e8ffec18d541aea 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/CommandHelp.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandHelp.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.client.cli; +package ch.systemsx.cisd.openbis.dss.client.api.cli; import java.io.PrintStream; import java.util.List; diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/CommandLs.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandLs.java similarity index 93% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/CommandLs.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandLs.java index 1cb6c01c6446f6ca8db106921a83ba09a5d34a12..0e628533b885ff0c3faa337aa0336e764bb5ae5c 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/CommandLs.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandLs.java @@ -14,15 +14,15 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.client.cli; +package ch.systemsx.cisd.openbis.dss.client.api.cli; import ch.systemsx.cisd.args4j.CmdLineParser; import ch.systemsx.cisd.args4j.Option; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; import ch.systemsx.cisd.common.exceptions.UserFailureException; -import ch.systemsx.cisd.openbis.dss.api.v1.client.IDataSetDss; -import ch.systemsx.cisd.openbis.dss.api.v1.client.IDssComponent; -import ch.systemsx.cisd.openbis.dss.api.v1.shared.FileInfoDssDTO; +import ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss; +import ch.systemsx.cisd.openbis.dss.client.api.v1.IDssComponent; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO; /** * Comand that lists files in the data set. diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/DssClient.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/DssClient.java similarity index 99% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/DssClient.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/DssClient.java index 226e493b775be0e9e1ee617dfaf576127ce624ea..ea3cc23dd303728f9505f03df038dede9af92f3b 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/DssClient.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/DssClient.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.client.cli; +package ch.systemsx.cisd.openbis.dss.client.api.cli; import java.net.UnknownHostException; import java.util.Arrays; diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/GlobalArguments.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/GlobalArguments.java similarity index 98% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/GlobalArguments.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/GlobalArguments.java index d5ef4679332d0f765a1aabfa355ac1dbf85f6c3e..049957a324ee3c6891ab97ca5038fdc1306c1f9d 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/GlobalArguments.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/GlobalArguments.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.client.cli; +package ch.systemsx.cisd.openbis.dss.client.api.cli; import java.util.ArrayList; import java.util.List; diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/ICommand.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/ICommand.java similarity index 97% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/ICommand.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/ICommand.java index 6b9932157df358b957db074d0b9b3e51ec317cfd..f82aec03aac56b28324fc662d5c7a1f89506fb59 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/client/cli/ICommand.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/cli/ICommand.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.client.cli; +package ch.systemsx.cisd.openbis.dss.client.api.cli; import java.io.PrintStream; diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/client/DssComponentFactory.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/DssComponentFactory.java similarity index 93% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/client/DssComponentFactory.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/DssComponentFactory.java index 3a847ec49a2d19e7b91ad827facde31256551a03..3d0d2526035b902917be3603a8871736d9316e19 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/client/DssComponentFactory.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/DssComponentFactory.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.v1.client; +package ch.systemsx.cisd.openbis.dss.client.api.v1; -import ch.systemsx.cisd.openbis.dss.api.v1.client.impl.DssComponent; +import ch.systemsx.cisd.openbis.dss.client.api.v1.impl.DssComponent; /** * A class that creates DssComponents. diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/client/IDataSetDss.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/IDataSetDss.java similarity index 93% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/client/IDataSetDss.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/IDataSetDss.java index e15176134fee4f85a40ae36d2d8677e504be5375..c53889d9389ff93c864b049d1c327e73d4596e11 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/client/IDataSetDss.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/IDataSetDss.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.v1.client; +package ch.systemsx.cisd.openbis.dss.client.api.v1; import java.io.InputStream; import ch.systemsx.cisd.common.exceptions.InvalidSessionException; -import ch.systemsx.cisd.openbis.dss.api.v1.shared.FileInfoDssDTO; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO; /** * The representation of a Data Set managed by a DSS server. It is safe to use instances in multiple diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/client/IDssComponent.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/IDssComponent.java similarity index 97% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/client/IDssComponent.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/IDssComponent.java index 2c1d2eea9f9f1c6f6b4de1d0026c317c2798a89b..b5e8491c652af4672a0ef59a4ca0c0f5d7920625 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/client/IDssComponent.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/IDssComponent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.v1.client; +package ch.systemsx.cisd.openbis.dss.client.api.v1; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; import ch.systemsx.cisd.common.exceptions.InvalidSessionException; diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DataSetDss.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DataSetDss.java new file mode 100644 index 0000000000000000000000000000000000000000..a37ebd94eada96c6a771019cbcefd2169a61de7a --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DataSetDss.java @@ -0,0 +1,68 @@ +/* + * 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.v1.impl; + +import java.io.InputStream; + +import ch.systemsx.cisd.common.exceptions.InvalidSessionException; +import ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.IDssServiceRpcGeneric; + +/** + * @author Chandrasekhar Ramakrishnan + */ +public class DataSetDss implements IDataSetDss +{ + private final String code; + + private final IDssServiceRpcGeneric service; + + private final AuthenticatedState parent; + + // private String ownerUrl; + + public DataSetDss(String code, IDssServiceRpcGeneric service, AuthenticatedState parent) + { + this.code = code; + this.service = service; + this.parent = parent; + } + + public String getCode() + { + return code; + } + + public InputStream getFile(String path) throws IllegalArgumentException, + InvalidSessionException + { + return parent.getFile(this, path); + } + + public FileInfoDssDTO[] listFiles(String startPath, boolean isRecursive) + throws IllegalArgumentException, InvalidSessionException + { + return parent.listFiles(this, startPath, isRecursive); + } + + IDssServiceRpcGeneric getService() + { + return service; + } + +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssComponent.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..735f111aed0cf86e7d0ff192406d1700474532a0 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssComponent.java @@ -0,0 +1,426 @@ +/* + * 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.v1.impl; + +import java.io.InputStream; +import java.util.Collection; + +import org.springframework.remoting.RemoteAccessException; +import org.springframework.remoting.RemoteConnectFailureException; + +import ch.systemsx.cisd.common.api.IRpcServiceFactory; +import ch.systemsx.cisd.common.api.RpcServiceInterfaceDTO; +import ch.systemsx.cisd.common.api.RpcServiceInterfaceVersionDTO; +import ch.systemsx.cisd.common.exceptions.AuthorizationFailureException; +import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; +import ch.systemsx.cisd.common.exceptions.InvalidSessionException; +import ch.systemsx.cisd.common.spring.HttpInvokerUtils; +import ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss; +import ch.systemsx.cisd.openbis.dss.client.api.v1.IDssComponent; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.IDssServiceRpcGeneric; +import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService; +import ch.systemsx.cisd.openbis.generic.shared.OpenBisServiceFactory; +import ch.systemsx.cisd.openbis.generic.shared.OpenBisServiceFactory.ILimsServiceStubFactory; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataStore; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData; +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. + * <p> + * The DssComponent manages a connection to openBIS (IETLLIMSService) as well as connections to data + * store servers (IDssServiceRpc) to present a simplified interface to downloading datasets. + * + * @author Chandrasekhar Ramakrishnan + */ +public class DssComponent implements IDssComponent +{ + private static final int SERVER_TIMEOUT_MIN = 5; + + private final IETLLIMSService openBisService; + + private final IRpcServiceFactory dssServiceFactory; + + private AbstractDssComponentState state; + + /** + * Public factory method for creating a DssComponent with a username and password. + * + * @param user The user name + * @param password The user's password + * @param openBISUrl The URL to openBIS + */ + public static DssComponent tryCreate(String user, String password, String openBISUrl) + { + DssComponent component = new DssComponent(openBISUrl, null); + try + { + component.login(user, password); + } catch (AuthorizationFailureException e) + { + // User name / Password is incorrect. + return null; + } + return component; + } + + /** + * Public factory method for creating a DssComponent for a user that has already been + * authenticated. + * + * @param sessionToken The session token provided by authentication + * @param openBISUrl The URL to openBIS + */ + public static DssComponent tryCreate(String sessionToken, String openBISUrl) + { + DssComponent component = new DssComponent(openBISUrl, sessionToken); + try + { + component.checkSession(); + } catch (InvalidSessionException e) + { + // Session has expired + return null; + } + return component; + } + + private static IETLLIMSService createOpenBisService(String openBISURL) + { + ILimsServiceStubFactory stubFactory = new ILimsServiceStubFactory() + { + public IETLLIMSService createServiceStub(String serverUrl) + { + return HttpInvokerUtils.createServiceStub(IETLLIMSService.class, serverUrl, + SERVER_TIMEOUT_MIN); + } + + }; + return new OpenBisServiceFactory(openBISURL, stubFactory).createService(); + } + + /** + * 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 + * @param sessionTokenOrNull A session token; If null is passed in, then login needs to be + * called. + */ + private DssComponent(String openBISURL, String sessionTokenOrNull) + { + this(createOpenBisService(openBISURL), new DssServiceRpcFactory(), sessionTokenOrNull); + } + + /** + * Internal constructor, also used for testing. + * + * @param service A proxy to the openBIS application server. + * @param dssServiceFactory A proxy to the DSS server. + * @param sessionTokenOrNull A session token, if the user has already logged in, or null + * otherwise. + */ + protected DssComponent(IETLLIMSService service, IRpcServiceFactory dssServiceFactory, + String sessionTokenOrNull) + { + this.openBisService = service; + this.dssServiceFactory = dssServiceFactory; + if (sessionTokenOrNull == null) + { + this.state = new UnauthenticatedState(service); + } else + { + this.state = new AuthenticatedState(service, dssServiceFactory, sessionTokenOrNull); + } + } + + public String getSessionToken() + { + return state.getSessionToken(); + } + + public void checkSession() throws InvalidSessionException + { + state.checkSession(); + } + + public IDataSetDss getDataSet(String code) throws EnvironmentFailureException, + IllegalStateException + { + return state.getDataSet(code); + } + + public void logout() + { + // logout and transition to the unauthenticated state + state.logout(); + state = new UnauthenticatedState(openBisService); + } + + /** + * Authenticates the <code>user</code> with given <code>password</code>. + * + * @throws AuthorizationFailureException Thrown if the username / password do not authenticate. + * @throws EnvironmentFailureException Thrown in cases where it is not possible to connect to + * the server. + */ + void login(String user, String password) throws AuthorizationFailureException, + EnvironmentFailureException + { + // login and transition to the authenticated state + state.login(user, password); + state = new AuthenticatedState(openBisService, dssServiceFactory, state.getSessionToken()); + } +} + +/** + * 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 IllegalStateException + { + throw new IllegalStateException("Please log in"); + } + + public IDataSetDss getDataSet(String code) throws IllegalStateException + { + throw new IllegalStateException("Please log in"); + } + + /** + * Authenticates the <code>user</code> with given <code>password</code>. + * + * @throws AuthorizationFailureException Thrown if the username / password do not authenticate. + * @throws EnvironmentFailureException Thrown in cases where it is not possible to connect to + * the server. + */ + abstract void login(final String user, final String password) + throws AuthorizationFailureException, EnvironmentFailureException; + + /** + * Package visible method used to transfer context information between states. + */ + public abstract String getSessionToken(); +} + +/** + * 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); + } + + @Override + public String getSessionToken() + { + if (sessionOrNull == null) + throw new IllegalStateException("Please log in"); + return sessionOrNull.getSessionToken(); + } + + @Override + void login(String user, String password) throws AuthorizationFailureException, + EnvironmentFailureException + { + try + { + sessionOrNull = service.tryToAuthenticate(user, password); + } catch (RemoteConnectFailureException e) + { + throw new EnvironmentFailureException("Could not connect to server", e); + } + if (sessionOrNull == null) + throw new AuthorizationFailureException("Login or Password invalid"); + } + + public void logout() + { + return; + } +} + +/** + * An object representing an authenticated state. Being in this state means that the user has logged + * in and all operations are available, except login. + * + * @author Chandrasekhar Ramakrishnan + */ +class AuthenticatedState extends AbstractDssComponentState +{ + private final String sessionToken; + + private final IRpcServiceFactory dssServiceFactory; + + /** + * @param service + */ + AuthenticatedState(IETLLIMSService service, IRpcServiceFactory dssServiceFactory, + String sessionToken) + { + super(service); + this.dssServiceFactory = dssServiceFactory; + this.sessionToken = sessionToken; + } + + @Override + void login(String user, String password) throws AuthorizationFailureException + { + throw new IllegalStateException("Already logged in."); + } + + @Override + public void checkSession() + { + if (null == service.tryGetSession(getSessionToken())) + { + throw new InvalidSessionException("Session has expired"); + } + } + + public void logout() + { + service.logout(getSessionToken()); + } + + @Override + public IDataSetDss getDataSet(String code) throws IllegalArgumentException, + EnvironmentFailureException, RemoteAccessException + { + // Contact openBIS to find out which DSS server manages the data set + ExternalData dataSetOpenBis = service.tryGetDataSet(getSessionToken(), code); + if (null == dataSetOpenBis) + { + throw new IllegalArgumentException("Could not retrieve data set with code " + code); + } + DataStore dataStore = dataSetOpenBis.getDataStore(); + + String url = dataStore.getDownloadUrl(); + + IDssServiceRpcGeneric dssService = getDssServiceForUrl(url); + // Return a proxy to the data set + return new DataSetDss(code, dssService, this); + + } + + /** + * Package visible method to communicate with the server and get a list of files contained in + * this data set. + */ + FileInfoDssDTO[] listFiles(DataSetDss dataSetDss, String startPath, boolean isRecursive) + throws InvalidSessionException + { + return dataSetDss.getService().listFilesForDataSet(getSessionToken(), dataSetDss.getCode(), + startPath, isRecursive); + } + + /** + * Package visible method to communicate with the server and get a list of files contained in + * this data set. + */ + InputStream getFile(DataSetDss dataSetDss, String path) throws InvalidSessionException + { + return dataSetDss.getService().getFileForDataSet(getSessionToken(), dataSetDss.getCode(), + path); + } + + /** + * Create a connection to the DSS server referenced by url + */ + private IDssServiceRpcGeneric getDssServiceForUrl(String url) + { + // Get an RPC service for the DSS server + String serverURL = url; + try + { + IDssServiceRpcGeneric dssService = basicGetDssServiceForUrl(serverURL); + return dssService; + } catch (RemoteAccessException e) + { + // if the url begins with https, try http + if (serverURL.startsWith("https://")) + { + // https:// has 8 characters + serverURL = "http://" + serverURL.substring(8); + IDssServiceRpcGeneric dssService = basicGetDssServiceForUrl(serverURL); + return dssService; + } + + // Rethrow the exception + throw e; + } + } + + /** + * A less sophisticated implementation of getDssServiceForUrl + */ + private IDssServiceRpcGeneric basicGetDssServiceForUrl(String serverURL) + { + IDssServiceRpcGeneric dssService = null; + Collection<RpcServiceInterfaceDTO> ifaces = + dssServiceFactory.getSupportedInterfaces(serverURL, false); + + for (RpcServiceInterfaceDTO iface : ifaces) + { + if (IDssServiceRpcGeneric.DSS_SERVICE_NAME.equals(iface.getInterfaceName())) + { + for (RpcServiceInterfaceVersionDTO ifaceVersion : iface.getVersions()) + { + if (1 == ifaceVersion.getMajorVersion()) + { + dssService = + dssServiceFactory.getService(ifaceVersion, + IDssServiceRpcGeneric.class, serverURL, false); + return dssService; + } + } + } + } + throw new IllegalArgumentException("Server does not support the " + + IDssServiceRpcGeneric.DSS_SERVICE_NAME + " interface."); + } + + @Override + public String getSessionToken() + { + return sessionToken; + } +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssServiceRpcFactory.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssServiceRpcFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..9c6f27412b8192d0126fa5e43f34e9b0fce94056 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssServiceRpcFactory.java @@ -0,0 +1,176 @@ +/* + * 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.v1.impl; + +import java.io.File; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Collection; + +import ch.systemsx.cisd.common.api.IRpcService; +import ch.systemsx.cisd.common.api.IRpcServiceFactory; +import ch.systemsx.cisd.common.api.IRpcServiceNameServer; +import ch.systemsx.cisd.common.api.IncompatibleAPIVersionsException; +import ch.systemsx.cisd.common.api.RpcServiceInterfaceDTO; +import ch.systemsx.cisd.common.api.RpcServiceInterfaceVersionDTO; +import ch.systemsx.cisd.common.spring.HttpInvokerUtils; +import ch.systemsx.cisd.common.ssl.SslCertificateHelper; + +/** + * Client-side factory for DssServiceRpc objects. + * <p> + * Create client-side proxies to server RPC interface objects. + * + * @author Chandrasekhar Ramakrishnan + */ +// TODO: This code should be refactored and moved into a common location, but it is a bit difficult +// due to dependencies. +public class DssServiceRpcFactory implements IRpcServiceFactory +{ + private static final int SERVER_TIMEOUT_MIN = 5; + + private static final String NAME_SERVER_SUFFIX = "/rmi-name-server"; + + public Collection<RpcServiceInterfaceDTO> getSupportedInterfaces(String serverURL, + boolean getServerCertificateFromServer) throws IncompatibleAPIVersionsException + { + // We assume the location of the name server follows the convention + String nameServerURL = serverURL + NAME_SERVER_SUFFIX; + Class<IRpcServiceNameServer> clazz = IRpcServiceNameServer.class; + if (getServerCertificateFromServer) + { + new SslCertificateHelper(nameServerURL, getConfigDirectory(), "dss").setUpKeyStore(); + } + + IRpcServiceNameServer nameServer = + new ServiceProxyBuilder<IRpcServiceNameServer>(nameServerURL, clazz, + SERVER_TIMEOUT_MIN, 1).getServiceInterface(); + return nameServer.getSupportedInterfaces(); + } + + public <T extends IRpcService> T getService(RpcServiceInterfaceVersionDTO ifaceVersion, + Class<T> ifaceClazz, String serverURL, boolean getServerCertificateFromServer) + throws IncompatibleAPIVersionsException + { + String serviceURL = serverURL + ifaceVersion.getUrlSuffix(); + if (getServerCertificateFromServer) + { + new SslCertificateHelper(serviceURL, getConfigDirectory(), "dss").setUpKeyStore(); + } + + return new ServiceProxyBuilder<T>(serviceURL, ifaceClazz, SERVER_TIMEOUT_MIN, 1) + .getServiceInterface(); + } + + private File getConfigDirectory() + { + String homeDir = System.getProperty("dss.root"); + File configDir; + if (homeDir != null) + { + configDir = new File(homeDir, "etc"); + } else + { + homeDir = System.getProperty("user.home"); + configDir = new File(homeDir, ".dss"); + } + configDir.mkdirs(); + return configDir; + } +} + +/** + * Internal helper class for constructing service proxies; + * + * @author Chandrasekhar Ramakrishnan + */ +@SuppressWarnings("unchecked") +class ServiceProxyBuilder<T extends IRpcService> +{ + private final String serviceURL; + + private final Class<?> clazz; + + private final int serverTimeoutMin; + + private final int apiClientVersion; + + ServiceProxyBuilder(String serviceURL, Class<?> clazz, int serverTimeoutMin, + int apiClientVersion) + { + this.serviceURL = serviceURL; + this.clazz = clazz; + this.serverTimeoutMin = serverTimeoutMin; + this.apiClientVersion = apiClientVersion; + } + + T getServiceInterface() throws IncompatibleAPIVersionsException + { + T service = getRawServiceProxy(); + service = wrapProxyInServiceInvocationHandler(service); + final int apiServerVersion = service.getMajorVersion(); + if (apiClientVersion != apiServerVersion) + { + throw new IncompatibleAPIVersionsException(apiClientVersion, apiServerVersion); + } + + return service; + } + + private T getRawServiceProxy() + { + return (T) HttpInvokerUtils.createStreamSupportingServiceStub(clazz, serviceURL, + serverTimeoutMin); + } + + private T wrapProxyInServiceInvocationHandler(T service) + { + final ClassLoader classLoader = DssServiceRpcFactory.class.getClassLoader(); + final ServiceInvocationHandler invocationHandler = new ServiceInvocationHandler(service); + final T proxy = (T) Proxy.newProxyInstance(classLoader, new Class[] + { clazz }, invocationHandler); + return proxy; + } + + /** + * An invocation handler that unwraps exceptions that occur in methods called via reflection. + * + * @author Chandrasekhar Ramakrishnan + */ + private static final class ServiceInvocationHandler implements InvocationHandler + { + private final IRpcService service; + + private ServiceInvocationHandler(IRpcService service) + { + this.service = service; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable + { + try + { + return method.invoke(service, args); + } catch (InvocationTargetException ex) + { + throw ex.getCause(); + } + } + } +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServer.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServer.java index aef7532fca0bbbdfe3a243ea02f80c12068ba551..b7e57457f46bd1230bf2790c748620c65a9190a6 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServer.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServer.java @@ -53,8 +53,8 @@ import ch.systemsx.cisd.common.logging.LogCategory; import ch.systemsx.cisd.common.logging.LogFactory; import ch.systemsx.cisd.common.logging.LogInitializer; import ch.systemsx.cisd.common.utilities.ExtendedProperties; -import ch.systemsx.cisd.openbis.dss.api.v1.server.DssServiceRpcGeneric; import ch.systemsx.cisd.openbis.dss.generic.server.ConfigParameters.PluginServlet; +import ch.systemsx.cisd.openbis.dss.generic.server.api.v1.DssServiceRpcGeneric; import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider; import ch.systemsx.cisd.openbis.dss.generic.shared.utils.DssPropertyParametersUtil; diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/server/DssServiceRpcGeneric.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v1/DssServiceRpcGeneric.java similarity index 93% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/server/DssServiceRpcGeneric.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v1/DssServiceRpcGeneric.java index 00e10eb47e80fa56d99deb79ef8cfd7111915e15..24c07e7ae320d11c5d1b59c541443ab5ebcd1b4a 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/server/DssServiceRpcGeneric.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/api/v1/DssServiceRpcGeneric.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.v1.server; +package ch.systemsx.cisd.openbis.dss.generic.server.api.v1; import java.io.File; import java.io.FileInputStream; @@ -23,11 +23,11 @@ import java.io.InputStream; import java.util.ArrayList; import ch.systemsx.cisd.base.exceptions.IOExceptionUnchecked; -import ch.systemsx.cisd.openbis.dss.api.v1.shared.FileInfoDssBuilder; -import ch.systemsx.cisd.openbis.dss.api.v1.shared.FileInfoDssDTO; -import ch.systemsx.cisd.openbis.dss.api.v1.shared.IDssServiceRpcGeneric; import ch.systemsx.cisd.openbis.dss.generic.server.AbstractDssServiceRpc; import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssBuilder; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.IDssServiceRpcGeneric; /** * Implementation of the generic RPC interface. diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/shared/FileInfoDssBuilder.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/FileInfoDssBuilder.java similarity index 98% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/shared/FileInfoDssBuilder.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/FileInfoDssBuilder.java index 6a40ba3d5c0f8b9cdb986f4f9300a84297118ccd..c8205f8bb1e870829280ec29ccca4bd6c54a83b7 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/shared/FileInfoDssBuilder.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/FileInfoDssBuilder.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.v1.shared; +package ch.systemsx.cisd.openbis.dss.generic.shared.api.v1; import java.io.File; import java.io.IOException; diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/shared/FileInfoDssDTO.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/FileInfoDssDTO.java similarity index 97% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/shared/FileInfoDssDTO.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/FileInfoDssDTO.java index 41a9c95046173b143caa2c70cdfcf619d0f29b1a..20c10bb6de6825db09b94269408796a78171fac0 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/shared/FileInfoDssDTO.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/FileInfoDssDTO.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.v1.shared; +package ch.systemsx.cisd.openbis.dss.generic.shared.api.v1; import java.io.Serializable; diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/shared/IDssServiceRpcGeneric.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/IDssServiceRpcGeneric.java similarity index 97% rename from datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/shared/IDssServiceRpcGeneric.java rename to datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/IDssServiceRpcGeneric.java index 09e5efd1a3ba338b07c3c055554b0e56db1aa30e..51bdc10b2151378336e8d742011078392eb1ec81 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/api/v1/shared/IDssServiceRpcGeneric.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/v1/IDssServiceRpcGeneric.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.v1.shared; +package ch.systemsx.cisd.openbis.dss.generic.shared.api.v1; import java.io.InputStream; diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/api/client/cli/CommandFactoryTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandFactoryTest.java similarity index 85% rename from datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/api/client/cli/CommandFactoryTest.java rename to datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandFactoryTest.java index 7780621e45426a7310ff30bd39a1f0e7c5ccb5d8..f5c57c94b1497c7deebb1a98d9dd84f9661c16ec 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/api/client/cli/CommandFactoryTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/CommandFactoryTest.java @@ -14,16 +14,16 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.client.cli; +package ch.systemsx.cisd.openbis.dss.client.api.cli; import org.testng.AssertJUnit; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import ch.systemsx.cisd.openbis.dss.api.client.cli.CommandFactory; -import ch.systemsx.cisd.openbis.dss.api.client.cli.CommandGet; -import ch.systemsx.cisd.openbis.dss.api.client.cli.CommandLs; -import ch.systemsx.cisd.openbis.dss.api.client.cli.ICommand; +import ch.systemsx.cisd.openbis.dss.client.api.cli.CommandFactory; +import ch.systemsx.cisd.openbis.dss.client.api.cli.CommandGet; +import ch.systemsx.cisd.openbis.dss.client.api.cli.CommandLs; +import ch.systemsx.cisd.openbis.dss.client.api.cli.ICommand; /** * @author Chandrasekhar Ramakrishnan diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/api/client/cli/GlobalArgumentsTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/GlobalArgumentsTest.java similarity index 96% rename from datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/api/client/cli/GlobalArgumentsTest.java rename to datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/GlobalArgumentsTest.java index c02111f1b6683ecc2dbf8ce895679a41b0c253c9..d201f65e7c5c6959d8df5141b4d321c14fce9385 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/api/client/cli/GlobalArgumentsTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/cli/GlobalArgumentsTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package ch.systemsx.cisd.openbis.dss.api.client.cli; +package ch.systemsx.cisd.openbis.dss.client.api.cli; import org.testng.AssertJUnit; import org.testng.annotations.BeforeMethod; @@ -22,7 +22,7 @@ import org.testng.annotations.Test; import ch.systemsx.cisd.args4j.CmdLineException; import ch.systemsx.cisd.args4j.CmdLineParser; -import ch.systemsx.cisd.openbis.dss.api.client.cli.GlobalArguments; +import ch.systemsx.cisd.openbis.dss.client.api.cli.GlobalArguments; /** * @author Chandrasekhar Ramakrishnan diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssComponentTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssComponentTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d241c21e7d08aecb8fb7d54bddfea450c6667435 --- /dev/null +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssComponentTest.java @@ -0,0 +1,274 @@ +/* + * 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.v1.impl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Random; + +import org.apache.commons.io.IOUtils; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; +import ch.systemsx.cisd.common.api.IRpcServiceFactory; +import ch.systemsx.cisd.common.api.RpcServiceInterfaceDTO; +import ch.systemsx.cisd.common.api.RpcServiceInterfaceVersionDTO; +import ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss; +import ch.systemsx.cisd.openbis.dss.client.api.v1.impl.DssComponent; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssBuilder; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.IDssServiceRpcGeneric; +import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataStore; +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 AbstractFileSystemTestCase +{ + private Mockery context; + + private IETLLIMSService openBisService; + + private IRpcServiceFactory dssServiceFactory; + + private DssComponent dssComponent; + + private File randomDataFile; + + private static final String DUMMY_SESSSION_TOKEN = "DummySessionToken"; + + private static final String DUMMY_DSS_URL = "http://localhost/datastore_server"; + + public DssComponentTest() + { + + } + + @Override + @BeforeMethod + public void setUp() throws IOException + { + super.setUp(); + context = new Mockery(); + openBisService = context.mock(IETLLIMSService.class); + dssServiceFactory = context.mock(IRpcServiceFactory.class); + dssComponent = new DssComponent(openBisService, dssServiceFactory, null); + randomDataFile = getFileWithRandomData(1); + } + + @Test + public void testLogin() + { + final SessionContextDTO session = getDummySession(); + + context.checking(new Expectations() + { + { + one(openBisService).tryToAuthenticate("foo", "bar"); + will(returnValue(session)); + } + }); + + dssComponent.login("foo", "bar"); + + context.assertIsSatisfied(); + } + + @Test + public void testListDataSetFiles() throws IOException + { + setupExpectations(); + + dssComponent.login("foo", "bar"); + IDataSetDss dataSetProxy = dssComponent.getDataSet("DummyDataSetCode"); + FileInfoDssDTO[] fileInfos = dataSetProxy.listFiles("/", true); + assertEquals(1, fileInfos.length); + + context.assertIsSatisfied(); + } + + @Test + public void testListDataSetFilesNoLogin() throws IOException + { + dssComponent = new DssComponent(openBisService, dssServiceFactory, DUMMY_SESSSION_TOKEN); + setupExpectationsNoLogin(); + IDataSetDss dataSetProxy = dssComponent.getDataSet("DummyDataSetCode"); + FileInfoDssDTO[] fileInfos = dataSetProxy.listFiles("/", true); + assertEquals(1, fileInfos.length); + + context.assertIsSatisfied(); + } + + @Test + public void testUnsupportedInterface() throws IOException + { + setupExpectations("Some Server Interface", true); + + dssComponent.login("foo", "bar"); + try + { + dssComponent.getDataSet("DummyDataSetCode"); + fail("Should have thrown an IllegalArgumentException"); + } catch (IllegalArgumentException e) + { + // correct behavior + } + + context.assertIsSatisfied(); + } + + @Test + public void testGetFileContents() throws IOException + { + setupExpectations(); + + dssComponent.login("foo", "bar"); + IDataSetDss dataSetProxy = dssComponent.getDataSet("DummyDataSetCode"); + FileInfoDssDTO[] fileInfos = dataSetProxy.listFiles("/", true); + FileInfoDssDTO fileFileInfo = null; + for (FileInfoDssDTO fid : fileInfos) + { + if (fid.isDirectory() == false) + { + fileFileInfo = fid; + break; + } + } + if (fileFileInfo == null) + { + fail("Could not find file info for random file"); + return; + } + + InputStream is = dataSetProxy.getFile(fileFileInfo.getPathInDataSet()); + int byteCount = 0; + while (is.read() >= 0) + { + ++byteCount; + } + + assertEquals(fileFileInfo.getFileSize(), byteCount); + } + + private void setupExpectations() throws IOException + { + setupExpectations(IDssServiceRpcGeneric.DSS_SERVICE_NAME, true); + } + + private void setupExpectationsNoLogin() throws IOException + { + setupExpectations(IDssServiceRpcGeneric.DSS_SERVICE_NAME, false); + } + + private void setupExpectations(String serviceName, final boolean needsLogin) throws IOException + { + final SessionContextDTO session = getDummySession(); + final ExternalData dataSetExternalData = new ExternalData(); + DataStore dataStore = new DataStore(); + dataStore.setDownloadUrl(DUMMY_DSS_URL); + dataSetExternalData.setDataStore(dataStore); + final IDssServiceRpcGeneric dssService = context.mock(IDssServiceRpcGeneric.class); + ArrayList<FileInfoDssDTO> list = new ArrayList<FileInfoDssDTO>(); + FileInfoDssBuilder builder = + new FileInfoDssBuilder(workingDirectory.getCanonicalPath(), workingDirectory + .getCanonicalPath()); + builder.appendFileInfosForFile(workingDirectory, list, true); + final FileInfoDssDTO[] fileInfos = new FileInfoDssDTO[list.size()]; + list.toArray(fileInfos); + + final ArrayList<RpcServiceInterfaceDTO> ifaces = new ArrayList<RpcServiceInterfaceDTO>(1); + final RpcServiceInterfaceDTO iface = new RpcServiceInterfaceDTO(serviceName); + final RpcServiceInterfaceVersionDTO ifaceVersion = + new RpcServiceInterfaceVersionDTO(serviceName, "/rpc/v1", 1, 0); + + iface.addVersion(ifaceVersion); + + ifaces.add(iface); + + context.checking(new Expectations() + { + { + final String dataSetCode = "DummyDataSetCode"; + + if (needsLogin) + { + one(openBisService).tryToAuthenticate("foo", "bar"); + will(returnValue(session)); + } + allowing(openBisService).tryGetDataSet(DUMMY_SESSSION_TOKEN, dataSetCode); + will(returnValue(dataSetExternalData)); + allowing(dssServiceFactory).getSupportedInterfaces(DUMMY_DSS_URL, false); + will(returnValue(ifaces)); + allowing(dssServiceFactory).getService(ifaceVersion, + IDssServiceRpcGeneric.class, DUMMY_DSS_URL, false); + will(returnValue(dssService)); + allowing(dssService).listFilesForDataSet(DUMMY_SESSSION_TOKEN, dataSetCode, + "/", true); + will(returnValue(fileInfos)); + allowing(dssService).getFileForDataSet(DUMMY_SESSSION_TOKEN, dataSetCode, + "/random.txt"); + will(returnValue(new FileInputStream(randomDataFile))); + } + }); + } + + private SessionContextDTO getDummySession() + { + final SessionContextDTO session = new SessionContextDTO(); + session.setSessionToken(DUMMY_SESSSION_TOKEN); + return session; + } + + private File getFileWithRandomData(long sizeInKB) throws IOException + { + File file = new File(workingDirectory, "random.txt"); + Random random = new Random(); + FileOutputStream outputStream = null; + try + { + outputStream = new FileOutputStream(file); + byte[] bytes = new byte[1024]; + for (int i = 0; i < sizeInKB; i++) + { + random.nextBytes(bytes); + outputStream.write(bytes); + } + } catch (IOException ex) + { + throw ex; + } finally + { + if (outputStream != null) + { + IOUtils.closeQuietly(outputStream); + } + } + + return file; + } + +} diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssComponentTestClient.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssComponentTestClient.java new file mode 100644 index 0000000000000000000000000000000000000000..e9d571cae3a987b79f1ae2e65502866900637139 --- /dev/null +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/client/api/v1/impl/DssComponentTestClient.java @@ -0,0 +1,60 @@ +/* + * 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.v1.impl; + +import java.util.Properties; + +import org.apache.log4j.PropertyConfigurator; + +import ch.systemsx.cisd.openbis.dss.client.api.v1.DssComponentFactory; +import ch.systemsx.cisd.openbis.dss.client.api.v1.IDataSetDss; +import ch.systemsx.cisd.openbis.dss.client.api.v1.IDssComponent; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO; + +/** + * @author Chandrasekhar Ramakrishnan + */ +public class DssComponentTestClient +{ + + public static void main(String[] args) + { + configureLogging(); + System.out.println("Logging in"); + IDssComponent component = + DssComponentFactory.tryCreate("test", "foobar", "http://localhost:8888"); + IDataSetDss dataSet = component.getDataSet("20100318094819344-4"); + FileInfoDssDTO fileInfos[] = dataSet.listFiles("/", true); + for (FileInfoDssDTO fileInfo : fileInfos) + { + System.out.println(fileInfo); + } + component.logout(); + System.out.println("Logging out"); + } + + private static void configureLogging() + { + Properties props = new Properties(); + props.put("log4j.appender.STDOUT", "org.apache.log4j.ConsoleAppender"); + props.put("log4j.appender.STDOUT.layout", "org.apache.log4j.PatternLayout"); + props.put("log4j.appender.STDOUT.layout.ConversionPattern", "%d %-5p [%t] %c - %m%n"); + props.put("log4j.rootLogger", "INFO, STDOUT"); + PropertyConfigurator.configure(props); + } + +} diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1Test.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1Test.java index e309591b7a237b8337f82d7cdbbe9bb90f948419..a005b87badb15cdf331c8ab6aaf43b2fdbe515c5 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1Test.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1Test.java @@ -30,9 +30,9 @@ import org.testng.annotations.Test; import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; import ch.systemsx.cisd.common.exceptions.UserFailureException; -import ch.systemsx.cisd.openbis.dss.api.v1.server.DssServiceRpcGeneric; -import ch.systemsx.cisd.openbis.dss.api.v1.shared.FileInfoDssDTO; +import ch.systemsx.cisd.openbis.dss.generic.server.api.v1.DssServiceRpcGeneric; import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; +import ch.systemsx.cisd.openbis.dss.generic.shared.api.v1.FileInfoDssDTO; import ch.systemsx.cisd.openbis.dss.generic.shared.utils.DatasetLocationUtil; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseInstance;