diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java index fbaea4cd2629722cc57fa5d20bebda84a5f19350..781494c0e1867a05717d5784bd2d17efd1c765de 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java @@ -62,15 +62,12 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind; public final class CommonBusinessObjectFactory extends AbstractBusinessObjectFactory implements ICommonBusinessObjectFactory { - public CommonBusinessObjectFactory(final IDAOFactory daoFactory) + + public CommonBusinessObjectFactory(IDAOFactory daoFactory, IDataStoreServiceFactory dssFactory) { - super(daoFactory); + super(daoFactory, dssFactory); } - // - // IGenericBusinessObjectFactory - // - public final IGroupBO createGroupBO(final Session session) { return new GroupBO(getDaoFactory(), session); @@ -98,7 +95,7 @@ public final class CommonBusinessObjectFactory extends AbstractBusinessObjectFac public final IExternalDataTable createExternalDataTable(final Session session) { - return new ExternalDataTable(getDaoFactory(), session); + return new ExternalDataTable(getDaoFactory(), getDSSFactory(), session); } public IExperimentTable createExperimentTable(final Session session) diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java index 6d655aa1ab9cfcb981e2579f5f1ec8673881dcf6..79a611a3a2de2d058dfe4691fbdd669f98c421ac 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java @@ -31,7 +31,6 @@ import ch.systemsx.cisd.authentication.ISessionManager; import ch.systemsx.cisd.authentication.Principal; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; import ch.systemsx.cisd.common.exceptions.UserFailureException; -import ch.systemsx.cisd.openbis.generic.server.business.DataStoreServerSessionManager; import ch.systemsx.cisd.openbis.generic.server.business.bo.ICommonBusinessObjectFactory; import ch.systemsx.cisd.openbis.generic.server.business.bo.IEntityTypeBO; import ch.systemsx.cisd.openbis.generic.server.business.bo.IEntityTypePropertyTypeBO; @@ -113,19 +112,15 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements private final ICommonBusinessObjectFactory businessObjectFactory; - private final DataStoreServerSessionManager dssSessionManager; - private final LastModificationState lastModificationState; public CommonServer(final IAuthenticationService authenticationService, - final ISessionManager<Session> sessionManager, - DataStoreServerSessionManager dssSessionManager, final IDAOFactory daoFactory, + final ISessionManager<Session> sessionManager, final IDAOFactory daoFactory, final ICommonBusinessObjectFactory businessObjectFactory, LastModificationState lastModificationState) { super(sessionManager, daoFactory); this.authenticationService = authenticationService; - this.dssSessionManager = dssSessionManager; this.businessObjectFactory = businessObjectFactory; this.lastModificationState = lastModificationState; } @@ -646,7 +641,7 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements { DataSetTypePE dataSetType = entry.getKey(); IDataSetTypeSlaveServerPlugin plugin = getDataSetTypeSlaveServerPlugin(dataSetType); - plugin.deleteDataSets(session, dssSessionManager, entry.getValue(), reason); + plugin.deleteDataSets(session, entry.getValue(), reason); } } catch (final DataAccessException ex) { @@ -663,7 +658,7 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements IExternalDataTable externalDataTable = businessObjectFactory.createExternalDataTable(session); externalDataTable.loadByDataSetCodes(dataSetCodes); - externalDataTable.uploadLoadedDataSetsToCIFEX(dssSessionManager, uploadContext); + externalDataTable.uploadLoadedDataSetsToCIFEX(uploadContext); } catch (final DataAccessException ex) { throw createUserFailureException(ex); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ComponentNames.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ComponentNames.java index adf1e4c8c61e2d89ef86412567385f0d8919299e..e54907126cbc3c26692880626b6feae2d20d1a8c 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ComponentNames.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ComponentNames.java @@ -36,6 +36,8 @@ public final class ComponentNames public static final String LOG_INTERCEPTOR = "log-interceptor"; public static final String DAO_FACTORY = "dao-factory"; + + public static final String DSS_FACTORY = "dss-factory"; public static final String COMMON_BUSINESS_OBJECT_FACTORY = "common-business-object-factory"; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/DataStoreServiceFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/DataStoreServiceFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..0087c4223b9749fd1bc160f048ccdda5ac40f081 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/DataStoreServiceFactory.java @@ -0,0 +1,48 @@ +/* + * Copyright 2009 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.generic.server; + +import static ch.systemsx.cisd.openbis.generic.shared.GenericSharedConstants.DATA_STORE_SERVER_SERVICE_NAME; + +import java.util.HashMap; +import java.util.Map; + +import ch.systemsx.cisd.common.spring.HttpInvokerUtils; +import ch.systemsx.cisd.openbis.generic.shared.IDataStoreService; + +/** + * Factory of cached {@link IDataStoreService} instances. + * + * @author Franz-Josef Elmer + */ +public class DataStoreServiceFactory implements IDataStoreServiceFactory +{ + private final Map<String, IDataStoreService> services = new HashMap<String, IDataStoreService>(); + + public IDataStoreService create(String serverURL) + { + IDataStoreService service = services.get(serverURL); + if (service == null) + { + service = HttpInvokerUtils.createServiceStub(IDataStoreService.class, serverURL + "/" + + DATA_STORE_SERVER_SERVICE_NAME, 5); + services.put(serverURL, service); + } + return service; + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java index e75e88a6e376c87a3998f5ec61a62f993049b43f..f1deabd587ba42cc956e31ce6e4dd2ac087da9d2 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLService.java @@ -16,8 +16,6 @@ package ch.systemsx.cisd.openbis.generic.server; -import static ch.systemsx.cisd.openbis.generic.shared.GenericSharedConstants.DATA_STORE_SERVER_SERVICE_NAME; - import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; @@ -27,18 +25,18 @@ import ch.systemsx.cisd.authentication.ISessionManager; import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; import ch.systemsx.cisd.common.exceptions.UserFailureException; -import ch.systemsx.cisd.common.spring.HttpInvokerUtils; import ch.systemsx.cisd.common.utilities.BeanUtils; -import ch.systemsx.cisd.openbis.generic.server.business.DataStoreServerSessionManager; import ch.systemsx.cisd.openbis.generic.server.business.bo.ICommonBusinessObjectFactory; import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataBO; import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleBO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IAttachmentDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; +import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataStoreDAO; import ch.systemsx.cisd.openbis.generic.shared.IDataStoreService; import ch.systemsx.cisd.openbis.generic.shared.IWebService; import ch.systemsx.cisd.openbis.generic.shared.dto.AttachmentPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServerSession; +import ch.systemsx.cisd.openbis.generic.shared.dto.DataStorePE; +import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServerInfo; import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalData; @@ -72,36 +70,17 @@ public class ETLService extends AbstractServer<IETLService> implements IETLServi private final ISessionManager<Session> sessionManager; - private final DataStoreServerSessionManager dssSessionManager; - private final IDAOFactory daoFactory; private final ICommonBusinessObjectFactory boFactory; private final IDataStoreServiceFactory dssFactory; - public ETLService(ISessionManager<Session> sessionManager, - DataStoreServerSessionManager dssSessionManager, IDAOFactory daoFactory, - ICommonBusinessObjectFactory boFactory) - { - this(sessionManager, dssSessionManager, daoFactory, boFactory, - new IDataStoreServiceFactory() - { - public IDataStoreService create(String serverURL) - { - return HttpInvokerUtils.createServiceStub(IDataStoreService.class, - serverURL + "/" + DATA_STORE_SERVER_SERVICE_NAME, 5); - } - }); - } - - ETLService(ISessionManager<Session> sessionManager, - DataStoreServerSessionManager dssSessionManager, IDAOFactory daoFactory, + public ETLService(ISessionManager<Session> sessionManager, IDAOFactory daoFactory, ICommonBusinessObjectFactory boFactory, IDataStoreServiceFactory dssFactory) { super(sessionManager, daoFactory); this.sessionManager = sessionManager; - this.dssSessionManager = dssSessionManager; this.daoFactory = daoFactory; this.boFactory = boFactory; this.dssFactory = dssFactory; @@ -129,13 +108,17 @@ public class ETLService extends AbstractServer<IETLService> implements IETLServi return daoFactory.getHomeDatabaseInstance(); } - public void registerDataStoreServer(String sessionToken, int port, final String dssSessionToken) + public void registerDataStoreServer(String sessionToken, DataStoreServerInfo info) { Session session = sessionManager.getSession(sessionToken); + + String dssSessionToken = info.getSessionToken(); String remoteHost = session.getRemoteHost(); + int port = info.getPort(); final String dssURL = "https://" + remoteHost + ":" + port; - DataStoreServerSession dssSession = dssSessionManager.tryToGetSession(dssURL); - if (dssSession == null) + IDataStoreDAO dataStoreDAO = daoFactory.getDataStoreDAO(); + DataStorePE dataStore = dataStoreDAO.tryToFindDataStoreByCode(info.getDataStoreCode()); + if (dataStore == null) { final IDataStoreService service = dssFactory.create(dssURL); if (operationLog.isInfoEnabled()) @@ -146,8 +129,8 @@ public class ETLService extends AbstractServer<IETLService> implements IETLServi if (IDataStoreService.VERSION != dssVersion) { String msg = - "Data Store Server version is " + dssVersion + " instead of " - + IDataStoreService.VERSION; + "Data Store Server version is " + dssVersion + " instead of " + + IDataStoreService.VERSION; notificationLog.error(msg); throw new ConfigurationFailureException(msg); } @@ -156,10 +139,14 @@ public class ETLService extends AbstractServer<IETLService> implements IETLServi operationLog.info("Data Store Server (version " + dssVersion + ") registered for " + dssURL); } - dssSession = new DataStoreServerSession(dssURL, service); - dssSessionManager.registerDataStoreServer(dssSession); + dataStore = new DataStorePE(); + dataStore.setDatabaseInstance(getHomeDatabaseInstance(sessionToken)); } - dssSession.setSessionToken(dssSessionToken); + dataStore.setCode(info.getDataStoreCode()); + dataStore.setDownloadUrl(info.getDownloadUrl()); + dataStore.setRemoteUrl(dssURL); + dataStore.setSessionToken(dssSessionToken); + dataStoreDAO.createOrUpdateDataStore(dataStore); } public String authenticate(String user, String password) throws UserFailureException diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java index d556cc0df852908e2de64664dd32ddcad706a5f8..ef606f9a8be9b252e0138ee15e2223d1cb176257 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceLogger.java @@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.server; import ch.systemsx.cisd.authentication.ISessionManager; import ch.systemsx.cisd.common.exceptions.UserFailureException; +import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServerInfo; import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalData; @@ -50,10 +51,15 @@ public class ETLServiceLogger extends AbstractServerLogger implements IETLServic return null; } - public void registerDataStoreServer(String sessionToken, int port, String dssSessionToken) + public void registerDataStoreServer(String sessionToken, DataStoreServerInfo info) { - logTracking(sessionToken, "register_data_store_server_session_token", "PORT(%s) DSS-TOKEN(%s)", - port, dssSessionToken); + String code = info.getDataStoreCode(); + String downloadUrl = info.getDownloadUrl(); + int port = info.getPort(); + String dssSessionToken = info.getSessionToken(); + logTracking(sessionToken, "register_data_store_server_session_token", + "CODE(%s) DOWNLOAD-URL(%s) PORT(%s) DSS-TOKEN(%s)", code, downloadUrl, port, + dssSessionToken); } public void registerDataSet(String sessionToken, SampleIdentifier sampleIdentifier, diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/DataStoreServerSessionManager.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/DataStoreServerSessionManager.java deleted file mode 100644 index 6dc593f3256501900a34ba3d1a8191ca19a72f85..0000000000000000000000000000000000000000 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/DataStoreServerSessionManager.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2009 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.generic.server.business; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServerSession; - -/** - * Class managing Data Store Server (DSS) sessions. It is assumed that the URL of the DSS is unique - * in order to allow more than one DSS. - * - * @author Franz-Josef Elmer - */ -public class DataStoreServerSessionManager -{ - private final Map<String, DataStoreServerSession> sessions = new HashMap<String, DataStoreServerSession>(); - - /** - * Registers the specified DSS session. - */ - public void registerDataStoreServer(DataStoreServerSession session) - { - synchronized (sessions) - { - sessions.put(session.getDataStoreServerURL(), session); - } - } - - /** - * Tries to get the DSS session identified by the specified Data Store Server URL. - * - * @return <code>null</code> if no session has been registered for the specified URL. - */ - public DataStoreServerSession tryToGetSession(String dssURL) - { - synchronized (sessions) - { - return sessions.get(dssURL); - } - } - - /** - * Returns all registered DSS sessions. - */ - public Collection<DataStoreServerSession> getSessions() - { - synchronized (sessions) - { - return new ArrayList<DataStoreServerSession>(sessions.values()); - } - } -} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java index 2742676ee63fc925baa9f66e975f3fd7d786e8f5..0f0ea0de0f83e9a700772ab15900f8ea979eb22d 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java @@ -21,6 +21,7 @@ import org.springframework.dao.DataAccessException; import ch.systemsx.cisd.common.exceptions.UserFailureException; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataSetTypeDAO; +import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataStoreDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDatabaseInstanceDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityPropertyTypeDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityTypeDAO; @@ -197,4 +198,9 @@ abstract class AbstractBusinessObject implements IDAOFactory { return daoFactory.getCodeSequenceDAO(); } + + public IDataStoreDAO getDataStoreDAO() + { + return daoFactory.getDataStoreDAO(); + } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObjectFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObjectFactory.java index 2ba222d2d596aa9630b5ccf00981d7affd607749..d7413f838d52273028cd7e36fc4e3a7b7fe36994 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObjectFactory.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObjectFactory.java @@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.generic.server.business.bo; import javax.annotation.Resource; import ch.systemsx.cisd.openbis.generic.server.ComponentNames; +import ch.systemsx.cisd.openbis.generic.server.IDataStoreServiceFactory; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; /** @@ -30,18 +31,27 @@ public abstract class AbstractBusinessObjectFactory { @Resource(name = ComponentNames.DAO_FACTORY) private IDAOFactory daoFactory; + + @Resource(name = ComponentNames.DSS_FACTORY) + private IDataStoreServiceFactory dssFactory; protected AbstractBusinessObjectFactory() { } - protected AbstractBusinessObjectFactory(final IDAOFactory daoFactory) + protected AbstractBusinessObjectFactory(final IDAOFactory daoFactory, IDataStoreServiceFactory dssFactory) { this.daoFactory = daoFactory; + this.dssFactory = dssFactory; } protected final IDAOFactory getDaoFactory() { return daoFactory; } + + protected final IDataStoreServiceFactory getDSSFactory() + { + return dssFactory; + } } \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBO.java index f954a03f56126158cff8db8d9d64300af97c82a1..8ab996f977bcab55af0bd88afbdf88b724b05a13 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBO.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBO.java @@ -115,6 +115,7 @@ public class ExternalDataBO extends AbstractExternalDataBusinessObject implement .getStorageFormat())); externalData.setLocatorType(getLocatorTypeDAO().tryToFindLocatorTypeByCode( locatorType.getCode())); + externalData.setDataStore(getDataStoreDAO().tryToFindDataStoreByCode(data.getDataStoreCode())); defineDataSetProperties(externalData, convertToDataSetProperties(data .getDataSetProperties())); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTable.java index c3854676661ed1cdfb4411204b56296f5c745670..1010523250504d32a32de2bd1f28c0a3d12cc305 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTable.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTable.java @@ -17,23 +17,24 @@ package ch.systemsx.cisd.openbis.generic.server.business.bo; import java.util.ArrayList; -import java.util.Collection; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; import ch.rinn.restrictions.Private; import ch.systemsx.cisd.common.exceptions.UserFailureException; -import ch.systemsx.cisd.openbis.generic.server.business.DataStoreServerSessionManager; +import ch.systemsx.cisd.openbis.generic.server.IDataStoreServiceFactory; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExternalDataDAO; import ch.systemsx.cisd.openbis.generic.shared.IDataStoreService; import ch.systemsx.cisd.openbis.generic.shared.basic.BasicConstant; import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE; import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetUploadContext; -import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServerSession; +import ch.systemsx.cisd.openbis.generic.shared.dto.DataStorePE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE; @@ -84,12 +85,15 @@ public final class ExternalDataTable extends AbstractExternalDataBusinessObject return builder.toString(); } + private final IDataStoreServiceFactory dssFactory; private List<ExternalDataPE> externalData; - public ExternalDataTable(final IDAOFactory daoFactory, final Session session) + public ExternalDataTable(final IDAOFactory daoFactory, IDataStoreServiceFactory dssFactory, + final Session session) { super(daoFactory, session); + this.dssFactory = dssFactory; } // @@ -157,63 +161,62 @@ public final class ExternalDataTable extends AbstractExternalDataBusinessObject } } - public void deleteLoadedDataSets(DataStoreServerSessionManager dssSessionManager, String reason) + public void deleteLoadedDataSets(String reason) { - assertDataSetsAreKnown(dssSessionManager); - for (ExternalDataPE dataSet : externalData) - { - IExternalDataDAO externalDataDAO = getExternalDataDAO(); - externalDataDAO.markAsDeleted(dataSet, session.tryGetPerson(), DELETION_DESCRIPTION, reason); - } - Collection<DataStoreServerSession> sessions = dssSessionManager.getSessions(); - List<String> locations = getLocations(); - for (DataStoreServerSession dssSession : sessions) + Map<DataStorePE, List<ExternalDataPE>> map = groupDataSetsByDataStores(); + assertDataSetsAreKnown(map); + IExternalDataDAO externalDataDAO = getExternalDataDAO(); + for (Map.Entry<DataStorePE, List<ExternalDataPE>> entry : map.entrySet()) { - dssSession.getService().deleteDataSets(dssSession.getSessionToken(), locations); + DataStorePE dataStore = entry.getKey(); + List<ExternalDataPE> dataSets = entry.getValue(); + for (ExternalDataPE dataSet : dataSets) + { + externalDataDAO.markAsDeleted(dataSet, session.tryGetPerson(), DELETION_DESCRIPTION, reason); + } + deleteDataSets(dataStore, getLocations(dataSets)); } } - public void uploadLoadedDataSetsToCIFEX(DataStoreServerSessionManager dssSessionManager, - DataSetUploadContext uploadContext) + public void uploadLoadedDataSetsToCIFEX(DataSetUploadContext uploadContext) { - assertDataSetsAreKnown(dssSessionManager); - Collection<DataStoreServerSession> sessions = dssSessionManager.getSessions(); + Map<DataStorePE, List<ExternalDataPE>> map = groupDataSetsByDataStores(); + assertDataSetsAreKnown(map); uploadContext.setUserEMail(session.getPrincipal().getEmail()); if (StringUtils.isBlank(uploadContext.getComment())) { uploadContext.setComment(createUploadComment(externalData)); } - for (ExternalDataPE dataSet : externalData) + for (Map.Entry<DataStorePE, List<ExternalDataPE>> entry : map.entrySet()) { - HibernateUtils.initialize(dataSet.getParents()); - SamplePE sample = dataSet.getAssociatedSample(); - ExperimentPE experiment; - if (sample != null) + DataStorePE dataStore = entry.getKey(); + List<ExternalDataPE> dataSets = entry.getValue(); + for (ExternalDataPE dataSet : dataSets) { - experiment = sample.getExperiment(); - } else - { - experiment = dataSet.getExperiment(); + HibernateUtils.initialize(dataSet.getParents()); + SamplePE sample = dataSet.getAssociatedSample(); + ExperimentPE experiment; + if (sample != null) + { + experiment = sample.getExperiment(); + } else + { + experiment = dataSet.getExperiment(); + } + HibernateUtils.initialize(experiment.getProject().getGroup()); } - HibernateUtils.initialize(experiment.getProject().getGroup()); - } - for (DataStoreServerSession dssSession : sessions) - { - dssSession.getService().uploadDataSetsToCIFEX(dssSession.getSessionToken(), externalData, - uploadContext); + uploadDataSetsToCIFEX(dataStore, dataSets, uploadContext); } } - private void assertDataSetsAreKnown(DataStoreServerSessionManager dssSessionManager) + private void assertDataSetsAreKnown(Map<DataStorePE, List<ExternalDataPE>> map) { - List<String> locations = getLocations(); Set<String> knownLocations = new LinkedHashSet<String>(); - Collection<DataStoreServerSession> sessions = dssSessionManager.getSessions(); - for (DataStoreServerSession dssSession : sessions) + for (Map.Entry<DataStorePE, List<ExternalDataPE>> entry : map.entrySet()) { - IDataStoreService service = dssSession.getService(); - String dssSessionToken = dssSession.getSessionToken(); - knownLocations.addAll(service.getKnownDataSets(dssSessionToken, locations)); + DataStorePE dataStore = entry.getKey(); + List<String> locations = getLocations(entry.getValue()); + knownLocations.addAll(getKnownDataSets(dataStore, locations)); } List<String> unknownDataSets = new ArrayList<String>(); for (ExternalDataPE dataSet : externalData) @@ -232,13 +235,52 @@ public final class ExternalDataTable extends AbstractExternalDataBusinessObject } } - private List<String> getLocations() + private Map<DataStorePE, List<ExternalDataPE>> groupDataSetsByDataStores() { - List<String> locations = new ArrayList<String>(); + Map<DataStorePE, List<ExternalDataPE>> map = new LinkedHashMap<DataStorePE, List<ExternalDataPE>>(); for (ExternalDataPE dataSet : externalData) + { + DataStorePE dataStore = dataSet.getDataStore(); + List<ExternalDataPE> list = map.get(dataStore); + if (list == null) + { + list = new ArrayList<ExternalDataPE>(); + map.put(dataStore, list); + } + list.add(dataSet); + } + return map; + } + + private List<String> getLocations(List<ExternalDataPE> dataSets) + { + List<String> locations = new ArrayList<String>(); + for (ExternalDataPE dataSet : dataSets) { locations.add(dataSet.getLocation()); } return locations; } + + private void uploadDataSetsToCIFEX(DataStorePE dataStore, List<ExternalDataPE> dataSets, + DataSetUploadContext context) + { + IDataStoreService service = dssFactory.create(dataStore.getRemoteUrl()); + String sessionToken = dataStore.getSessionToken(); + service.uploadDataSetsToCIFEX(sessionToken, dataSets, context); + } + + private void deleteDataSets(DataStorePE dataStore, List<String> locations) + { + IDataStoreService service = dssFactory.create(dataStore.getRemoteUrl()); + String sessionToken = dataStore.getSessionToken(); + service.deleteDataSets(sessionToken, locations); + } + + private List<String> getKnownDataSets(DataStorePE dataStore, List<String> locations) + { + IDataStoreService service = dssFactory.create(dataStore.getRemoteUrl()); + String sessionToken = dataStore.getSessionToken(); + return service.getKnownDataSets(sessionToken, locations); + } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExternalDataTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExternalDataTable.java index d9d1a91dc82e6d4d6889f1217776506bd5e7b774..14796d990b23c3f0a537d859fa25fb253c97d84e 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExternalDataTable.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExternalDataTable.java @@ -18,7 +18,6 @@ package ch.systemsx.cisd.openbis.generic.server.business.bo; import java.util.List; -import ch.systemsx.cisd.openbis.generic.server.business.DataStoreServerSessionManager; import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetUploadContext; import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier; @@ -58,16 +57,13 @@ public interface IExternalDataTable void setExternalData(List<ExternalDataPE> externalData); /** - * Deletes loaded data sets for specified reason on all Data Store Servers registered - * at specified manager. + * Deletes loaded data sets for specified reason. */ - void deleteLoadedDataSets(DataStoreServerSessionManager dssSessionManager, String reason); + void deleteLoadedDataSets(String reason); /** - * Uploads loaded data sets to CIFEX server of specified URL using specified upload - * context. + * Uploads loaded data sets to CIFEX server as specified in the upload context. */ - void uploadLoadedDataSetsToCIFEX(DataStoreServerSessionManager dssSessionManager, - DataSetUploadContext uploadContext); + void uploadLoadedDataSetsToCIFEX(DataSetUploadContext uploadContext); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDAOFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDAOFactory.java index a9afc29f50e27a213b273675f50607d0bc8f9080..ca0672a77d7b85c25ce826dcfa28d2262508a682 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDAOFactory.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDAOFactory.java @@ -91,5 +91,8 @@ public interface IDAOFactory extends IAuthorizationDAOFactory /** Returns an implementation of {@link ICodeSequenceDAO} */ public ICodeSequenceDAO getCodeSequenceDAO(); + + /** Returns an implementation of {@link IDataStoreDAO}. */ + public IDataStoreDAO getDataStoreDAO(); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDataStoreDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDataStoreDAO.java new file mode 100644 index 0000000000000000000000000000000000000000..8463e7abf8274289e0738416591c05259d249e46 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDataStoreDAO.java @@ -0,0 +1,37 @@ +/* + * Copyright 2009 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.generic.server.dataaccess; + +import ch.systemsx.cisd.openbis.generic.shared.dto.DataStorePE; + +/** + * <i>Data Access Object</i> for {@link DataStorePE}. + * + * @author Franz-Josef Elmer + */ +public interface IDataStoreDAO +{ + /** + * Creates or updates specified data store. + */ + public void createOrUpdateDataStore(DataStorePE dataStore); + + /** + * Tries to returns specified data store or <code>null</code> if not found. + */ + public DataStorePE tryToFindDataStoreByCode(String dataStoreCode); +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java index 459058f29b8f6e8b096c5a2ec9cbdd2d21ef2464..73d4c8b3bbf6cfe448351caaee45cd7a2b98a79b 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java @@ -24,6 +24,7 @@ import org.hibernate.SessionFactory; import ch.systemsx.cisd.dbmigration.DatabaseConfigurationContext; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataSetTypeDAO; +import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataStoreDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityPropertyTypeDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityTypeDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IAttachmentDAO; @@ -79,6 +80,8 @@ public final class DAOFactory extends AuthorizationDAOFactory implements IDAOFac private final IMaterialDAO materialDAO; private final ICodeSequenceDAO codeSequenceDAO; + + private final IDataStoreDAO dataStoreDAO; public DAOFactory(final DatabaseConfigurationContext context, final SessionFactory sessionFactory) @@ -98,6 +101,7 @@ public final class DAOFactory extends AuthorizationDAOFactory implements IDAOFac locatorTypeDAO = new LocatorTypeDAO(sessionFactory, databaseInstance); materialDAO = new MaterialDAO(sessionFactory, databaseInstance); codeSequenceDAO = new CodeSequenceDAO(sessionFactory, databaseInstance); + dataStoreDAO = new DataStoreDAO(sessionFactory, databaseInstance); final EntityKind[] entityKinds = EntityKind.values(); for (final EntityKind entityKind : entityKinds) { @@ -187,4 +191,9 @@ public final class DAOFactory extends AuthorizationDAOFactory implements IDAOFac { return codeSequenceDAO; } + + public IDataStoreDAO getDataStoreDAO() + { + return dataStoreDAO; + } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DataStoreDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DataStoreDAO.java new file mode 100644 index 0000000000000000000000000000000000000000..c868b2c5a9a013664a9c44a7008a831b660d4ca5 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DataStoreDAO.java @@ -0,0 +1,69 @@ +/* + * Copyright 2009 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.generic.server.dataaccess.db; + +import org.apache.log4j.Logger; +import org.hibernate.Criteria; +import org.hibernate.SessionFactory; +import org.hibernate.criterion.Restrictions; +import org.springframework.orm.hibernate3.HibernateTemplate; + +import ch.systemsx.cisd.common.logging.LogCategory; +import ch.systemsx.cisd.common.logging.LogFactory; +import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataStoreDAO; +import ch.systemsx.cisd.openbis.generic.shared.dto.CodeConverter; +import ch.systemsx.cisd.openbis.generic.shared.dto.DataStorePE; +import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE; + +/** + * Hibernate-based implementation of {@link IDataStoreDAO}. + * + * @author Franz-Josef Elmer + */ +public class DataStoreDAO extends AbstractDAO implements IDataStoreDAO +{ + private static final Logger operationLog = + LogFactory.getLogger(LogCategory.OPERATION, DataStoreDAO.class); + + public DataStoreDAO(SessionFactory sessionFactory, DatabaseInstancePE databaseInstance) + { + super(sessionFactory, databaseInstance); + } + + public void createOrUpdateDataStore(DataStorePE dataStore) + { + assert dataStore != null : "Unspecified data store"; + + HibernateTemplate template = getHibernateTemplate(); + template.saveOrUpdate(dataStore); + template.flush(); + if (operationLog.isInfoEnabled()) + { + operationLog.info(String.format("SAVE/UPDATE: data store '%s'.", dataStore)); + } + } + + public DataStorePE tryToFindDataStoreByCode(String dataStoreCode) + { + assert dataStoreCode != null : "Unspecified data store code."; + + final Criteria criteria = getSession().createCriteria(DataStorePE.class); + criteria.add(Restrictions.eq("code", CodeConverter.tryToDatabase(dataStoreCode))); + return (DataStorePE) criteria.uniqueResult(); + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/plugin/IDataSetTypeSlaveServerPlugin.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/plugin/IDataSetTypeSlaveServerPlugin.java index 7f8bf05d36f1ebecd73c4966d1830c9da712af15..491aef5de97d9a6bb4d0e7888ab94b029fbab711 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/plugin/IDataSetTypeSlaveServerPlugin.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/plugin/IDataSetTypeSlaveServerPlugin.java @@ -18,7 +18,6 @@ package ch.systemsx.cisd.openbis.generic.server.plugin; import java.util.List; -import ch.systemsx.cisd.openbis.generic.server.business.DataStoreServerSessionManager; import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.DAOFactory; import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE; import ch.systemsx.cisd.openbis.generic.shared.dto.Session; @@ -36,10 +35,8 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.Session; public interface IDataSetTypeSlaveServerPlugin { /** - * Deletes the specified data sets for the specified reason on all Data Store Servers - * managed by the specifed DSS manager. + * Deletes the specified data sets for the specified reason. */ - public void deleteDataSets(Session session, DataStoreServerSessionManager dssSessionManager, - List<ExternalDataPE> dataSets, String reason); + public void deleteDataSets(Session session, List<ExternalDataPE> dataSets, String reason); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java index 168f9c59fcceaf557541d62bdde55264cc9c72fa..b71514b52150fdc2c85a8791b4bf7d5f637ba6c5 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java @@ -16,8 +16,6 @@ package ch.systemsx.cisd.openbis.generic.shared; -import javax.servlet.http.HttpServletRequest; - import org.springframework.transaction.annotation.Transactional; import ch.systemsx.cisd.common.exceptions.UserFailureException; @@ -26,6 +24,7 @@ import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.Authoriz import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RoleSet; import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RolesAllowed; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.SampleOwnerIdentifierPredicate; +import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServerInfo; import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalData; @@ -49,13 +48,11 @@ public interface IETLLIMSService extends IWebService, ISessionProvider public DatabaseInstancePE getHomeDatabaseInstance(final String sessionToken); /** - * Registers a Data Store Server for the specified port and DSS session token. - * It should be reachable via this port and the DSS session token should be used when invoking - * methods. Note, that the host can be inferred by the asking {@link HttpServletRequest}. + * Registers a Data Store Server for the specified info. */ @Transactional @RolesAllowed(RoleSet.ETL_SERVER) - public void registerDataStoreServer(String sessionToken, int port, String dssSessionToken); + public void registerDataStoreServer(String sessionToken, DataStoreServerInfo dataStoreServerInfo); /** * Gets an {@link ExperimentPE} object specified by experiment ID and sample code. diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataStorePE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataStorePE.java index 83b53229095d10aa0b1937ed0d68050413590c8f..53008088c819ce7238483e001b1a48d7847f65e9 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataStorePE.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataStorePE.java @@ -20,11 +20,15 @@ import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; import javax.persistence.SequenceGenerator; import javax.persistence.Table; +import javax.persistence.Version; import org.hibernate.annotations.Generated; import org.hibernate.annotations.GenerationTime; @@ -61,6 +65,10 @@ public final class DataStorePE extends AbstractIdAndCodeHolder<DataStorePE> private String sessionToken; + private DatabaseInstancePE databaseInstance; + + private Date modificationDate; + public final void setId(final Long id) { this.id = id; @@ -119,6 +127,31 @@ public final class DataStorePE extends AbstractIdAndCodeHolder<DataStorePE> this.registrationDate = registrationDate; } + @Version + @Column(name = ColumnNames.MODIFICATION_TIMESTAMP_COLUMN, nullable = false) + public Date getModificationDate() + { + return modificationDate; + } + + public void setModificationDate(Date versionDate) + { + this.modificationDate = versionDate; + } + + @ManyToOne(fetch = FetchType.EAGER) + @NotNull(message = ValidationMessages.DATABASE_INSTANCE_NOT_NULL_MESSAGE) + @JoinColumn(name = ColumnNames.DATABASE_INSTANCE_COLUMN, updatable = false) + public DatabaseInstancePE getDatabaseInstance() + { + return databaseInstance; + } + + public void setDatabaseInstance(final DatabaseInstancePE databaseInstance) + { + this.databaseInstance = databaseInstance; + } + // // AbstractIdAndCodeHolder // diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataStoreServerInfo.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataStoreServerInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..1dd0584d7e0ea0203903ab5a57f37f65afffd9d8 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataStoreServerInfo.java @@ -0,0 +1,92 @@ +/* + * Copyright 2009 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.generic.shared.dto; + +import java.io.Serializable; + +import javax.servlet.http.HttpServletRequest; + +import ch.systemsx.cisd.openbis.generic.shared.GenericSharedConstants; + +/** + * Information about a data store server (DSS) needed by openBIS server. + * <p> + * It contains + * <ul> + * <li>the port on which the DSS is reachable. Note, that the host can be inferred by the asking + * {@link HttpServletRequest}. + * <li>the DSS session token which has to used when invoking methods on the DSS. + * <li>the download URL which is the URL at which the DSS Web server can be accessed from a Web + * browser. + * <li>the unique code of the DSS. + * </ul> + * + * @author Franz-Josef Elmer + */ +public class DataStoreServerInfo implements Serializable +{ + private static final long serialVersionUID = GenericSharedConstants.VERSION; + + private int port; + + private String dataStoreCode; + + private String downloadUrl; + + private String sessionToken; + + public final int getPort() + { + return port; + } + + public final void setPort(int port) + { + this.port = port; + } + + public final String getDataStoreCode() + { + return dataStoreCode; + } + + public final void setDataStoreCode(String dataStoreCode) + { + this.dataStoreCode = dataStoreCode; + } + + public final String getDownloadUrl() + { + return downloadUrl; + } + + public final void setDownloadUrl(String downloadUrl) + { + this.downloadUrl = downloadUrl; + } + + public final String getSessionToken() + { + return sessionToken; + } + + public final void setSessionToken(String sessionToken) + { + this.sessionToken = sessionToken; + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataStoreServerSession.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataStoreServerSession.java deleted file mode 100644 index a1be4426d5a649153089540d7a6d677d84b5f32c..0000000000000000000000000000000000000000 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataStoreServerSession.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2009 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.generic.shared.dto; - -import java.io.Serializable; - -import ch.systemsx.cisd.openbis.generic.shared.IDataStoreService; - -/** - * Class for session on a Data Store Server. - * - * @author Franz-Josef Elmer - */ -public class DataStoreServerSession implements Serializable -{ - private static final long serialVersionUID = 1L; - - private final String dataStoreServerURL; - private final IDataStoreService service; - - private String sessionToken; - - public DataStoreServerSession(String dataStoreServerURL, IDataStoreService service) - { - this.dataStoreServerURL = dataStoreServerURL; - this.service = service; - } - - public final String getDataStoreServerURL() - { - return dataStoreServerURL; - } - - public final String getSessionToken() - { - return sessionToken; - } - - public final void setSessionToken(String sessionToken) - { - this.sessionToken = sessionToken; - } - - public final IDataStoreService getService() - { - return service; - } - -} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExternalData.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExternalData.java index 780f052840b2d258c4ae1a873037bb56c23454c8..9f3c426555e3693dbb9f5436998991b74666f84c 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExternalData.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExternalData.java @@ -50,6 +50,8 @@ public final class ExternalData extends ExtractableData private String associatedSampleCode; + private String dataStoreCode; + private boolean measured; /** Returns <code>dataSetType</code>. */ @@ -159,6 +161,16 @@ public final class ExternalData extends ExtractableData this.associatedSampleCode = sampleCode; } + public final String getDataStoreCode() + { + return dataStoreCode; + } + + public final void setDataStoreCode(String dataStoreCode) + { + this.dataStoreCode = dataStoreCode; + } + public final boolean isMeasured() { return measured; diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericDataSetTypeSlaveServerPlugin.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericDataSetTypeSlaveServerPlugin.java index b1d5a8267f2499d9d66f198fe6506ff8c82bb396..04e948808a44428a3803956af2c67b1609e76a4e 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericDataSetTypeSlaveServerPlugin.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericDataSetTypeSlaveServerPlugin.java @@ -23,7 +23,6 @@ import javax.annotation.Resource; import org.springframework.stereotype.Component; import ch.rinn.restrictions.Private; -import ch.systemsx.cisd.openbis.generic.server.business.DataStoreServerSessionManager; import ch.systemsx.cisd.openbis.generic.server.business.bo.IExternalDataTable; import ch.systemsx.cisd.openbis.generic.server.plugin.IDataSetTypeSlaveServerPlugin; import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE; @@ -47,12 +46,11 @@ public class GenericDataSetTypeSlaveServerPlugin implements IDataSetTypeSlaveSer { } - public void deleteDataSets(Session session, DataStoreServerSessionManager dssSessionManager, - List<ExternalDataPE> dataSets, String reason) + public void deleteDataSets(Session session, List<ExternalDataPE> dataSets, String reason) { IExternalDataTable externalDataTable = businessObjectFactory.createExternalDataTable(session); externalDataTable.setExternalData(dataSets); - externalDataTable.deleteLoadedDataSets(dssSessionManager, reason); + externalDataTable.deleteLoadedDataSets(reason); } diff --git a/openbis/source/java/genericApplicationContext.xml b/openbis/source/java/genericApplicationContext.xml index 7f12f487957afe1c68772f1f2e53bf68ac56ba49..e11302dc5bdb9c5a3245c8ee59bc33741db97b74 100644 --- a/openbis/source/java/genericApplicationContext.xml +++ b/openbis/source/java/genericApplicationContext.xml @@ -36,6 +36,8 @@ <constructor-arg ref="db-configuration-context" /> <constructor-arg ref="hibernate-session-factory" /> </bean> + + <bean id="dss-factory" class="ch.systemsx.cisd.openbis.generic.server.DataStoreServiceFactory"/> <bean id="authentication-service" class="ch.systemsx.cisd.openbis.generic.server.AuthenticationServiceHolder"> @@ -62,6 +64,7 @@ <bean id="common-business-object-factory" class="ch.systemsx.cisd.openbis.generic.server.CommonBusinessObjectFactory"> <constructor-arg ref="dao-factory" /> + <constructor-arg ref="dss-factory" /> </bean> <bean id="last-modification-state" @@ -74,7 +77,6 @@ <bean id="common-server" class="ch.systemsx.cisd.openbis.generic.server.CommonServer"> <constructor-arg ref="authentication-service" /> <constructor-arg ref="session-manager" /> - <constructor-arg ref="dss-session-manager" /> <constructor-arg ref="dao-factory" /> <constructor-arg ref="common-business-object-factory" /> <constructor-arg ref="last-modification-state" /> @@ -100,9 +102,9 @@ <property name="target"> <bean class="ch.systemsx.cisd.openbis.generic.server.ETLService"> <constructor-arg ref="session-manager" /> - <constructor-arg ref="dss-session-manager" /> <constructor-arg ref="dao-factory" /> <constructor-arg ref="common-business-object-factory" /> + <constructor-arg ref="dss-factory" /> </bean> </property> <property name="interceptorNames"> @@ -113,8 +115,6 @@ </property> </bean> - <bean id="dss-session-manager" class="ch.systemsx.cisd.openbis.generic.server.business.DataStoreServerSessionManager"/> - <bean id="exception-translator" class="ch.systemsx.cisd.common.spring.ServiceExceptionTranslator"> <property name="packagesNotMasqueraded"> diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java index d3125f8aa33b3fd5cf4db8f42646f64cc48f3d04..f01e822c63c7c3c32f11cb2fd474d977aadce478 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java @@ -27,7 +27,6 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import ch.systemsx.cisd.common.exceptions.UserFailureException; -import ch.systemsx.cisd.openbis.generic.server.business.DataStoreServerSessionManager; import ch.systemsx.cisd.openbis.generic.server.business.bo.ICommonBusinessObjectFactory; import ch.systemsx.cisd.openbis.generic.server.plugin.IDataSetTypeSlaveServerPlugin; import ch.systemsx.cisd.openbis.generic.server.plugin.ISampleTypeSlaveServerPlugin; @@ -91,15 +90,13 @@ public final class CommonServerTest extends AbstractServerTestCase private ICommonBusinessObjectFactory commonBusinessObjectFactory; - private DataStoreServerSessionManager dssSessionManager; - private ISampleTypeSlaveServerPlugin sampleTypeSlaveServerPlugin; private IDataSetTypeSlaveServerPlugin dataSetTypeSlaveServerPlugin; private final ICommonServer createServer() { - CommonServer server = new CommonServer(authenticationService, sessionManager, dssSessionManager, + CommonServer server = new CommonServer(authenticationService, sessionManager, daoFactory, commonBusinessObjectFactory, new LastModificationState()); server.setSampleTypeSlaveServerPlugin(sampleTypeSlaveServerPlugin); server.setDataSetTypeSlaveServerPlugin(dataSetTypeSlaveServerPlugin); @@ -122,7 +119,6 @@ public final class CommonServerTest extends AbstractServerTestCase public final void setUp() { super.setUp(); - dssSessionManager = new DataStoreServerSessionManager(); commonBusinessObjectFactory = context.mock(ICommonBusinessObjectFactory.class); sampleTypeSlaveServerPlugin = context.mock(ISampleTypeSlaveServerPlugin.class); dataSetTypeSlaveServerPlugin = context.mock(IDataSetTypeSlaveServerPlugin.class); @@ -871,10 +867,10 @@ public final class CommonServerTest extends AbstractServerTestCase ExternalDataPE ds3 = createDataSet("ds3", "type2"); will(returnValue(Arrays.asList(ds1, ds2, ds3))); - one(dataSetTypeSlaveServerPlugin).deleteDataSets(SESSION, dssSessionManager, - Arrays.asList(ds1, ds2), "reason"); - one(dataSetTypeSlaveServerPlugin).deleteDataSets(SESSION, dssSessionManager, - Arrays.asList(ds3), "reason"); + one(dataSetTypeSlaveServerPlugin).deleteDataSets(SESSION, Arrays.asList(ds1, ds2), + "reason"); + one(dataSetTypeSlaveServerPlugin).deleteDataSets(SESSION, Arrays.asList(ds3), + "reason"); } }); @@ -907,8 +903,7 @@ public final class CommonServerTest extends AbstractServerTestCase will(returnValue(externalDataTable)); one(externalDataTable).loadByDataSetCodes(dataSetCodes); - one(externalDataTable).uploadLoadedDataSetsToCIFEX(dssSessionManager, - uploadContext); + one(externalDataTable).uploadLoadedDataSetsToCIFEX(uploadContext); } }); diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java index 95a178b81587150ed1fcdb99b6129703c06e8eab..6e38458396d5d959f9dbb92755dffdac29ac4a8f 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/ETLServiceTest.java @@ -22,6 +22,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashSet; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; import org.jmock.Expectations; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -29,14 +31,15 @@ import org.testng.annotations.Test; import ch.rinn.restrictions.Friend; import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException; import ch.systemsx.cisd.common.exceptions.UserFailureException; -import ch.systemsx.cisd.openbis.generic.server.business.DataStoreServerSessionManager; import ch.systemsx.cisd.openbis.generic.server.business.bo.ICommonBusinessObjectFactory; +import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataStoreDAO; import ch.systemsx.cisd.openbis.generic.shared.AbstractServerTestCase; import ch.systemsx.cisd.openbis.generic.shared.IDataStoreService; import ch.systemsx.cisd.openbis.generic.shared.IETLLIMSService; import ch.systemsx.cisd.openbis.generic.shared.dto.AttachmentContentPE; import ch.systemsx.cisd.openbis.generic.shared.dto.AttachmentPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServerSession; +import ch.systemsx.cisd.openbis.generic.shared.dto.DataStorePE; +import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServerInfo; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalData; import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE; @@ -56,67 +59,139 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier; @Friend(toClasses=ETLService.class) public class ETLServiceTest extends AbstractServerTestCase { + private static final String DOWNLOAD_URL = "download-url"; + private static final String DSS_CODE = "my-dss"; + private static final String DSS_SESSION_TOKEN = "dss42"; + private static final int PORT = 443; + private static final String URL = "https://" + SESSION.getRemoteHost() + ":" + PORT; private ICommonBusinessObjectFactory boFactory; - private DataStoreServerSessionManager dssSessionManager; private IDataStoreServiceFactory dssfactory; private IDataStoreService dataStoreService; + private IDataStoreDAO dataStoreDAO; @Override @BeforeMethod public final void setUp() { super.setUp(); - dssSessionManager = new DataStoreServerSessionManager(); boFactory = context.mock(ICommonBusinessObjectFactory.class); dssfactory = context.mock(IDataStoreServiceFactory.class); dataStoreService = context.mock(IDataStoreService.class); + dataStoreDAO = context.mock(IDataStoreDAO.class); } @Test public void testRegisterDataStoreServer() { - final String url = "https://" + SESSION.getRemoteHost() + ":443"; - final String dssToken = "dss42"; prepareGetSession(); context.checking(new Expectations() { { - one(dssfactory).create(url); + one(daoFactory).getDataStoreDAO(); + will(returnValue(dataStoreDAO)); + + one(dataStoreDAO).tryToFindDataStoreByCode(DSS_CODE); + will(returnValue(null)); + + one(dssfactory).create(URL); will(returnValue(dataStoreService)); - one(dataStoreService).getVersion(dssToken); + one(dataStoreService).getVersion(DSS_SESSION_TOKEN); will(returnValue(IDataStoreService.VERSION)); + + one(dataStoreDAO).createOrUpdateDataStore(with(new BaseMatcher<DataStorePE>() + { + public void describeTo(Description description) + { + } + + public boolean matches(Object item) + { + if (item instanceof DataStorePE) + { + DataStorePE store = (DataStorePE) item; + return DSS_CODE.equals(store.getCode()) + && URL.equals(store.getRemoteUrl()) + && DOWNLOAD_URL.equals(store.getDownloadUrl()) + && DSS_SESSION_TOKEN.equals(store.getSessionToken()); + } + return false; + } + + })); } }); - createService().registerDataStoreServer(SESSION_TOKEN, 443, dssToken); - - DataStoreServerSession session = dssSessionManager.tryToGetSession(url); - assertEquals(dssToken, session.getSessionToken()); + createService().registerDataStoreServer(SESSION_TOKEN, createDSSInfo()); context.assertIsSatisfied(); } + @Test + public void testRegisterDataStoreServerAgain() + { + prepareGetSession(); + context.checking(new Expectations() + { + { + one(daoFactory).getDataStoreDAO(); + will(returnValue(dataStoreDAO)); + + one(dataStoreDAO).tryToFindDataStoreByCode(DSS_CODE); + will(returnValue(new DataStorePE())); + + one(dataStoreDAO).createOrUpdateDataStore(with(new BaseMatcher<DataStorePE>() + { + public void describeTo(Description description) + { + } + + public boolean matches(Object item) + { + if (item instanceof DataStorePE) + { + DataStorePE store = (DataStorePE) item; + return DSS_CODE.equals(store.getCode()) + && URL.equals(store.getRemoteUrl()) + && DOWNLOAD_URL.equals(store.getDownloadUrl()) + && DSS_SESSION_TOKEN.equals(store.getSessionToken()); + } + return false; + } + + })); + } + }); + + createService().registerDataStoreServer(SESSION_TOKEN, createDSSInfo()); + + context.assertIsSatisfied(); + } + @Test public void testRegisterDataStoreServerWithWrongVersion() { - final String url = "https://" + SESSION.getRemoteHost() + ":443"; - final String dssToken = "dss42"; prepareGetSession(); context.checking(new Expectations() { { - one(dssfactory).create(url); + one(daoFactory).getDataStoreDAO(); + will(returnValue(dataStoreDAO)); + + one(dataStoreDAO).tryToFindDataStoreByCode(DSS_CODE); + will(returnValue(null)); + + one(dssfactory).create(URL); will(returnValue(dataStoreService)); - one(dataStoreService).getVersion(dssToken); + one(dataStoreService).getVersion(DSS_SESSION_TOKEN); will(returnValue(VERSION + 1)); } }); try { - createService().registerDataStoreServer(SESSION_TOKEN, 443, dssToken); + createService().registerDataStoreServer(SESSION_TOKEN, createDSSInfo()); fail("ConfigurationFailureException expected"); } catch (ConfigurationFailureException e) { @@ -462,6 +537,16 @@ public class ETLServiceTest extends AbstractServerTestCase private IETLLIMSService createService() { - return new ETLService(sessionManager, dssSessionManager, daoFactory, boFactory, dssfactory); + return new ETLService(sessionManager, daoFactory, boFactory, dssfactory); + } + + private DataStoreServerInfo createDSSInfo() + { + DataStoreServerInfo info = new DataStoreServerInfo(); + info.setPort(PORT); + info.setSessionToken(DSS_SESSION_TOKEN); + info.setDataStoreCode(DSS_CODE); + info.setDownloadUrl(DOWNLOAD_URL); + return info; } } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBOTest.java index 51627fb72f44e2fe51b756317b9d2a8a88586d61..2ebbc10779c89b6b9e825ef66b4bb6a66aeaf7fa 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBOTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBOTest.java @@ -24,6 +24,7 @@ import org.testng.annotations.BeforeMethod; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataSetTypeDAO; +import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataStoreDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDatabaseInstanceDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityPropertyTypeDAO; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityTypeDAO; @@ -85,6 +86,8 @@ public abstract class AbstractBOTest extends AssertJUnit ILocatorTypeDAO locatorTypeDAO; + IDataStoreDAO dataStoreDAO; + @BeforeMethod public void beforeMethod() { @@ -107,6 +110,7 @@ public abstract class AbstractBOTest extends AssertJUnit dataSetTypeDAO = context.mock(IDataSetTypeDAO.class); fileFormatTypeDAO = context.mock(IFileFormatTypeDAO.class); locatorTypeDAO = context.mock(ILocatorTypeDAO.class); + dataStoreDAO = context.mock(IDataStoreDAO.class); context.checking(new Expectations() { { @@ -128,6 +132,8 @@ public abstract class AbstractBOTest extends AssertJUnit will(returnValue(locatorTypeDAO)); allowing(daoFactory).getExternalDataDAO(); will(returnValue(externalDataDAO)); + allowing(daoFactory).getDataStoreDAO(); + will(returnValue(dataStoreDAO)); } }); } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBOTest.java index 397941b759a6999da324ae14a8db0e252513dd73..af6f67b256de59112c097ad8368a087189c17391 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBOTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataBOTest.java @@ -33,6 +33,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE; import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetPropertyPE; import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetType; import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetTypePE; +import ch.systemsx.cisd.openbis.generic.shared.dto.DataStorePE; import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalData; @@ -56,6 +57,8 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.types.ProcedureTypeCode; */ public class ExternalDataBOTest extends AbstractBOTest { + private static final String DATA_STORE_CODE = "dss1"; + private static final String PARENT_CODE = "parent"; private static final Date PRODUCTION_DATE = new Date(1001); @@ -104,7 +107,7 @@ public class ExternalDataBOTest extends AbstractBOTest SamplePE sample = new SamplePE(); ExperimentPE experimentPE = new ExperimentPE(); sample.setExperiment(experimentPE); - prepareDefine(dataSetType, fileFormatType, vocabulary, locatorType); + prepareDefine(dataSetType, fileFormatType, vocabulary, locatorType, new DataStorePE()); IExternalDataBO sampleBO = createExternalDataBO(); sampleBO.define(createData(null), sample, SourceType.DERIVED); @@ -141,7 +144,8 @@ public class ExternalDataBOTest extends AbstractBOTest SamplePE sample = new SamplePE(); ExperimentPE experimentPE = new ExperimentPE(); sample.setExperiment(experimentPE); - prepareDefine(dataSetType, fileFormatType, vocabulary, locatorType); + DataStorePE dataStore = new DataStorePE(); + prepareDefine(dataSetType, fileFormatType, vocabulary, locatorType, dataStore); final DataPE data = new DataPE(); context.checking(new Expectations() { @@ -157,6 +161,7 @@ public class ExternalDataBOTest extends AbstractBOTest assertSame(sample, externalData.getSampleAcquiredFrom()); assertSame(null, externalData.getSampleDerivedFrom()); + assertSame(dataStore, externalData.getDataStore()); assertEquals(1, externalData.getParents().size()); assertSame(data, externalData.getParents().iterator().next()); context.assertIsSatisfied(); @@ -174,7 +179,8 @@ public class ExternalDataBOTest extends AbstractBOTest vocabulary.addTerm(vocabularyTerm); final LocatorTypePE locatorType = new LocatorTypePE(); final SamplePE sample = new SamplePE(); - prepareDefine(dataSetType, fileFormatType, vocabulary, locatorType); + final DataStorePE dataStore = new DataStorePE(); + prepareDefine(dataSetType, fileFormatType, vocabulary, locatorType, dataStore); final DataSetTypePE dataSetTypeUnknown = new DataSetTypePE(); final DataPE parentData = new DataPE(); parentData.setCode(PARENT_CODE); @@ -202,6 +208,7 @@ public class ExternalDataBOTest extends AbstractBOTest assertSame(sample, externalData.getSampleAcquiredFrom()); assertSame(null, externalData.getSampleDerivedFrom()); + assertSame(dataStore, externalData.getDataStore()); assertEquals(1, externalData.getParents().size()); assertEquals(parentData, externalData.getParents().iterator().next()); context.assertIsSatisfied(); @@ -219,7 +226,8 @@ public class ExternalDataBOTest extends AbstractBOTest vocabulary.addTerm(vocabularyTerm); final LocatorTypePE locatorType = new LocatorTypePE(); final SamplePE data = new SamplePE(); - prepareDefine(dataSetType, fileFormatType, vocabulary, locatorType); + final DataStorePE dataStore = new DataStorePE(); + prepareDefine(dataSetType, fileFormatType, vocabulary, locatorType, dataStore); final DataSetTypePE dataSetTypeUnknown = new DataSetTypePE(); final DataPE parentData = new DataPE(); parentData.setCode(PARENT_CODE); @@ -236,7 +244,7 @@ public class ExternalDataBOTest extends AbstractBOTest one(dataSetTypeDAO).tryToFindDataSetTypeByCode( DataSetTypeCode.UNKNOWN.getCode()); will(returnValue(dataSetTypeUnknown)); - + one(externalDataDAO).createDataSet(parentData); } }); @@ -247,6 +255,7 @@ public class ExternalDataBOTest extends AbstractBOTest assertSame(data, externalData.getSampleAcquiredFrom()); assertSame(null, externalData.getSampleDerivedFrom()); + assertSame(dataStore, externalData.getDataStore()); assertEquals(1, externalData.getParents().size()); assertEquals(parentData, externalData.getParents().iterator().next()); context.assertIsSatisfied(); @@ -265,7 +274,8 @@ public class ExternalDataBOTest extends AbstractBOTest final LocatorTypePE locatorType = new LocatorTypePE(); SamplePE sample = new SamplePE(); sample.setExperiment(new ExperimentPE()); - prepareDefine(dataSetType, fileFormatType, vocabulary, locatorType); + final DataStorePE dataStore = new DataStorePE(); + prepareDefine(dataSetType, fileFormatType, vocabulary, locatorType, dataStore); context.checking(new Expectations() { { @@ -298,7 +308,8 @@ public class ExternalDataBOTest extends AbstractBOTest final LocatorTypePE locatorType = new LocatorTypePE(); SamplePE sample = new SamplePE(); sample.setExperiment(new ExperimentPE()); - prepareDefine(dataSetType, fileFormatType, vocabulary, locatorType); + final DataStorePE dataStore = new DataStorePE(); + prepareDefine(dataSetType, fileFormatType, vocabulary, locatorType, dataStore); context.checking(new Expectations() { { @@ -320,6 +331,7 @@ public class ExternalDataBOTest extends AbstractBOTest sampleBO.save(); ExternalDataPE externalData = sampleBO.getExternalData(); + assertSame(dataStore, externalData.getDataStore()); assertEquals(false, externalData.isPlaceholder()); assertEquals(4711, externalData.getId().longValue()); assertEquals(null, externalData.getSampleDerivedFrom()); @@ -359,7 +371,7 @@ public class ExternalDataBOTest extends AbstractBOTest private void prepareDefine(final DataSetTypePE dataSetType, final FileFormatTypePE fileFormatType, final VocabularyPE vocabulary, - final LocatorTypePE locatorType) + final LocatorTypePE locatorType, final DataStorePE dataStore) { context.checking(new Expectations() { @@ -378,6 +390,9 @@ public class ExternalDataBOTest extends AbstractBOTest dataSetType.getCode(), EXAMPLE_SESSION.tryGetPerson()); ArrayList<DataSetPropertyPE> properties = new ArrayList<DataSetPropertyPE>(); will(returnValue(properties)); + + one(dataStoreDAO).tryToFindDataStoreByCode(DATA_STORE_CODE); + will(returnValue(dataStore)); } }); } @@ -395,6 +410,7 @@ public class ExternalDataBOTest extends AbstractBOTest data.setFileFormatType(FILE_FORMAT_TYPE); data.setLocatorType(LOCATOR_TYPE); data.setLocation(LOCATION); + data.setDataStoreCode(DATA_STORE_CODE); return data; } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTableTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTableTest.java index 2a8079a03da72e5a30bfa20130be0670626afb0f..b0a4bb9b3f900c2342ce5a303593f95c7fa42fdd 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTableTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExternalDataTableTest.java @@ -30,13 +30,13 @@ import org.testng.annotations.Test; import ch.rinn.restrictions.Friend; import ch.systemsx.cisd.common.exceptions.UserFailureException; -import ch.systemsx.cisd.openbis.generic.server.business.DataStoreServerSessionManager; +import ch.systemsx.cisd.openbis.generic.server.IDataStoreServiceFactory; import ch.systemsx.cisd.openbis.generic.server.business.ManagerTestTool; import ch.systemsx.cisd.openbis.generic.shared.IDataStoreService; import ch.systemsx.cisd.openbis.generic.shared.basic.BasicConstant; import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE; import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetUploadContext; -import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServerSession; +import ch.systemsx.cisd.openbis.generic.shared.dto.DataStorePE; import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE; @@ -59,12 +59,15 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier; @Friend(toClasses=ExternalDataTable.class) public final class ExternalDataTableTest extends AbstractBOTest { - private DataStoreServerSessionManager dssSessionManager; - private IDataStoreService dataStoreService; + private IDataStoreServiceFactory dssFactory; + private DataStorePE dss1; + private DataStorePE dss2; + private IDataStoreService dataStoreService1; + private IDataStoreService dataStoreService2; private final ExternalDataTable createExternalDataTable() { - return new ExternalDataTable(daoFactory, ManagerTestTool.EXAMPLE_SESSION); + return new ExternalDataTable(daoFactory, dssFactory, ManagerTestTool.EXAMPLE_SESSION); } @BeforeMethod @@ -72,8 +75,21 @@ public final class ExternalDataTableTest extends AbstractBOTest public void beforeMethod() { super.beforeMethod(); - dssSessionManager = new DataStoreServerSessionManager(); - dataStoreService = context.mock(IDataStoreService.class); + dssFactory = context.mock(IDataStoreServiceFactory.class); + dss1 = createDataStore("dss1"); + dss2 = createDataStore("dss2"); + dataStoreService1 = context.mock(IDataStoreService.class, "dataStoreService1"); + dataStoreService2 = context.mock(IDataStoreService.class, "dataStoreService2"); + context.checking(new Expectations() + { + { + allowing(dssFactory).create(dss1.getRemoteUrl()); + will(returnValue(dataStoreService1)); + + allowing(dssFactory).create(dss2.getRemoteUrl()); + will(returnValue(dataStoreService2)); + } + }); } @Test @@ -215,40 +231,11 @@ public final class ExternalDataTableTest extends AbstractBOTest context.assertIsSatisfied(); } - @Test - public void testDeleteLoadedDataSetsButDataStoreServerIsDown() - { - final ExternalDataPE d1 = createDataSet("d1"); - context.checking(new Expectations() - { - { - one(externalDataDAO).tryToFindFullDataSetByCode(d1.getCode()); - will(returnValue(d1)); - } - }); - - ExternalDataTable externalDataTable = createExternalDataTable(); - externalDataTable.loadByDataSetCodes(Arrays.asList(d1.getCode())); - try - { - externalDataTable.deleteLoadedDataSets(dssSessionManager, ""); - fail("UserFailureException expected"); - } catch (UserFailureException e) - { - assertEquals( - "The following data sets are unknown by any registered Data Store Server. " - + "May be the responsible Data Store Server is not running.\n[d1]", e - .getMessage()); - } - - context.assertIsSatisfied(); - } - @Test public void testLoadByDataSetCodes() { - final ExternalDataPE d1 = createDataSet("d1"); - final ExternalDataPE d2 = createDataSet("d2"); + final ExternalDataPE d1 = createDataSet("d1", dss1); + final ExternalDataPE d2 = createDataSet("d2", dss2); context.checking(new Expectations() { { @@ -272,32 +259,32 @@ public final class ExternalDataTableTest extends AbstractBOTest @Test public void testDeleteLoadedDataSetsButOneDataSetIsUnknown() { - dssSessionManager.registerDataStoreServer(new DataStoreServerSession("url", - dataStoreService)); - final ExternalDataPE d1 = createDataSet("d1"); - final ExternalDataPE d2 = createDataSet("d2"); + final ExternalDataPE d1 = createDataSet("d1", dss1); + final ExternalDataPE d2 = createDataSet("d2", dss2); context.checking(new Expectations() - { { - one(externalDataDAO).tryToFindFullDataSetByCode(d1.getCode()); - will(returnValue(d1)); - - one(externalDataDAO).tryToFindFullDataSetByCode(d2.getCode()); - will(returnValue(d2)); - - List<String> locations = Arrays.asList(d1.getLocation(), d2.getLocation()); - one(dataStoreService).getKnownDataSets(with(any(String.class)), - with(equal(locations))); - will(returnValue(Arrays.asList(d1.getLocation()))); - - } - }); + { + one(externalDataDAO).tryToFindFullDataSetByCode(d1.getCode()); + will(returnValue(d1)); + + one(externalDataDAO).tryToFindFullDataSetByCode(d2.getCode()); + will(returnValue(d2)); + + one(dataStoreService1).getKnownDataSets(dss1.getSessionToken(), + Arrays.asList(d1.getLocation())); + will(returnValue(Arrays.asList(d1.getLocation()))); + + one(dataStoreService2).getKnownDataSets(dss2.getSessionToken(), + Arrays.asList(d2.getLocation())); + will(returnValue(Arrays.asList())); + } + }); ExternalDataTable externalDataTable = createExternalDataTable(); externalDataTable.loadByDataSetCodes(Arrays.asList(d1.getCode(), d2.getCode())); try { - externalDataTable.deleteLoadedDataSets(dssSessionManager, ""); + externalDataTable.deleteLoadedDataSets(""); fail("UserFailureException expected"); } catch (UserFailureException e) { @@ -313,10 +300,8 @@ public final class ExternalDataTableTest extends AbstractBOTest @Test public void testDeleteLoadedDataSets() { - dssSessionManager.registerDataStoreServer(new DataStoreServerSession("url", - dataStoreService)); - final ExternalDataPE d1 = createDataSet("d1"); - final ExternalDataPE d2 = createDataSet("d2"); + final ExternalDataPE d1 = createDataSet("d1", dss1); + final ExternalDataPE d2 = createDataSet("d2", dss2); context.checking(new Expectations() { { @@ -325,23 +310,27 @@ public final class ExternalDataTableTest extends AbstractBOTest one(externalDataDAO).tryToFindFullDataSetByCode(d2.getCode()); will(returnValue(d2)); + + List<String> d1Locations = Arrays.asList(d1.getLocation()); + one(dataStoreService1).getKnownDataSets(dss1.getSessionToken(), d1Locations); + will(returnValue(d1Locations)); - List<String> locations = Arrays.asList(d1.getLocation(), d2.getLocation()); - one(dataStoreService).getKnownDataSets(with(any(String.class)), - with(equal(locations))); - will(returnValue(locations)); + List<String> d2Locations = Arrays.asList(d2.getLocation()); + one(dataStoreService2).getKnownDataSets(dss2.getSessionToken(), d2Locations); + will(returnValue(d2Locations)); PersonPE person = EXAMPLE_SESSION.tryGetPerson(); one(externalDataDAO).markAsDeleted(d1, person, DELETION_DESCRIPTION, "reason"); one(externalDataDAO).markAsDeleted(d2, person, DELETION_DESCRIPTION, "reason"); - one(dataStoreService).deleteDataSets(with(any(String.class)), - with(equal(locations))); + + one(dataStoreService1).deleteDataSets(dss1.getSessionToken(), d1Locations); + one(dataStoreService2).deleteDataSets(dss2.getSessionToken(), d2Locations); } }); ExternalDataTable externalDataTable = createExternalDataTable(); externalDataTable.loadByDataSetCodes(Arrays.asList(d1.getCode(), d2.getCode())); - externalDataTable.deleteLoadedDataSets(dssSessionManager, "reason"); + externalDataTable.deleteLoadedDataSets("reason"); context.assertIsSatisfied(); } @@ -349,10 +338,8 @@ public final class ExternalDataTableTest extends AbstractBOTest @Test public void testUploadDataSets() { - dssSessionManager.registerDataStoreServer(new DataStoreServerSession("url", - dataStoreService)); - final ExternalDataPE d1 = createDataSet("d1"); - final ExternalDataPE d2 = createDataSet("d2"); + final ExternalDataPE d1 = createDataSet("d1", dss1); + final ExternalDataPE d2 = createDataSet("d2", dss2); final DataSetUploadContext uploadContext = new DataSetUploadContext(); uploadContext.setCifexURL("cifexURL"); uploadContext.setUserID(EXAMPLE_SESSION.getUserName()); @@ -367,20 +354,25 @@ public final class ExternalDataTableTest extends AbstractBOTest one(externalDataDAO).tryToFindFullDataSetByCode(d2.getCode()); will(returnValue(d2)); - - List<String> locations = Arrays.asList(d1.getLocation(), d2.getLocation()); - one(dataStoreService).getKnownDataSets(with(any(String.class)), - with(equal(locations))); - will(returnValue(locations)); - - one(dataStoreService).uploadDataSetsToCIFEX(with(any(String.class)), - with(equal(Arrays.asList(d1, d2))), with(equal(uploadContext))); + + List<String> d1Locations = Arrays.asList(d1.getLocation()); + one(dataStoreService1).getKnownDataSets(dss1.getSessionToken(), d1Locations); + will(returnValue(d1Locations)); + + List<String> d2Locations = Arrays.asList(d2.getLocation()); + one(dataStoreService2).getKnownDataSets(dss2.getSessionToken(), d2Locations); + will(returnValue(d2Locations)); + + one(dataStoreService1).uploadDataSetsToCIFEX(dss1.getSessionToken(), + Arrays.asList(d1), uploadContext); + one(dataStoreService2).uploadDataSetsToCIFEX(dss2.getSessionToken(), + Arrays.asList(d2), uploadContext); } }); ExternalDataTable externalDataTable = createExternalDataTable(); externalDataTable.loadByDataSetCodes(Arrays.asList(d1.getCode(), d2.getCode())); - externalDataTable.uploadLoadedDataSetsToCIFEX(dssSessionManager, uploadContext); + externalDataTable.uploadLoadedDataSetsToCIFEX(uploadContext); context.assertIsSatisfied(); } @@ -433,10 +425,11 @@ public final class ExternalDataTableTest extends AbstractBOTest return sequence.substring(0, codeLength - result.length()) + result; } - private ExternalDataPE createDataSet(String code) + private ExternalDataPE createDataSet(String code, DataStorePE dataStore) { ExternalDataPE data = new ExternalDataPE(); data.setCode(code); + data.setDataStore(dataStore); data.setLocation("here/" + code); ExperimentPE experiment = new ExperimentPE(); experiment.setCode("exp1"); @@ -449,4 +442,13 @@ public final class ExternalDataTableTest extends AbstractBOTest data.setExperiment(experiment); return data; } + + private DataStorePE createDataStore(String code) + { + DataStorePE dataStore = new DataStorePE(); + dataStore.setCode(code); + dataStore.setRemoteUrl("http://" + code); + dataStore.setSessionToken("session-" + code); + return dataStore; + } } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java.expected b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java.expected index 65cfa59590bde5318103fc5f53a1c95b58377681..75d8808a69397cbe60c667188a810435f7884dca 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java.expected +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/IETLLIMSService.java.expected @@ -16,8 +16,6 @@ package ch.systemsx.cisd.openbis.generic.shared; -import javax.servlet.http.HttpServletRequest; - import org.springframework.transaction.annotation.Transactional; import ch.systemsx.cisd.common.exceptions.UserFailureException; @@ -26,6 +24,7 @@ import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.Authoriz import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RoleSet; import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RolesAllowed; import ch.systemsx.cisd.openbis.generic.shared.authorization.predicate.SampleOwnerIdentifierPredicate; +import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServerInfo; import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalData; @@ -33,41 +32,85 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE; import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePropertyPE; import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier; +/** + * <b>LIMS</b> <i>Web Service</i> interface for the <b>ETL</b> (<i>Extract, Transform, Load</i>) + * server. + * + * @author Christian Ribeaud + */ public interface IETLLIMSService extends IWebService, ISessionProvider { - + /** + * Returns the home database instance. + */ @Transactional(readOnly = true) @RolesAllowed(RoleSet.ETL_SERVER) public DatabaseInstancePE getHomeDatabaseInstance(final String sessionToken); - + + /** + * Registers a Data Store Server for the specified info. + */ @Transactional @RolesAllowed(RoleSet.ETL_SERVER) - public void registerDataStoreServer(String sessionToken, int port, String dssSessionToken); - + public void registerDataStoreServer(String sessionToken, DataStoreServerInfo dataStoreServerInfo); + + /** + * Gets an {@link ExperimentPE} object specified by experiment ID and sample code. + * + * @param sessionToken the user authentication token. Must not be <code>null</code>. + * @param sampleIdentifier an identifier which uniquely identifies the sample. + * @return <code>null</code> if no experiment could be found for given <var>sampleIdentifier</var>. + */ @Transactional(readOnly = true) @RolesAllowed(RoleSet.ETL_SERVER) public ExperimentPE tryToGetBaseExperiment(final String sessionToken, @AuthorizationGuard(guardClass = SampleOwnerIdentifierPredicate.class) final SampleIdentifier sampleIdentifier) throws UserFailureException; + /** + * Tries to return the properties of the top sample (e.g. master plate) registered for the + * specified sample code. + * + * @param sessionToken the user authentication token. Must not be <code>null</code>. + * @param sampleIdentifier an identifier which uniquely identifies the sample. + * @return <code>null</code> if no appropriated sample found. Returns an empty array if a a + * sample found with no properties. + */ @Transactional(readOnly = true) @RolesAllowed(RoleSet.ETL_SERVER) public SamplePropertyPE[] tryToGetPropertiesOfTopSampleRegisteredFor(final String sessionToken, @AuthorizationGuard(guardClass = SampleOwnerIdentifierPredicate.class) final SampleIdentifier sampleIdentifier) throws UserFailureException; + /** + * Registers the specified data. + * + * @param sessionToken The user authentication token. Must not be <code>null</code>. + * @param sampleIdentifier an identifier which uniquely identifies the sample. + * @param externalData Data set to be registered. It is assumed that the attributes + * <code>location</code>, <code>fileFormatType</code>, <code>dataSetType</code>, + * and <code>locatorType</code> are not-<code>null</code>. + * @throws UserFailureException if given data set code could not be found in the persistence + * layer. + */ @Transactional @RolesAllowed(RoleSet.ETL_SERVER) public void registerDataSet(final String sessionToken, @AuthorizationGuard(guardClass = SampleOwnerIdentifierPredicate.class) final SampleIdentifier sampleIdentifier, final ExternalData externalData) throws UserFailureException; - + + /** + * Tries to return the data set specified by its code. + */ @Transactional @RolesAllowed(RoleSet.OBSERVER) public ExternalDataPE tryGetDataSet(String sessionToken, String dataSetCode) throws UserFailureException; + /** + * Creates and returns a unique code for a new data set. + */ @Transactional @RolesAllowed(RoleSet.ETL_SERVER) public String createDataSetCode(final String sessionToken) throws UserFailureException;