Skip to content
Snippets Groups Projects
Commit 7b63f644 authored by felmer's avatar felmer
Browse files

SSDM-7857: Starting a complete rewrite of data source servlet

parent 6147b489
No related branches found
No related tags found
No related merge requests found
Showing
with 1335 additions and 0 deletions
/*
* Copyright 2019 ETH Zuerich, SIS
*
* 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.ethz.sis.openbis.generic.server.dss.plugins.sync.datasource;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Function;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.apache.log4j.Logger;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.attachment.Attachment;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.ICodeHolder;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IModificationDateHolder;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IModifierHolder;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IRegistrationDateHolder;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IRegistratorHolder;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.Experiment;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.Project;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.Sample;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.Space;
import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory;
import ch.systemsx.cisd.openbis.generic.server.batch.BatchOperationExecutor;
import ch.systemsx.cisd.openbis.generic.server.batch.IBatchOperation;
/**
* @author Franz-Josef Elmer
*/
abstract class AbstractEntityDeliverer<T>
{
private static final int CHUNK_SIZE = 1000;
private static interface IConsumer<T>
{
public void consume(T t) throws XMLStreamException;
}
protected final Logger operationLog;
protected final DeliveryContext context;
private final String entityKind;
AbstractEntityDeliverer(DeliveryContext context, String entityKind)
{
this.context = context;
this.entityKind = entityKind;
operationLog = LogFactory.getLogger(LogCategory.OPERATION, getClass());
}
void deliverEntities(XMLStreamWriter writer, String sessionToken, Set<String> spaces, Date requestTimestamp) throws XMLStreamException
{
List<T> allEntities = getAllEntities(sessionToken);
executeInBatches(allEntities, entities -> deliverEntities(writer, sessionToken, spaces, entities));
}
protected List<T> getAllEntities(String sessionToken)
{
return Collections.emptyList();
}
protected void deliverEntities(XMLStreamWriter writer, String sessionToken, Set<String> spaces, List<T> entities)
throws XMLStreamException
{
}
protected void addProperties(XMLStreamWriter writer, Map<String, String> properties) throws XMLStreamException
{
if (properties.isEmpty() == false)
{
writer.writeStartElement("x:properties");
Set<Entry<String, String>> entrySet = properties.entrySet();
for (Entry<String, String> entry : entrySet)
{
writer.writeStartElement("x:property");
writer.writeStartElement("x:code");
writer.writeCharacters(entry.getKey());
writer.writeEndElement();
writer.writeStartElement("x:value");
writer.writeCharacters(entry.getValue());
writer.writeEndElement();
writer.writeEndElement();
}
writer.writeEndElement();
}
}
protected void addAttachments(XMLStreamWriter writer, List<Attachment> attachments) throws XMLStreamException
{
if (attachments.isEmpty())
{
return;
}
startBinaryDataElement(writer);
for (Attachment attachment : attachments)
{
writer.writeStartElement("x:attachment");
addAttribute(writer, "description", attachment.getDescription());
addAttribute(writer, "fileName", attachment.getFileName());
addAttribute(writer, "latestVersion", attachment.getVersion(), v -> Integer.toString(v));
addAttribute(writer, "permLink", attachment.getPermlink());
addAttribute(writer, "title", attachment.getTitle());
writer.writeEndElement();
}
writer.writeEndElement();
}
protected void addSpace(XMLStreamWriter writer, Space space) throws XMLStreamException
{
addAttribute(writer, "space", space, s -> s.getCode());
}
protected void addProject(XMLStreamWriter writer, Project project) throws XMLStreamException
{
addAttribute(writer, "project", project, p -> p.getCode());
}
protected void addSample(XMLStreamWriter writer, Sample sample) throws XMLStreamException
{
addAttribute(writer, "sample", sample, s -> s.getIdentifier().getIdentifier());
}
protected void addExperiment(XMLStreamWriter writer, Experiment experiment) throws XMLStreamException
{
addAttribute(writer, "experiment", experiment, e -> e.getIdentifier().getIdentifier());
}
protected void addKind(XMLStreamWriter writer, Object kind) throws XMLStreamException
{
addAttribute(writer, "kind", kind, k -> k.toString());
}
protected void addType(XMLStreamWriter writer, ICodeHolder type) throws XMLStreamException
{
addAttribute(writer, "type", type, t -> t.getCode());
}
protected void addModifier(XMLStreamWriter writer, IModifierHolder dataSet) throws XMLStreamException
{
addAttribute(writer, "modifier", dataSet.getModifier(), m -> m.getUserId());
}
protected void addRegistrator(XMLStreamWriter writer, IRegistratorHolder dataSet) throws XMLStreamException
{
addAttribute(writer, "registrator", dataSet.getRegistrator(), r -> r.getUserId());
}
protected void addRegistrationDate(XMLStreamWriter writer, IRegistrationDateHolder dateHolder) throws XMLStreamException
{
addAttribute(writer, "registration-timestamp", dateHolder.getRegistrationDate(), h -> DataSourceUtils.convertToW3CDate(h));
}
protected void addAttribute(XMLStreamWriter writer, String attributeName, String value) throws XMLStreamException
{
addAttribute(writer, attributeName, value, v -> v);
}
protected <O> void addAttribute(XMLStreamWriter writer, String attributeName, O object, Function<O, String> mapper) throws XMLStreamException
{
if (object != null)
{
writer.writeAttribute(attributeName, mapper.apply(object));
}
}
protected void addLink(XMLStreamWriter writer, String code, String entityKind) throws XMLStreamException
{
addLink(writer, "?viewMode=SIMPLE&anonymous=true#entity=" + entityKind + "&permId=" + code);
}
protected void addLink(XMLStreamWriter writer, String urlPart2) throws XMLStreamException
{
writer.writeStartElement("rs:ln");
writer.writeAttribute("href", context.getServerUrl() + urlPart2);
writer.writeAttribute("rel", "describes");
writer.writeEndElement();
}
protected void addLocation(XMLStreamWriter writer, String code, String entityKind) throws XMLStreamException
{
writer.writeStartElement("loc");
writer.writeCharacters(context.getServerUrl() + "/" + entityKind + "/" + code + "/M");
writer.writeEndElement();
}
protected void addLastModificationDate(XMLStreamWriter writer, IModificationDateHolder dateHolder) throws XMLStreamException
{
addLastModificationDate(writer, dateHolder.getModificationDate());
}
protected void addLastModificationDate(XMLStreamWriter writer, Date modificationDate) throws XMLStreamException
{
writer.writeStartElement("lastmod");
writer.writeCharacters(DataSourceUtils.convertToW3CDate(modificationDate));
writer.writeEndElement();
}
protected void startUrlElement(XMLStreamWriter writer, String entityKind, String permId, Date modificationDate) throws XMLStreamException
{
startUrlElement(writer);
addLocation(writer, permId, entityKind);
addLastModificationDate(writer, modificationDate);
addLink(writer, permId, entityKind);
}
protected void startUrlElement(XMLStreamWriter writer) throws XMLStreamException
{
writer.writeStartElement("url");
}
protected void startXdElement(XMLStreamWriter writer) throws XMLStreamException
{
writer.writeStartElement("x:xd");
}
protected void startBinaryDataElement(XMLStreamWriter writer) throws XMLStreamException
{
writer.writeStartElement("x:binaryData");
}
private void executeInBatches(List<T> allEntities, IConsumer<List<T>> action)
{
operationLog.info(allEntities.size() + " " + entityKind + "s in total.");
BatchOperationExecutor.executeInBatches(new IBatchOperation<T>()
{
@Override
public void execute(List<T> entities)
{
try
{
action.consume(entities);
} catch (XMLStreamException e)
{
throw CheckedExceptionTunnel.wrapIfNecessary(e);
}
}
@Override
public List<T> getAllEntities()
{
return allEntities;
}
@Override
public String getEntityName()
{
return entityKind;
}
@Override
public String getOperationName()
{
return "deliver";
}
}, CHUNK_SIZE);
}
}
/*
* Copyright 2019 ETH Zuerich, SIS
*
* 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.ethz.sis.openbis.generic.server.dss.plugins.sync.datasource;
import java.util.ArrayList;
import java.util.List;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.apache.commons.lang3.StringUtils;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IPermIdHolder;
class ConnectionsBuilder
{
private enum ConnectionType
{
CONNECTION, CHILD, COMPONENT
}
private static final class Connection
{
private String permId;
private ConnectionsBuilder.ConnectionType type;
Connection(String permId, ConnectionsBuilder.ConnectionType type)
{
this.permId = permId;
this.type = type;
}
}
private List<ConnectionsBuilder.Connection> connections = new ArrayList<>();
void addChildren(List<? extends IPermIdHolder> entities)
{
addConnections(entities, ConnectionType.CHILD);
}
void addComponents(List<? extends IPermIdHolder> entities)
{
addConnections(entities, ConnectionType.COMPONENT);
}
void addConnections(List<? extends IPermIdHolder> entities)
{
addConnections(entities, ConnectionType.CONNECTION);
}
void writeTo(XMLStreamWriter writer) throws XMLStreamException
{
if (connections.isEmpty())
{
return;
}
writer.writeStartElement("x:connections");
for (Connection connection : connections)
{
writer.writeStartElement("x:connection");
writer.writeAttribute("to", connection.permId);
writer.writeAttribute("type", StringUtils.capitalize(connection.type.toString().toLowerCase()));
writer.writeEndElement();
}
writer.writeEndElement();
}
private void addConnections(List<? extends IPermIdHolder> entities, ConnectionsBuilder.ConnectionType child)
{
for (IPermIdHolder entity : entities)
{
connections.add(new Connection(entity.getPermId().toString(), child));
}
}
}
\ No newline at end of file
/*
* Copyright 2019 ETH Zuerich, SIS
*
* 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.ethz.sis.openbis.generic.server.dss.plugins.sync.datasource;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.ContentCopy;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.LinkedData;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.PhysicalData;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetFetchOptions;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.id.DataSetPermId;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.DataSetSearchCriteria;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.EntityKind;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.Experiment;
import ch.systemsx.cisd.openbis.common.io.hierarchical_content.api.IHierarchicalContentNode;
/**
* @author Franz-Josef Elmer
*/
public class DataSetDeliverer extends AbstractEntityDeliverer<DataSet>
{
DataSetDeliverer(DeliveryContext context)
{
super(context, "data set");
}
@Override
protected List<DataSet> getAllEntities(String sessionToken)
{
DataSetSearchCriteria searchCriteria = new DataSetSearchCriteria();
DataSetFetchOptions fetchOptions = new DataSetFetchOptions();
fetchOptions.sortBy().code().asc();
return context.getV3api().searchDataSets(sessionToken, searchCriteria, fetchOptions).getObjects();
}
@Override
protected void deliverEntities(XMLStreamWriter writer, String sessionToken, Set<String> spaces, List<DataSet> dataSets) throws XMLStreamException
{
List<DataSetPermId> permIds = dataSets.stream().map(DataSet::getPermId).collect(Collectors.toList());
Collection<DataSet> fullDataSets = context.getV3api().getDataSets(sessionToken, permIds, createDataSetFetchOptions()).values();
int count = 0;
for (DataSet dataSet : fullDataSets)
{
if (accept(dataSet, spaces))
{
String code = dataSet.getCode();
startUrlElement(writer, "DATA_SET", code, dataSet.getModificationDate());
startXdElement(writer);
writer.writeAttribute("code", code);
writer.writeAttribute("dsKind", dataSet.getKind().toString());
addExperiment(writer, dataSet.getExperiment());
addKind(writer, EntityKind.DATA_SET);
addModifier(writer, dataSet);
addRegistrationDate(writer, dataSet);
addRegistrator(writer, dataSet);
addSample(writer, dataSet.getSample());
addType(writer, dataSet.getType());
addProperties(writer, dataSet.getProperties());
addPhysicalData(writer, dataSet, code);
addLinkedData(writer, dataSet, code);
ConnectionsBuilder connectionsBuilder = new ConnectionsBuilder();
connectionsBuilder.addChildren(dataSet.getChildren());
connectionsBuilder.addComponents(dataSet.getComponents());
connectionsBuilder.writeTo(writer);
writer.writeEndElement();
writer.writeEndElement();
count++;
}
}
operationLog.info(count + " of " + dataSets.size() + " data sets have been delivered.");
}
private void addPhysicalData(XMLStreamWriter writer, DataSet dataSet, String code) throws XMLStreamException
{
PhysicalData physicalData = dataSet.getPhysicalData();
if (physicalData != null)
{
startBinaryDataElement(writer);
addFileNodes(writer, code, context.getContentProvider().asContent(code).getRootNode());
writer.writeEndElement();
}
}
private void addLinkedData(XMLStreamWriter writer, DataSet dataSet, String code) throws XMLStreamException
{
LinkedData linkedData = dataSet.getLinkedData();
if (linkedData != null)
{
startBinaryDataElement(writer);
List<ContentCopy> contentCopies = linkedData.getContentCopies();
for (ContentCopy contentCopy : contentCopies)
{
addAttribute(writer, "externalCode", contentCopy.getExternalCode());
addAttribute(writer, "externalDMS", contentCopy.getExternalDms(), edms -> edms.getCode());
addAttribute(writer, "gitCommitHash", contentCopy.getGitCommitHash());
addAttribute(writer, "gitRepositoryId", contentCopy.getGitRepositoryId());
addAttribute(writer, "id", contentCopy.getId(), id -> id.getPermId());
addAttribute(writer, "path", contentCopy.getPath());
}
addFileNodes(writer, code, context.getContentProvider().asContent(code).getRootNode());
writer.writeEndElement();
}
}
private void addFileNodes(XMLStreamWriter writer, String dataSetCode, IHierarchicalContentNode node) throws XMLStreamException
{
if (node.isDirectory())
{
List<IHierarchicalContentNode> childNodes = node.getChildNodes();
for (IHierarchicalContentNode childNode : childNodes)
{
addFileNodes(writer, dataSetCode, childNode);
}
} else
{
writer.writeStartElement("x:fileNode");
addAttribute(writer, "checksum", node.getChecksum());
if (node.isChecksumCRC32Precalculated())
{
writer.writeAttribute("crc32checksum", Integer.toString(node.getChecksumCRC32()));
}
writer.writeAttribute("length", Long.toString(node.getFileLength()));
writer.writeAttribute("path", context.getDownloadUrl() + "/datastore_server/" + dataSetCode + "/"
+ node.getRelativePath() + "?");
writer.writeEndElement();
}
}
private boolean accept(DataSet dataSet, Set<String> spaces)
{
Experiment experiment = dataSet.getExperiment();
if (experiment != null)
{
return spaces.contains(experiment.getProject().getSpace().getCode());
}
return spaces.contains(dataSet.getSample().getSpace().getCode());
}
private DataSetFetchOptions createDataSetFetchOptions()
{
DataSetFetchOptions fo = new DataSetFetchOptions();
fo.withRegistrator();
fo.withModifier();
fo.withType();
fo.withSample().withSpace();
fo.withExperiment().withProject().withSpace();
fo.withProperties();
fo.withChildren();
fo.withComponents();
fo.withPhysicalData();
fo.withLinkedData().withExternalDms();
fo.sortBy().code();
return fo;
}
}
/*
* Copyright 2019 ETH Zuerich, SIS
*
* 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.ethz.sis.openbis.generic.server.dss.plugins.sync.datasource;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.apache.log4j.Logger;
import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSet;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.Space;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.fetchoptions.SpaceFetchOptions;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.space.search.SpaceSearchCriteria;
import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory;
import ch.systemsx.cisd.common.properties.PropertyUtils;
import ch.systemsx.cisd.openbis.dss.generic.server.oaipmh.IRequestHandler;
import ch.systemsx.cisd.openbis.dss.generic.shared.DataSourceQueryService;
import ch.systemsx.cisd.openbis.dss.generic.shared.IHierarchicalContentProvider;
import ch.systemsx.cisd.openbis.dss.generic.shared.ServiceProvider;
import ch.systemsx.cisd.openbis.generic.shared.dto.SessionContextDTO;
/**
* @author Franz-Josef Elmer
*/
public class DataSourceRequestHandler implements IRequestHandler
{
private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, DataSourceRequestHandler.class);
private File tempDir;
private String serverUrl;
private String downloadUrl;
private String servletPath;
private DataSourceQueryService queryService;
private IApplicationServerApi v3api;
private IHierarchicalContentProvider contentProvider;
private AbstractEntityDeliverer<DataSet> dataSetDeliverer;
private ExperimentDeliverer experimentDeliverer;
private MaterialDeliverer materialDeliverer;
private SampleDeliverer sampleDeliverer;
private ProjectDeliverer projectDeliverer;
private MasterDataDeliverer masterDataDeliverer;
@Override
public void init(Properties properties)
{
DeliveryContext deliveryContext = new DeliveryContext();
servletPath = new File(PropertyUtils.getMandatoryProperty(properties, "path")).getParent();
deliveryContext.setServletPath(servletPath);
tempDir = new File(PropertyUtils.getMandatoryProperty(properties, "temp-dir"));
serverUrl = PropertyUtils.getMandatoryProperty(properties, "server-url");
deliveryContext.setServerUrl(serverUrl);
downloadUrl = PropertyUtils.getMandatoryProperty(properties, "download-url");
deliveryContext.setDownloadUrl(downloadUrl);
queryService = new DataSourceQueryService();
v3api = ServiceProvider.getV3ApplicationService();
deliveryContext.setV3api(v3api);
contentProvider = ServiceProvider.getHierarchicalContentProvider();
deliveryContext.setContentProvider(contentProvider);
dataSetDeliverer = new DataSetDeliverer(deliveryContext);
experimentDeliverer = new ExperimentDeliverer(deliveryContext);
materialDeliverer = new MaterialDeliverer(deliveryContext);
sampleDeliverer = new SampleDeliverer(deliveryContext);
projectDeliverer = new ProjectDeliverer(deliveryContext);
masterDataDeliverer = new MasterDataDeliverer(deliveryContext);
}
@Override
public void handle(SessionContextDTO session, HttpServletRequest request, HttpServletResponse response)
{
try
{
Map<String, Set<String>> parameterMap = getParameterMap(request);
XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
XMLStreamWriter writer = xmlOutputFactory.createXMLStreamWriter(response.getWriter());
writer.writeStartDocument();
writer.writeStartElement("urlset");
writer.writeAttribute("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9");
writer.writeAttribute("xmlns:rs", "http://www.openarchives.org/rs/terms/");
writer.writeAttribute("xmlns:xmd", "https://sis.id.ethz.ch/software/#openbis/xmdterms/");
writer.writeAttribute("xmlns:x", "https://sis.id.ethz.ch/software/#openbis/xdterms/");
writer.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
writer.writeAttribute("xsi:schemaLocation",
"https://sis.id.ethz.ch/software/#openbis/xdterms/ ./xml/xdterms.xsd https://sis.id.ethz.ch/software/#openbis/xmdterms/");
String sessionToken = session.getSessionToken();
Set<String> verbs = parameterMap.get("verb");
if (verbs.contains("resourcelist.xml"))
{
deliverResourceList(parameterMap, sessionToken, writer);
}
writer.writeEndElement();
writer.writeEndDocument();
} catch (Exception e)
{
throw CheckedExceptionTunnel.wrapIfNecessary(e);
}
}
private void deliverResourceList(Map<String, Set<String>> parameterMap, String sessionToken, XMLStreamWriter writer) throws XMLStreamException
{
writer.writeStartElement("rs:ln");
writer.writeAttribute("href", downloadUrl + servletPath + "/?verb=capabilitylist.xml");
writer.writeAttribute("rel", "up");
writer.writeEndElement();
writer.writeStartElement("rs:md");
Date requestTimestamp = getRequestTimestamp();
writer.writeAttribute("at", DataSourceUtils.convertToW3CDate(requestTimestamp));
writer.writeAttribute("capability", "resourceList");
writer.writeEndElement();
Set<String> ignoredSpaces = parameterMap.get("black_list");
if (ignoredSpaces == null)
{
ignoredSpaces = Collections.emptySet();
}
Set<String> requestedSpaces = new TreeSet<>();
List<Space> spaces = v3api.searchSpaces(sessionToken, new SpaceSearchCriteria(), new SpaceFetchOptions()).getObjects();
for (Space space : spaces)
{
if (ignoredSpaces.contains(space.getCode()) == false)
{
requestedSpaces.add(space.getCode());
}
}
dataSetDeliverer.deliverEntities(writer, sessionToken, requestedSpaces, requestTimestamp);
experimentDeliverer.deliverEntities(writer, sessionToken, requestedSpaces, requestTimestamp);
masterDataDeliverer.deliverEntities(writer, sessionToken, requestedSpaces, requestTimestamp);;
materialDeliverer.deliverEntities(writer, sessionToken, requestedSpaces, requestTimestamp);
projectDeliverer.deliverEntities(writer, sessionToken, requestedSpaces, requestTimestamp);
sampleDeliverer.deliverEntities(writer, sessionToken, requestedSpaces, requestTimestamp);
}
protected Date getRequestTimestamp()
{
Date requestTimestamp = new Date();
String query = "select xact_start FROM pg_stat_activity WHERE xact_start IS NOT NULL ORDER BY xact_start ASC LIMIT 1";
for (Map<String, Object> map : queryService.select("openbis-db", query))
{
requestTimestamp = (Date) map.get("xact_start");
}
return requestTimestamp;
}
private Map<String, Set<String>> getParameterMap(HttpServletRequest request)
{
Enumeration<String> enumeration = request.getParameterNames();
Map<String, Set<String>> parameterMap = new HashMap<>();
while (enumeration.hasMoreElements())
{
String parameter = enumeration.nextElement();
parameterMap.put(parameter, new HashSet<>(Arrays.asList(request.getParameterValues(parameter))));
}
return parameterMap;
}
}
/*
* Copyright 2019 ETH Zuerich, SIS
*
* 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.ethz.sis.openbis.generic.server.dss.plugins.sync.datasource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
/**
* @author Franz-Josef Elmer
*
*/
class DataSourceUtils
{
static String convertToW3CDate(Date date)
{
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("GMT"));
return format.format(date) + "Z";
}
}
/*
* Copyright 2019 ETH Zuerich, SIS
*
* 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.ethz.sis.openbis.generic.server.dss.plugins.sync.datasource;
import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi;
import ch.systemsx.cisd.openbis.dss.generic.shared.IHierarchicalContentProvider;
/**
* @author Franz-Josef Elmer
*
*/
class DeliveryContext
{
private String serverUrl;
private String downloadUrl;
private String servletPath;
private IApplicationServerApi v3api;
private IHierarchicalContentProvider contentProvider;
public String getServerUrl()
{
return serverUrl;
}
public void setServerUrl(String serverUrl)
{
this.serverUrl = serverUrl;
}
public String getDownloadUrl()
{
return downloadUrl;
}
public void setDownloadUrl(String downloadUrl)
{
this.downloadUrl = downloadUrl;
}
public String getServletPath()
{
return servletPath;
}
public void setServletPath(String servletPath)
{
this.servletPath = servletPath;
}
public IApplicationServerApi getV3api()
{
return v3api;
}
public void setV3api(IApplicationServerApi v3api)
{
this.v3api = v3api;
}
public IHierarchicalContentProvider getContentProvider()
{
return contentProvider;
}
public void setContentProvider(IHierarchicalContentProvider contentProvider)
{
this.contentProvider = contentProvider;
}
}
/*
* Copyright 2019 ETH Zuerich, SIS
*
* 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.ethz.sis.openbis.generic.server.dss.plugins.sync.datasource;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.EntityKind;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.Experiment;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.fetchoptions.ExperimentFetchOptions;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.id.ExperimentPermId;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.search.ExperimentSearchCriteria;
/**
* @author Franz-Josef Elmer
*
*/
public class ExperimentDeliverer extends AbstractEntityDeliverer<Experiment>
{
ExperimentDeliverer(DeliveryContext context)
{
super(context, "experiment");
}
@Override
protected List<Experiment> getAllEntities(String sessionToken)
{
ExperimentSearchCriteria searchCriteria = new ExperimentSearchCriteria();
ExperimentFetchOptions fetchOptions = new ExperimentFetchOptions();
fetchOptions.sortBy().permId();
return context.getV3api().searchExperiments(sessionToken, searchCriteria, fetchOptions).getObjects();
}
@Override
protected void deliverEntities(XMLStreamWriter writer, String sessionToken, Set<String> spaces, List<Experiment> experiments)
throws XMLStreamException
{
List<ExperimentPermId> permIds = experiments.stream().map(Experiment::getPermId).collect(Collectors.toList());
Collection<Experiment> fullExperiments = context.getV3api().getExperiments(sessionToken, permIds, createFullFetchOptions()).values();
int count = 0;
for (Experiment experiment : fullExperiments)
{
if (spaces.contains(experiment.getProject().getSpace().getCode()))
{
String permId = experiment.getPermId().getPermId();
startUrlElement(writer, "EXPERIMENT", permId, experiment.getModificationDate());
startXdElement(writer);
writer.writeAttribute("code", experiment.getCode());
addKind(writer, EntityKind.EXPERIMENT);
addModifier(writer, experiment);
addProject(writer, experiment.getProject());
addRegistrationDate(writer, experiment);
addRegistrator(writer, experiment);
addSpace(writer, experiment.getProject().getSpace());
addType(writer, experiment.getType());
addProperties(writer, experiment.getProperties());
ConnectionsBuilder connectionsBuilder = new ConnectionsBuilder();
connectionsBuilder.addConnections(experiment.getSamples());
connectionsBuilder.addConnections(experiment.getDataSets());
connectionsBuilder.writeTo(writer);
addAttachments(writer, experiment.getAttachments());
writer.writeEndElement();
writer.writeEndElement();
count++;
}
}
operationLog.info(count + " of " + experiments.size() + " experiments have been delivered.");
}
private ExperimentFetchOptions createFullFetchOptions()
{
ExperimentFetchOptions fo = new ExperimentFetchOptions();
fo.withRegistrator();
fo.withModifier();
fo.withProperties();
fo.withProject().withSpace();
fo.withType();
fo.withAttachments();
fo.withSamples();
fo.withDataSets();
return fo;
}
}
/*
* Copyright 2019 ETH Zuerich, SIS
*
* 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.ethz.sis.openbis.generic.server.dss.plugins.sync.datasource;
import java.util.Date;
import java.util.Set;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
/**
* @author Franz-Josef Elmer
*
*/
public class MasterDataDeliverer extends AbstractEntityDeliverer<Object>
{
MasterDataDeliverer(DeliveryContext context)
{
super(context, "master data");
}
@Override
void deliverEntities(XMLStreamWriter writer, String sessionToken, Set<String> spaces, Date requestTimestamp) throws XMLStreamException
{
startUrlElement(writer);
addLocation(writer, "MASTER_DATA", "MASTER_DATA");
addLastModificationDate(writer, requestTimestamp);
writer.writeEndElement();
}
}
/*
* Copyright 2019 ETH Zuerich, SIS
*
* 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.ethz.sis.openbis.generic.server.dss.plugins.sync.datasource;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.material.Material;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.material.fetchoptions.MaterialFetchOptions;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.material.id.MaterialPermId;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.material.search.MaterialSearchCriteria;
/**
* @author Franz-Josef Elmer
*/
public class MaterialDeliverer extends AbstractEntityDeliverer<Material>
{
MaterialDeliverer(DeliveryContext context)
{
super(context, "material");
}
@Override
protected List<Material> getAllEntities(String sessionToken)
{
MaterialSearchCriteria searchCriteria = new MaterialSearchCriteria();
MaterialFetchOptions fetchOptions = new MaterialFetchOptions();
fetchOptions.sortBy().permId();
return context.getV3api().searchMaterials(sessionToken, searchCriteria, fetchOptions).getObjects();
}
@Override
protected void deliverEntities(XMLStreamWriter writer, String sessionToken, Set<String> spaces, List<Material> materials)
throws XMLStreamException
{
List<MaterialPermId> permIds = materials.stream().map(Material::getPermId).collect(Collectors.toList());
Collection<Material> fullMaterials = context.getV3api().getMaterials(sessionToken, permIds, createFullFetchOptions()).values();
for (Material material : fullMaterials)
{
startUrlElement(writer);
String type = material.getType().getCode();
String code = material.getCode();
addLocation(writer, type + "/" + code, "MATERIAL");
addLastModificationDate(writer, material.getModificationDate());
addLink(writer, "#action=VIEW&entity=MATERIAL&code=" + code + "&type=" + type);
startXdElement(writer);
writer.writeAttribute("code", code);
writer.writeAttribute("dsKind", "MATERIAL");
addRegistrationDate(writer, material);
addRegistrator(writer, material);
addType(writer, material.getType());
HashMap<String, String> allProperties = new HashMap<>(material.getProperties());
Map<String, Material> materialProperties = material.getMaterialProperties();
Set<Entry<String, Material>> entrySet = materialProperties.entrySet();
for (Entry<String, Material> entity : entrySet)
{
allProperties.put(entity.getKey(), entity.getValue().getPermId().toString());
}
addProperties(writer, allProperties);
writer.writeEndElement();
writer.writeEndElement();
}
operationLog.info(materials.size() + " of " + materials.size() + " materials have been delivered.");
}
private MaterialFetchOptions createFullFetchOptions()
{
MaterialFetchOptions fetchOptions = new MaterialFetchOptions();
fetchOptions.withMaterialProperties();
fetchOptions.withRegistrator();
fetchOptions.withType();
fetchOptions.withProperties();
return fetchOptions;
}
}
/*
* Copyright 2019 ETH Zuerich, SIS
*
* 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.ethz.sis.openbis.generic.server.dss.plugins.sync.datasource;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.Project;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.fetchoptions.ProjectFetchOptions;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.id.ProjectPermId;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.search.ProjectSearchCriteria;
/**
* @author Franz-Josef Elmer
*
*/
public class ProjectDeliverer extends AbstractEntityDeliverer<Project>
{
ProjectDeliverer(DeliveryContext context)
{
super(context, "project");
}
@Override
protected List<Project> getAllEntities(String sessionToken)
{
ProjectSearchCriteria searchCriteria = new ProjectSearchCriteria();
ProjectFetchOptions fetchOptions = new ProjectFetchOptions();
fetchOptions.sortBy().permId();
return context.getV3api().searchProjects(sessionToken, searchCriteria, fetchOptions).getObjects();
}
@Override
protected void deliverEntities(XMLStreamWriter writer, String sessionToken, Set<String> spaces, List<Project> projects) throws XMLStreamException
{
List<ProjectPermId> permIds = projects.stream().map(Project::getPermId).collect(Collectors.toList());
Collection<Project> fullProjects = context.getV3api().getProjects(sessionToken, permIds, createFullFetchOptions()).values();
int count = 0;
for (Project project : fullProjects)
{
if (spaces.contains(project.getSpace().getCode()))
{
String permId = project.getPermId().getPermId();
startUrlElement(writer, "PROJECT", permId, project.getModificationDate());
startXdElement(writer);
writer.writeAttribute("code", project.getCode());
addAttribute(writer, "desc", project.getDescription());
addKind(writer, "PROJECT");
addModifier(writer, project);
addRegistrationDate(writer, project);
addRegistrator(writer, project);
addSpace(writer, project.getSpace());
ConnectionsBuilder connectionsBuilder = new ConnectionsBuilder();
connectionsBuilder.addConnections(project.getExperiments());
connectionsBuilder.addConnections(project.getSamples().stream()
.filter(s -> s.getExperiment() == null).collect(Collectors.toList()));
connectionsBuilder.writeTo(writer);
addAttachments(writer, project.getAttachments());
writer.writeEndElement();
writer.writeEndElement();
count++;
}
}
operationLog.info(count + " of " + projects.size() + " projects have been delivered.");
}
private ProjectFetchOptions createFullFetchOptions()
{
ProjectFetchOptions fetchOptions = new ProjectFetchOptions();
fetchOptions.withAttachments();
fetchOptions.withRegistrator();
fetchOptions.withModifier();
fetchOptions.withSpace();
fetchOptions.withExperiments();
fetchOptions.withSamples().withExperiment();
return fetchOptions;
}
}
/*
* Copyright 2019 ETH Zuerich, SIS
*
* 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.ethz.sis.openbis.generic.server.dss.plugins.sync.datasource;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.EntityKind;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.Sample;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.fetchoptions.SampleFetchOptions;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.id.SamplePermId;
import ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.search.SampleSearchCriteria;
/**
* @author Franz-Josef Elmer
*
*/
public class SampleDeliverer extends AbstractEntityDeliverer<Sample>
{
SampleDeliverer(DeliveryContext context)
{
super(context, "sample");
}
@Override
protected List<Sample> getAllEntities(String sessionToken)
{
SampleSearchCriteria searchCriteria = new SampleSearchCriteria();
SampleFetchOptions fetchOptions = new SampleFetchOptions();
fetchOptions.sortBy().permId();
return context.getV3api().searchSamples(sessionToken, searchCriteria, fetchOptions).getObjects();
}
@Override
protected void deliverEntities(XMLStreamWriter writer, String sessionToken, Set<String> spaces, List<Sample> samples) throws XMLStreamException
{
List<SamplePermId> permIds = samples.stream().map(Sample::getPermId).collect(Collectors.toList());
Collection<Sample> fullSamples = context.getV3api().getSamples(sessionToken, permIds, createFullFetchOptions()).values();
int count = 0;
for (Sample sample : fullSamples)
{
if (sample.getSpace() == null || spaces.contains(sample.getSpace().getCode()))
{
String permId = sample.getPermId().getPermId();
startUrlElement(writer, "SAMPLE", permId, sample.getModificationDate());
startXdElement(writer);
writer.writeAttribute("code", sample.getCode());
addExperiment(writer, sample.getExperiment());
addKind(writer, EntityKind.SAMPLE);
addModifier(writer, sample);
addProject(writer, sample.getProject());
addRegistrationDate(writer, sample);
addRegistrator(writer, sample);
addSpace(writer, sample.getSpace());
addType(writer, sample.getType());
addProperties(writer, sample.getProperties());
ConnectionsBuilder connectionsBuilder = new ConnectionsBuilder();
connectionsBuilder.addConnections(sample.getDataSets());
connectionsBuilder.addChildren(sample.getChildren());
connectionsBuilder.addComponents(sample.getComponents());
connectionsBuilder.writeTo(writer);
addAttachments(writer, sample.getAttachments());
writer.writeEndElement();
writer.writeEndElement();
count++;
}
}
operationLog.info(count + " of " + samples.size() + " samples have been delivered.");
}
private SampleFetchOptions createFullFetchOptions()
{
SampleFetchOptions fo = new SampleFetchOptions();
fo.withRegistrator();
fo.withModifier();
fo.withProperties();
fo.withDataSets();
fo.withType();
fo.withExperiment();
fo.withProject();
fo.withSpace();
fo.withAttachments();
fo.withChildren();
fo.withComponents();
fo.withDataSets();
return fo;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment