diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/DssComponentFactory.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/DssComponentFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..aaad87287e795884461c64ec6f66ab30c9a59861 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/DssComponentFactory.java @@ -0,0 +1,51 @@ +/* + * 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.component; + +import ch.systemsx.cisd.openbis.dss.component.impl.DssComponent; + +/** + * A class that creates DssComponents. + * + * @author Chandrasekhar Ramakrishnan + */ +public class DssComponentFactory +{ + /** + * Public factory method for creating an IDssComponent with a username and password. + * + * @param user The user name + * @param password The user's password + * @param openBISUrl The URL to openBIS + */ + public static IDssComponent tryCreate(String user, String password, String openBISUrl) + { + return DssComponent.tryCreate(user, password, openBISUrl); + } + + /** + * Public factory method for creating an IDssComponent for a user that has already been + * authenticated. + * + * @param sessionToken The session token provided by authentication + * @param openBISUrl The URL to openBIS + */ + public static IDssComponent tryCreate(String sessionToken, String openBISUrl) + { + return DssComponent.tryCreate(sessionToken, openBISUrl); + } +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/IDssComponent.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/IDssComponent.java index 347153aef1e5484ab04211efa3ffcfd3c4f5d9ae..f3f2229381baf58e569200a561e45daba6154690 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/IDssComponent.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/IDssComponent.java @@ -16,7 +16,6 @@ package ch.systemsx.cisd.openbis.dss.component; -import ch.systemsx.cisd.common.exceptions.AuthorizationFailureException; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; import ch.systemsx.cisd.common.exceptions.InvalidSessionException; @@ -40,21 +39,19 @@ import ch.systemsx.cisd.common.exceptions.InvalidSessionException; public interface IDssComponent { /** - * Authenticates the <code>user</code> with given <code>password</code>. + * Checks whether the session is alive. * - * @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. + * @throws InvalidSessionException If the session is not alive. */ - public void login(final String user, final String password) - throws AuthorizationFailureException, EnvironmentFailureException; + public void checkSession() throws InvalidSessionException; /** - * Checks whether the session is alive. + * Returns the session token. * - * @throws InvalidSessionException If the session is not alive. + * @return The session token for an authenticated user. + * @throws IllegalStateException Thrown if the user has not yet been authenticated. */ - public void checkSession() throws InvalidSessionException; + public String getSessionToken() throws IllegalStateException; /** * Get a proxy to the data set designated by the given data set code. diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/impl/DssComponent.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/impl/DssComponent.java index 1b8c14adcaf2279147b30cac72d3b01449b1e755..55170179799cba2a39d659554f7ae2171baa16e7 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/impl/DssComponent.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/impl/DssComponent.java @@ -59,6 +59,40 @@ public class DssComponent implements IDssComponent 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); + return component; + } + /** * Create a DSS component that connects to the openBIS instance specified by the URL. * <p> @@ -66,31 +100,40 @@ public class DssComponent implements IDssComponent * 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. */ - public DssComponent(String openBISURL) + private DssComponent(String openBISURL, String sessionTokenOrNull) { this(HttpInvokerUtils.createServiceStub(IETLLIMSService.class, openBISURL + "/rmi-etl", - SERVIER_TIMEOUT_MIN), new DssServiceRpcFactory()); + SERVIER_TIMEOUT_MIN), new DssServiceRpcFactory(), sessionTokenOrNull); } /** - * Internal constructor used for testing. + * Internal constructor, also used for testing. * - * @param service + * @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, IDssServiceRpcFactory dssServiceFactory) + protected DssComponent(IETLLIMSService service, IDssServiceRpcFactory dssServiceFactory, + String sessionTokenOrNull) { this.openBisService = service; this.dssServiceFactory = dssServiceFactory; - this.state = new UnauthenticatedState(service); + if (sessionTokenOrNull == null) + { + this.state = new UnauthenticatedState(service); + } else + { + this.state = new AuthenticatedState(service, dssServiceFactory, sessionTokenOrNull); + } } - public void login(String user, String password) throws AuthorizationFailureException, - EnvironmentFailureException + public String getSessionToken() { - // login and transition to the authenticated state - state.login(user, password); - state = new AuthenticatedState(openBisService, dssServiceFactory, state.getSession()); + return state.getSessionToken(); } public void checkSession() throws InvalidSessionException @@ -110,6 +153,21 @@ public class DssComponent implements IDssComponent 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()); + } } /** @@ -139,10 +197,20 @@ abstract class AbstractDssComponentState implements IDssComponent 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. */ - abstract SessionContextDTO getSession(); + public abstract String getSessionToken(); } /** @@ -161,14 +229,15 @@ class UnauthenticatedState extends AbstractDssComponentState } @Override - SessionContextDTO getSession() + public String getSessionToken() { if (sessionOrNull == null) - throw new UserFailureException("Please log in"); - return sessionOrNull; + throw new IllegalStateException("Please log in"); + return sessionOrNull.getSessionToken(); } - public void login(String user, String password) throws AuthorizationFailureException, + @Override + void login(String user, String password) throws AuthorizationFailureException, EnvironmentFailureException { try @@ -196,7 +265,7 @@ class UnauthenticatedState extends AbstractDssComponentState */ class AuthenticatedState extends AbstractDssComponentState { - private final SessionContextDTO session; + private final String sessionToken; private final IDssServiceRpcFactory dssServiceFactory; @@ -204,20 +273,15 @@ class AuthenticatedState extends AbstractDssComponentState * @param service */ AuthenticatedState(IETLLIMSService service, IDssServiceRpcFactory dssServiceFactory, - SessionContextDTO session) + String sessionToken) { super(service); this.dssServiceFactory = dssServiceFactory; - this.session = session; + this.sessionToken = sessionToken; } @Override - SessionContextDTO getSession() - { - return session; - } - - public void login(String user, String password) throws AuthorizationFailureException + void login(String user, String password) throws AuthorizationFailureException { throw new UserFailureException("Already logged in."); } @@ -324,8 +388,9 @@ class AuthenticatedState extends AbstractDssComponentState + IDssServiceRpcGeneric.DSS_SERVICE_NAME + " interface."); } - private String getSessionToken() + @Override + public String getSessionToken() { - return session.getSessionToken(); + return sessionToken; } } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/client/cli/AbstractCommand.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/client/cli/AbstractCommand.java index 559c6a53e5c32529b8d03022bf8b739ec3def623..577fa5b1ec855ac8a463b026318e769e4f78ea09 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/client/cli/AbstractCommand.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/client/cli/AbstractCommand.java @@ -81,8 +81,9 @@ abstract class AbstractCommand implements ICommand */ protected IDssComponent login(GlobalArguments arguments) { - IDssComponent component = new DssComponent(arguments.getServerBaseUrl()); - component.login(arguments.getUsername(), arguments.getPassword()); + IDssComponent component = + DssComponent.tryCreate(arguments.getUsername(), arguments.getPassword(), arguments + .getServerBaseUrl()); return component; } diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/component/impl/DssComponentTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/component/impl/DssComponentTest.java index c92e1e41387b90748280ffa7bbee48020ca7a91e..c473f2c27ebffe73e4940e838f40b8edaff9e00f 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/component/impl/DssComponentTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/component/impl/DssComponentTest.java @@ -75,7 +75,7 @@ public class DssComponentTest extends AbstractFileSystemTestCase context = new Mockery(); openBisService = context.mock(IETLLIMSService.class); dssServiceFactory = context.mock(IDssServiceRpcFactory.class); - dssComponent = new DssComponent(openBisService, dssServiceFactory); + dssComponent = new DssComponent(openBisService, dssServiceFactory, null); randomDataFile = getFileWithRandomData(1); } @@ -110,10 +110,22 @@ public class DssComponentTest extends AbstractFileSystemTestCase 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"); + setupExpectations("Some Server Interface", true); dssComponent.login("foo", "bar"); try @@ -163,10 +175,15 @@ public class DssComponentTest extends AbstractFileSystemTestCase private void setupExpectations() throws IOException { - setupExpectations(IDssServiceRpcGeneric.DSS_SERVICE_NAME); + setupExpectations(IDssServiceRpcGeneric.DSS_SERVICE_NAME, true); } - private void setupExpectations(String serviceName) throws IOException + 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(); @@ -200,8 +217,11 @@ public class DssComponentTest extends AbstractFileSystemTestCase { final String dataSetCode = "DummyDataSetCode"; - one(openBisService).tryToAuthenticate("foo", "bar"); - will(returnValue(session)); + 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); diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/component/impl/DssComponentTestClient.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/component/impl/DssComponentTestClient.java new file mode 100644 index 0000000000000000000000000000000000000000..afee477100a8e8a368064d08b04de8892d6ece1b --- /dev/null +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/component/impl/DssComponentTestClient.java @@ -0,0 +1,50 @@ +/* + * 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.component.impl; + +import java.util.Properties; + +import org.apache.log4j.PropertyConfigurator; + +/** + * @author Chandrasekhar Ramakrishnan + */ +public class DssComponentTestClient +{ + + public static void main(String[] args) + { + configureLogging(); + System.out.println("Logging in"); + DssComponent component = + DssComponent.tryCreate("test", "foobar", "http://localhost:8888/openbis"); + component.getDataSet("20100318094819344-4"); + 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); + } + +}