diff --git a/src/main/java/caosdb/server/CaosDBServer.java b/src/main/java/caosdb/server/CaosDBServer.java index 19560aacd50ede38471c0fb02e31fd4560e9d8bb..eaf53dd4a6d904254ae66d875cd54c963756fc09 100644 --- a/src/main/java/caosdb/server/CaosDBServer.java +++ b/src/main/java/caosdb/server/CaosDBServer.java @@ -19,6 +19,49 @@ */ package caosdb.server; +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Properties; +import java.util.TimeZone; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.config.Ini; +import org.apache.shiro.config.Ini.Section; +import org.apache.shiro.config.IniSecurityManagerFactory; +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.subject.Subject; +import org.apache.shiro.util.Factory; +import org.apache.shiro.util.ThreadContext; +import org.restlet.Application; +import org.restlet.Component; +import org.restlet.Context; +import org.restlet.Request; +import org.restlet.Response; +import org.restlet.Restlet; +import org.restlet.Server; +import org.restlet.data.CookieSetting; +import org.restlet.data.Parameter; +import org.restlet.data.Protocol; +import org.restlet.data.Reference; +import org.restlet.data.ServerInfo; +import org.restlet.data.Status; +import org.restlet.engine.Engine; +import org.restlet.routing.Route; +import org.restlet.routing.Router; +import org.restlet.routing.Template; +import org.restlet.routing.TemplateRoute; +import org.restlet.routing.Variable; +import org.restlet.util.Series; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import caosdb.server.accessControl.AnonymousRealm; import caosdb.server.accessControl.AuthenticationUtils; import caosdb.server.accessControl.CaosDBAuthorizingRealm; @@ -63,49 +106,6 @@ import caosdb.server.utils.FileUtils; import caosdb.server.utils.Initialization; import caosdb.server.utils.NullPrintStream; import caosdb.server.utils.Utils; -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.time.ZoneId; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Properties; -import java.util.TimeZone; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.LogRecord; -import org.apache.shiro.SecurityUtils; -import org.apache.shiro.config.Ini; -import org.apache.shiro.config.Ini.Section; -import org.apache.shiro.config.IniSecurityManagerFactory; -import org.apache.shiro.mgt.SecurityManager; -import org.apache.shiro.subject.Subject; -import org.apache.shiro.util.Factory; -import org.apache.shiro.util.ThreadContext; -import org.restlet.Application; -import org.restlet.Component; -import org.restlet.Context; -import org.restlet.Request; -import org.restlet.Response; -import org.restlet.Restlet; -import org.restlet.Server; -import org.restlet.data.CookieSetting; -import org.restlet.data.Parameter; -import org.restlet.data.Protocol; -import org.restlet.data.Reference; -import org.restlet.data.ServerInfo; -import org.restlet.data.Status; -import org.restlet.engine.Engine; -import org.restlet.routing.Route; -import org.restlet.routing.Router; -import org.restlet.routing.Template; -import org.restlet.routing.TemplateRoute; -import org.restlet.routing.Variable; -import org.restlet.util.Series; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class CaosDBServer extends Application { diff --git a/src/main/java/caosdb/server/FileSystem.java b/src/main/java/caosdb/server/FileSystem.java index c46f0f644442a5df6c2363dedfacb38025cacde4..6ea9222989a66647ba4e4a164f81bb4d338225e8 100644 --- a/src/main/java/caosdb/server/FileSystem.java +++ b/src/main/java/caosdb/server/FileSystem.java @@ -24,16 +24,6 @@ package caosdb.server; -import caosdb.server.database.access.Access; -import caosdb.server.database.backend.transaction.GetFileRecordByPath; -import caosdb.server.database.misc.TransactionBenchmark; -import caosdb.server.entity.EntityInterface; -import caosdb.server.entity.FileProperties; -import caosdb.server.entity.Message; -import caosdb.server.utils.FileUtils; -import caosdb.server.utils.ServerMessages; -import caosdb.server.utils.Utils; -import com.google.common.io.Files; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -44,6 +34,16 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.regex.Pattern; import org.apache.commons.fileupload.FileItemStream; +import com.google.common.io.Files; +import caosdb.server.database.access.Access; +import caosdb.server.database.backend.transaction.GetFileRecordByPath; +import caosdb.server.database.misc.TransactionBenchmark; +import caosdb.server.entity.EntityInterface; +import caosdb.server.entity.FileProperties; +import caosdb.server.entity.Message; +import caosdb.server.utils.FileUtils; +import caosdb.server.utils.ServerMessages; +import caosdb.server.utils.Utils; public class FileSystem { private static String filesystem = null; @@ -150,10 +150,9 @@ public class FileSystem { * @return FileProperties of the uploaded File. * @throws NoSuchAlgorithmException * @throws IOException - * @throws CaosDBException */ public static final FileProperties upload(final FileItemStream item, final String session) - throws NoSuchAlgorithmException, IOException, CaosDBException { + throws NoSuchAlgorithmException, IOException { String checksum = null; // Name of the temporary FILE object. diff --git a/src/main/java/caosdb/server/converter/misc/AbstractContainerHelper.java b/src/main/java/caosdb/server/converter/misc/AbstractContainerHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..9da3f99083fa57191fd123054dfa333bb8a00b70 --- /dev/null +++ b/src/main/java/caosdb/server/converter/misc/AbstractContainerHelper.java @@ -0,0 +1,64 @@ +package caosdb.server.converter.misc; + + + +import java.util.Collections; +import java.util.List; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.subject.Subject; +import org.restlet.engine.converter.ConverterHelper; +import org.restlet.engine.resource.VariantInfo; +import org.restlet.representation.Representation; +import org.restlet.representation.Variant; +import org.restlet.resource.Resource; +import caosdb.server.entity.container.TransactionContainer; + +public abstract class AbstractContainerHelper extends ConverterHelper { + + private static final List<Class<?>> OBJECT_CLASSES = + Collections.singletonList(TransactionContainer.class); + private final VariantInfo[] variants; + + public AbstractContainerHelper(VariantInfo... variants) { + this.variants = variants; + } + + public final boolean isCompatibleSource(Variant source) { + for(VariantInfo v : variants) { + if(v.isCompatible(source)) { + return true; + } + } + return false; + } + + public final TransactionContainer createContainer(Resource resource) { + final String sRID = resource.getAttribute("srid"); + final long timestamp = resource.getRequest().getDate().getTime(); + final Subject owner = SecurityUtils.getSubject(); + + final TransactionContainer result = new TransactionContainer(owner, timestamp, sRID); + return result; + } + + @Override + public final List<Class<?>> getObjectClasses(Variant source) { + if (isCompatibleSource(source)) { + return OBJECT_CLASSES; + } + return null; + } + + @Override + public final <T> float score(Representation source, Class<T> target, Resource resource) { + // this class only converts from multipart/form-data to Containers. + if (TransactionContainer.class.isAssignableFrom(target) + && isCompatibleSource(source)) { + return 1.0F; + } + return -1.0F; + } + + + +} diff --git a/src/main/java/caosdb/server/converter/misc/MultipartContainerConverter.java b/src/main/java/caosdb/server/converter/misc/MultipartContainerConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..dc35e3dcb765355c6713a45bf4fab8cbbdb3c29c --- /dev/null +++ b/src/main/java/caosdb/server/converter/misc/MultipartContainerConverter.java @@ -0,0 +1,109 @@ +package caosdb.server.converter.misc; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.util.List; +import org.apache.commons.fileupload.FileItemIterator; +import org.apache.commons.fileupload.FileItemStream; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.restlet.data.MediaType; +import org.restlet.data.Status; +import org.restlet.engine.converter.ConverterHelper; +import org.restlet.engine.converter.ConverterUtils; +import org.restlet.engine.resource.VariantInfo; +import org.restlet.ext.fileupload.RestletFileUpload; +import org.restlet.representation.InputRepresentation; +import org.restlet.representation.Representation; +import org.restlet.representation.Variant; +import org.restlet.resource.Resource; +import org.restlet.resource.ResourceException; +import caosdb.server.FileSystem; +import caosdb.server.entity.FileProperties; +import caosdb.server.entity.container.TransactionContainer; + +/** + * Convert HTTP entities with media type "multipart/form-data" into Containers. + * + * The reverse conversion is not implemented. + * + * This conversion is mainly used for the FileUpload. + * + * @author Timm Fitschen (t.fitschen@indiscale.com) + * + */ +public class MultipartContainerConverter extends AbstractContainerHelper { + + private static final VariantInfo VARIANT_MULTIPART_FORMDATA = + new VariantInfo(MediaType.MULTIPART_FORM_DATA); + + public MultipartContainerConverter() { + super(VARIANT_MULTIPART_FORMDATA); + } + + @Override + public List<VariantInfo> getVariants(Class<?> source) throws IOException { + return null; + } + + @Override + public float score(Object source, Variant target, Resource resource) { + // this class only converts from multipart/form-data to Containers. + return -1.0F; + } + + @Override + public <T> T toObject(Representation source, Class<T> target, Resource resource) + throws IOException { + T result = toContainer(source, target, resource); + return result; + } + + + @SuppressWarnings("unchecked") + public <T> T toContainer(Representation source, Class<T> target, Resource resource) { + TransactionContainer result = null; + final DiskFileItemFactory factory = new DiskFileItemFactory(); + factory.setSizeThreshold(1000240); + final RestletFileUpload upload = new RestletFileUpload(factory); + try { + FileItemIterator iter = upload.getItemIterator(source); + FileItemStream item = iter.next(); + + // First part of the multi-part form data entity must be the container + // Name of the form field: FileRepresentation + if (item.isFormField()) { + if (item.getFieldName().equals("FileRepresentation")) { + final MediaType mediaType = MediaType.valueOf(item.getContentType()); + Representation entities = new InputRepresentation(item.openStream(), mediaType); + ConverterHelper helper = ConverterUtils.getBestHelper(entities, target, resource); + if (helper == null) { + throw new ResourceException(new Status(Status.CLIENT_ERROR_BAD_REQUEST, "Could not parse the FileRepresentation field. Probably it has an unsupported media type."), resource.getRequest(), resource.getResponse()); + } + result = (TransactionContainer) helper.toObject(source, target, resource); + } else { + throw new ResourceException(new Status(Status.CLIENT_ERROR_BAD_REQUEST, "No entities submitted."), resource.getRequest(), resource.getResponse()); + } + } else { + throw new ResourceException(new Status(Status.CLIENT_ERROR_BAD_REQUEST, "Form contains unexpected content."), resource.getRequest(), resource.getResponse()); + } + + // Get files, store to tmp dir. + while (iter.hasNext()) { + item = iter.next(); + final FileProperties file = FileSystem.upload(item, resource.getAttribute("srid")); + result.addFile(item.getName(), file); + } + } catch (FileUploadException | IOException | NoSuchAlgorithmException e) { + throw new ResourceException(new Status(Status.SERVER_ERROR_INTERNAL, "The file upload failed."), e, resource.getRequest(), resource.getResponse()); + } + return (T) result; + } + + @Override + public Representation toRepresentation(Object source, Variant target, Resource resource) + throws IOException { + return null; + } + +} diff --git a/src/main/java/caosdb/server/converter/xml/EntityXMLConverterHelper.java b/src/main/java/caosdb/server/converter/xml/EntityXMLConverterHelper.java index 5b425e8d88e2621975783ea99efb48070ee6f72e..8aa039e2ac4637ac76043e0b60094f799a4eaf7e 100644 --- a/src/main/java/caosdb/server/converter/xml/EntityXMLConverterHelper.java +++ b/src/main/java/caosdb/server/converter/xml/EntityXMLConverterHelper.java @@ -2,41 +2,35 @@ package caosdb.server.converter.xml; import java.io.IOException; import java.util.Collection; -import java.util.Collections; import java.util.List; -import org.apache.shiro.SecurityUtils; import org.apache.shiro.subject.Subject; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.jdom2.ProcessingInstruction; import org.restlet.data.MediaType; -import org.restlet.engine.converter.ConverterHelper; +import org.restlet.data.Status; import org.restlet.engine.resource.VariantInfo; import org.restlet.representation.Representation; import org.restlet.representation.Variant; import org.restlet.resource.Resource; +import org.restlet.resource.ResourceException; import caosdb.server.accessControl.AuthenticationUtils; import caosdb.server.accessControl.Principal; import caosdb.server.accessControl.UserSources; +import caosdb.server.converter.misc.AbstractContainerHelper; import caosdb.server.entity.Entity; import caosdb.server.entity.EntityInterface; import caosdb.server.entity.container.Container; import caosdb.server.entity.container.TransactionContainer; import caosdb.server.resource.JdomRepresentation; -public class EntityXMLConverterHelper extends ConverterHelper { +public class EntityXMLConverterHelper extends AbstractContainerHelper { private static final VariantInfo VARIANT_TEXT_XML = new VariantInfo(MediaType.TEXT_XML); private static final VariantInfo VARIANT_APPLICATION_XML = new VariantInfo(MediaType.APPLICATION_XML); - private static final List<Class<?>> objectClasses = Collections.singletonList(TransactionContainer.class); private static final XMLParser xmlParser = new XMLParser(); - @Override - public List<Class<?>> getObjectClasses(Variant source) { - return objectClasses; - } - @Override public List<VariantInfo> getVariants(Class<?> source) throws IOException { List<VariantInfo> result = null; @@ -57,13 +51,13 @@ public class EntityXMLConverterHelper extends ConverterHelper { try { xml = xmlParser.parse(source.getStream()); } catch (JDOMException e) { - throw new IOException(e); + throw new ResourceException(new Status(Status.CLIENT_ERROR_BAD_REQUEST, "Could not parse XML."), e, resource.getRequest(), resource.getResponse()); } - return (T) createContainer(xml, resource.getAttribute("srid"), resource.getRequest().getDate().getTime(), SecurityUtils.getSubject()); + return (T) createContainer(xml, resource); } - private Container<? extends EntityInterface> createContainer(Document xml, String sRID, long timestamp, Subject owner) { - TransactionContainer result = new TransactionContainer( owner, timestamp, sRID); + private Container<? extends EntityInterface> createContainer(Document xml, Resource resource) { + TransactionContainer result = createContainer(resource); for (Element e : xml.getRootElement().getChildren()) { result.add(new Entity(e)); } @@ -73,6 +67,7 @@ public class EntityXMLConverterHelper extends ConverterHelper { @Override public Representation toRepresentation(Object source, Variant target, Resource resource) throws IOException { + return toJdomRepresentation((TransactionContainer) source, resource); } @@ -207,27 +202,12 @@ public class EntityXMLConverterHelper extends ConverterHelper { public float score(Object source, Variant target, Resource resource) { float result = -1.0F; - if (source instanceof Container && isCompatible(target)) { + if (source instanceof TransactionContainer && isCompatible(target)) { result = 1.0F; } return result; } - /* - ********************************************************************** - * The following function is stolen from {@link - * org.restlet.engine.converter.StatusInfoHtmlConverter} and adapted. - * - * Licensed under Apache 2.0. - * - * Author: Manuel Boillod. - * Copyright 2005-2019 Talend - * ******************************************************************** - */ - @Override - public <T> float score(Representation source, Class<T> target, Resource resource) { - return -1.0F; - } } diff --git a/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java b/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java index 95f9b0147f7b0bf4cfcf88029ce52a650af856ca..ca683a5e7e3ad1625ef606fd671f9e70042e7331 100644 --- a/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java +++ b/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java @@ -23,31 +23,18 @@ */ package caosdb.server.resource; -import static caosdb.server.utils.Utils.isNonNullInteger; -import static java.net.URLDecoder.decode; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; import org.apache.shiro.SecurityUtils; import org.apache.shiro.subject.Subject; -import org.restlet.data.Form; -import org.restlet.data.Parameter; import org.restlet.resource.ServerResource; import caosdb.server.utils.WebinterfaceUtils; /** - * Class is still under construction. + * Base class for all CaosDB Server Resources. * * @author Timm Fitschen */ public abstract class AbstractCaosDBServerResource extends ServerResource { - private final Map<String, String> flags = new HashMap<String, String>(); - private Long timestamp = null; - private String[] requestedItems = null; - private ArrayList<Integer> requestedIDs = new ArrayList<Integer>(); - private ArrayList<String> requestedNames = new ArrayList<String>(); private WebinterfaceUtils utils; /** Return the {@link WebinterfaceUtils} instance for this resource. */ @@ -55,11 +42,11 @@ public abstract class AbstractCaosDBServerResource extends ServerResource { return this.utils; } - public Long getTimestamp() { - return this.timestamp; + public final Long getTimestamp() { + return getRequest().getDate().getTime(); } - public Subject getUser() { + public final Subject getUser() { Subject ret = SecurityUtils.getSubject(); return ret; } @@ -79,48 +66,9 @@ public abstract class AbstractCaosDBServerResource extends ServerResource { this.utils = WebinterfaceUtils.getInstance(getHostRef()); - this.timestamp = getRequest().getDate().getTime(); - this.setAttribute("xsl", getXSLScript()); - String specifier = (String) getRequestAttributes().get("specifier"); - if (specifier != null && !specifier.equals("")) { - try { - specifier = decode(specifier, "UTF-8"); - } catch (final UnsupportedEncodingException e) { - // this should never happen - e.printStackTrace(); - System.exit(1); - } - - this.requestedItems = specifier.split("&"); - for (final String requestedItem : this.requestedItems) { - if (isNonNullInteger(requestedItem)) { - final int id = Integer.parseInt(requestedItem); - if (id > 0) { - getRequestedIDs().add(id); - } - } else if (requestedItem.equalsIgnoreCase("all")) { - getRequestedNames().clear(); - getRequestedIDs().clear(); - getRequestedNames().add("all"); - break; - } else { - getRequestedNames().add(requestedItem); - } - } - } - - // flags - final Form queryAsForm = getRequest().getResourceRef().getQueryAsForm(true); - if (queryAsForm != null) { - for (final Parameter p : queryAsForm) { - getFlags() - .put( - p.getName(), - (p.getValue() == null || p.getValue().isEmpty() ? null : p.getValue())); - } - } + } @Override @@ -130,24 +78,8 @@ public abstract class AbstractCaosDBServerResource extends ServerResource { return this.utils.getWebinterfaceURI("webcaosdb.xsl"); } - protected String getSRID() { + public final String getSRID() { return getRequest().getAttributes().get("SRID").toString(); } - public ArrayList<Integer> getRequestedIDs() { - return this.requestedIDs; - } - - public ArrayList<String> getRequestedNames() { - return this.requestedNames; - } - - public void setRequestedNames(final ArrayList<String> requestedNames) { - this.requestedNames = requestedNames; - } - - public Map<String, String> getFlags() { - return this.flags; - } - } diff --git a/src/main/java/caosdb/server/resource/AuthenticationResource.java b/src/main/java/caosdb/server/resource/AuthenticationResource.java index 4da792192494185f23b60512052cf16edeaff53a..ef80acd5d3e97eea39754e524fcb0186cbcc7d93 100644 --- a/src/main/java/caosdb/server/resource/AuthenticationResource.java +++ b/src/main/java/caosdb/server/resource/AuthenticationResource.java @@ -25,6 +25,8 @@ package caosdb.server.resource; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; import java.util.logging.Level; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AccountException; @@ -32,6 +34,7 @@ import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.CredentialsException; import org.apache.shiro.subject.Subject; import org.restlet.data.Form; +import org.restlet.data.Parameter; import org.restlet.data.Reference; import org.restlet.data.Status; import org.restlet.representation.Representation; @@ -105,4 +108,18 @@ public class AuthenticationResource extends AbstractCaosDBServerResource { return null; } + public final Map<String, String> getFlags() { + final Form queryAsForm = getRequest().getResourceRef().getQueryAsForm(true); + final Map<String, String> result = new HashMap<>(); + if (queryAsForm != null) { + for (final Parameter p : queryAsForm) { + result + .put( + p.getName(), + (p.getValue() == null || p.getValue().isEmpty() ? null : p.getValue())); + } + } + return result; + } + } diff --git a/src/main/java/caosdb/server/resource/EntityOwnerResource.java b/src/main/java/caosdb/server/resource/EntityOwnerResource.java index d4e58f1ce50e02d93f465e39a2b84e9b61307f73..2754760a609811ae0f189f0cb05bec1d8ad8c5d1 100644 --- a/src/main/java/caosdb/server/resource/EntityOwnerResource.java +++ b/src/main/java/caosdb/server/resource/EntityOwnerResource.java @@ -22,8 +22,16 @@ */ package caosdb.server.resource; -import caosdb.server.resource.transaction.EntityResource; +import java.util.Map; +import caosdb.server.resource.transaction.AbstractEntityResource; -public class EntityOwnerResource extends EntityResource { +public class EntityOwnerResource extends AbstractEntityResource { + + @Override + public Map<String, String> getFlags() { + Map<String, String> result = super.getFlags(); + result.put("owner", null); + return result; + } } diff --git a/src/main/java/caosdb/server/resource/EntityPermissionsResource.java b/src/main/java/caosdb/server/resource/EntityPermissionsResource.java index b29d6c5eab1a21e8e86a56fbc3c806c97c426769..f7bc39a16ef116484c68c89ed6e965e4e229642f 100644 --- a/src/main/java/caosdb/server/resource/EntityPermissionsResource.java +++ b/src/main/java/caosdb/server/resource/EntityPermissionsResource.java @@ -23,16 +23,11 @@ package caosdb.server.resource; import caosdb.server.entity.container.RetrieveContainer; -import caosdb.server.resource.transaction.EntityResource; +import caosdb.server.resource.transaction.AbstractEntityResource; import caosdb.server.resource.transaction.handlers.RequestHandler; import caosdb.server.resource.transaction.handlers.RetrieveGlobalEntityPermissionsHandler; -public class EntityPermissionsResource extends EntityResource { - - public EntityPermissionsResource() { - // only retrieval is allowed - super(true, false, false, false); - } +public class EntityPermissionsResource extends AbstractEntityResource { @Override protected RequestHandler<RetrieveContainer> getGetRequestHandler() { diff --git a/src/main/java/caosdb/server/resource/PermissionRulesResource.java b/src/main/java/caosdb/server/resource/PermissionRulesResource.java index bcb6539aa0a1fb6c80df012b54474c55d5f6d7b2..98841db687b2777e31607d26bfb890b56d647f72 100644 --- a/src/main/java/caosdb/server/resource/PermissionRulesResource.java +++ b/src/main/java/caosdb/server/resource/PermissionRulesResource.java @@ -46,7 +46,7 @@ public class PermissionRulesResource extends XMLServerResource { protected Representation httpGetInChildClass() throws ConnectionException, IOException, SQLException, CaosDBException, NoSuchAlgorithmException, Exception { - final String role = getRequestedNames().get(0); + final String role = getSpecifier(); getUser().checkPermission(ACMPermissions.PERMISSION_RETRIEVE_ROLE_PERMISSIONS(role)); @@ -73,7 +73,7 @@ public class PermissionRulesResource extends XMLServerResource { public Representation httpPutInChildClass(final Representation entity) throws Exception { final Element root = parseEntity(entity).getRootElement(); - final String role = getRequestedNames().get(0); + final String role = getSpecifier(); final HashSet<PermissionRule> rules = new HashSet<PermissionRule>(); for (final Element e : root.getChildren()) { diff --git a/src/main/java/caosdb/server/resource/RolesResource.java b/src/main/java/caosdb/server/resource/RolesResource.java index fc7d092e9310f9860f6b99f5a256f2187030f225..09fb48da697110f6cf5551745e66c553cd928b92 100644 --- a/src/main/java/caosdb/server/resource/RolesResource.java +++ b/src/main/java/caosdb/server/resource/RolesResource.java @@ -52,8 +52,7 @@ public class RolesResource extends XMLServerResource { final Element root = generateRootElement(); final Document document = new Document(); - if (!getRequestedNames().isEmpty()) { - final String name = getRequestedNames().get(0); + final String name = getSpecifier(); if (name != null) { getUser().checkPermission(ACMPermissions.PERMISSION_RETRIEVE_ROLE_DESCRIPTION(name)); final RetrieveRoleTransaction t = new RetrieveRoleTransaction(name); @@ -68,7 +67,6 @@ public class RolesResource extends XMLServerResource { } } } - } document.setRootElement(root); return ok(document); @@ -78,8 +76,7 @@ public class RolesResource extends XMLServerResource { protected Representation httpDeleteInChildClass() throws ConnectionException, SQLException, CaosDBException, IOException, NoSuchAlgorithmException, Exception { - if (!getRequestedNames().isEmpty()) { - final String name = getRequestedNames().get(0); + final String name = getSpecifier(); if (name != null) { final DeleteRoleTransaction t = new DeleteRoleTransaction(name); try { @@ -92,7 +89,6 @@ public class RolesResource extends XMLServerResource { } } } - } return new StringRepresentation("ok"); } @@ -133,7 +129,7 @@ public class RolesResource extends XMLServerResource { protected Representation httpPutInChildClass(final Representation entity) throws ConnectionException, JDOMException, Exception, xmlNotWellFormedException { - final String name = getRequestedNames().get(0); + final String name = getSpecifier(); String description = null; final Form f = new Form(entity); diff --git a/src/main/java/caosdb/server/resource/UserResource.java b/src/main/java/caosdb/server/resource/UserResource.java index f84ff0c330f28a6c152b14906cd07e2d7f5fd6ae..51bf19b409a3ec56c02e2907ea5b72fefe0a8376 100644 --- a/src/main/java/caosdb/server/resource/UserResource.java +++ b/src/main/java/caosdb/server/resource/UserResource.java @@ -60,9 +60,8 @@ public class UserResource extends XMLServerResource { final Document doc = new Document(); final Element rootElem = generateRootElement(); - if (!getRequestedNames().isEmpty()) { try { - final String username = getRequestedNames().get(0); + final String username = getSpecifier(); final String realm = (getRequestAttributes().containsKey("realm") ? (String) getRequestAttributes().get("realm") @@ -80,7 +79,6 @@ public class UserResource extends XMLServerResource { } throw m; } - } doc.setRootElement(rootElem); return ok(doc); @@ -92,7 +90,7 @@ public class UserResource extends XMLServerResource { try { final Form form = new Form(entity); - final String username = getRequestedNames().get(0); + final String username = getSpecifier(); final String realm = (getRequestAttributes().containsKey("realm") ? (String) getRequestAttributes().get("realm") @@ -187,7 +185,7 @@ public class UserResource extends XMLServerResource { final Document doc = new Document(); final Element rootElem = generateRootElement(); - final DeleteUserTransaction t = new DeleteUserTransaction(getRequestedNames().get(0)); + final DeleteUserTransaction t = new DeleteUserTransaction(getSpecifier()); try { t.execute(); } catch (final Message m) { diff --git a/src/main/java/caosdb/server/resource/UserRolesResource.java b/src/main/java/caosdb/server/resource/UserRolesResource.java index 0b129062ff509c0cf91a628902dc059bff494a5c..7a85e4ad8e21e14858614aa192e532f9c17fa1f1 100644 --- a/src/main/java/caosdb/server/resource/UserRolesResource.java +++ b/src/main/java/caosdb/server/resource/UserRolesResource.java @@ -47,7 +47,7 @@ public class UserRolesResource extends XMLServerResource { protected Representation httpGetInChildClass() throws ConnectionException, IOException, SQLException, CaosDBException, NoSuchAlgorithmException, Exception { - final String user = getRequestedNames().get(0); + final String user = getSpecifier(); final String realm = (getRequestAttributes().get("realm") != null ? (String) getRequestAttributes().get("realm") @@ -73,7 +73,7 @@ public class UserRolesResource extends XMLServerResource { @Override protected Representation httpPutInChildClass(final Representation entity) throws ConnectionException, JDOMException, Exception, xmlNotWellFormedException { - final String user = getRequestedNames().get(0); + final String user = getSpecifier(); final String realm = (getRequestAttributes().get("realm") != null ? (String) getRequestAttributes().get("realm") diff --git a/src/main/java/caosdb/server/resource/XMLServerResource.java b/src/main/java/caosdb/server/resource/XMLServerResource.java index b0668268fffa4bc80d400fed318309a3bf50aa93..05b3e247b56347e46bec6a77fdec513fb7816ef5 100644 --- a/src/main/java/caosdb/server/resource/XMLServerResource.java +++ b/src/main/java/caosdb/server/resource/XMLServerResource.java @@ -1,57 +1,43 @@ /* - * ** header v3.0 - * This file is a part of the CaosDB Project. + * ** header v3.0 This file is a part of the CaosDB Project. * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * Copyright (C) 2019 IndiScale GmbH + * Copyright (C) 2018 Research Group Biomedical Physics, Max-Planck-Institute for Dynamics and + * Self-Organization Göttingen Copyright (C) 2019 IndiScale GmbH * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify it under the terms of the + * GNU Affero General Public License as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. + * You should have received a copy of the GNU Affero General Public License along with this program. + * If not, see <https://www.gnu.org/licenses/>. * * ** end header */ package caosdb.server.resource; -import static caosdb.server.utils.Utils.isNonNullInteger; -import static java.net.URLDecoder.decode; import java.io.IOException; import java.io.InputStream; -import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; import java.sql.SQLException; -import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.logging.Level; import org.apache.commons.fileupload.FileUploadException; -import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authz.AuthorizationException; import org.apache.shiro.subject.Subject; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; -import org.restlet.data.Form; -import org.restlet.data.Header; -import org.restlet.data.Parameter; import org.restlet.data.Status; import org.restlet.representation.Representation; import org.restlet.resource.Delete; import org.restlet.resource.Get; import org.restlet.resource.Post; import org.restlet.resource.Put; -import org.restlet.util.Series; import caosdb.server.CaosDBException; import caosdb.server.accessControl.AuthenticationUtils; import caosdb.server.accessControl.Principal; @@ -60,141 +46,48 @@ import caosdb.server.converter.xml.XMLParser; import caosdb.server.database.backend.implementation.MySQL.ConnectionException; import caosdb.server.entity.Message; import caosdb.server.utils.ServerMessages; -import caosdb.server.utils.WebinterfaceUtils; /** - * Class is still under construction. - * + * This is a temporary bridge class. It contains all code which is necessary for any resources that + * are hard-coded to deliver XML representations. + * * @author Timm Fitschen */ +@Deprecated public abstract class XMLServerResource extends AbstractCaosDBServerResource { - private final HashMap<String, String> flags = new HashMap<String, String>(); - private Long timestamp = null; private static final XMLParser xmlparser = new XMLParser(); - protected String sRID = null; // Server side request ID - private String cRID = null; // Client side request ID - private String[] requestedItems = null; - private ArrayList<Integer> requestedIDs = new ArrayList<Integer>(); - private ArrayList<String> requestedNames = new ArrayList<String>(); - private WebinterfaceUtils utils; - - /** Return the {@link WebinterfaceUtils} instance for this resource. */ - @Override - public WebinterfaceUtils getUtils() { - return this.utils; - } public static class xmlNotWellFormedException extends Exception { private static final long serialVersionUID = -6836378704013776849L; } - /** - * Returns the (probably unique) server request ID. - * - * @return The server request ID. - */ @Override - public String getSRID() { - return this.sRID; - } - - @Override - public Long getTimestamp() { - return this.timestamp; - } + protected void doRelease() {} - @Override - public Subject getUser() { - Subject ret = SecurityUtils.getSubject(); - return ret; + public String getSpecifier() { + return getRequestAttributes().get("specifier").toString(); } - /** - * Setup method, called by {@link org.restlet.resource.Resource#init(org.restlet.Context, - * org.restlet.Request, org.restlet.Response)}. - */ - @Override - protected void doInit() { - if (getRequestEntity().isTransient() && !getRequestEntity().isEmpty()) { - final ReReadableRepresentation r = new ReReadableRepresentation(getRequestEntity()); - getRequest().setEntity(r); - } - - this.utils = WebinterfaceUtils.getInstance(getHostRef()); - - this.timestamp = getRequest().getDate().getTime(); - - this.sRID = getRequest().getAttributes().get("SRID").toString(); - - final Series<Header> headers = getRequest().getHeaders(); - - this.setCRID(headers.getFirstValue("crequestid")); - - String specifier = (String) getRequestAttributes().get("specifier"); - if (specifier != null && !specifier.equals("")) { - try { - specifier = decode(specifier, "UTF-8"); - } catch (final UnsupportedEncodingException e) { - // this should never happen - e.printStackTrace(); - System.exit(1); - } - - this.requestedItems = specifier.split("&"); - for (final String requestedItem : this.requestedItems) { - if (isNonNullInteger(requestedItem)) { - final int id = Integer.parseInt(requestedItem); - if (id > 0) { - getRequestedIDs().add(id); - } - } else if (requestedItem.equalsIgnoreCase("all")) { - getRequestedNames().clear(); - getRequestedIDs().clear(); - getRequestedNames().add("all"); - break; - } else { - getRequestedNames().add(requestedItem); - } - } - } - - // flags - final Form queryAsForm = getRequest().getResourceRef().getQueryAsForm(true); - if (queryAsForm != null) { - for (final Parameter p : queryAsForm) { - getFlags() - .put( - p.getName(), - (p.getValue() == null || p.getValue().isEmpty() ? null : p.getValue())); - } - } - } - - @Override - protected void doRelease() {} - /** * Creates the XML root. * - * <p>The XML root node contains: + * <p> + * The XML root node contains: * * <p> * * <ul> - * <li>User info as per addUserInfo - * <li>The sRID (server-side request ID) - * <li>A timestamp - * <li>The URI to this resource. + * <li>User info as per addUserInfo + * <li>The sRID (server-side request ID) + * <li>A timestamp + * <li>The URI to this resource. */ protected Element generateRootElement() { final Element retRoot = new Element("Response"); addUserInfo(retRoot, getUser()); retRoot.setAttribute("srid", getSRID()); - if (this.getCRID() != null) { - retRoot.setAttribute("crid", this.getCRID()); - } retRoot.setAttribute("timestamp", getTimestamp().toString()); retRoot.setAttribute("baseuri", getRootRef().toString()); return retRoot; @@ -232,7 +125,8 @@ public abstract class XMLServerResource extends AbstractCaosDBServerResource { */ private void addRoles(Element userInfo, Subject user) { Collection<String> roles = UserSources.resolve(user.getPrincipals()); - if (roles == null) return; + if (roles == null) + return; Element rs = new Element("Roles"); for (String role : roles) { Element r = new Element("Role"); @@ -261,9 +155,8 @@ public abstract class XMLServerResource extends AbstractCaosDBServerResource { } } - protected abstract Representation httpGetInChildClass() - throws ConnectionException, IOException, SQLException, CaosDBException, - NoSuchAlgorithmException, Exception; + protected abstract Representation httpGetInChildClass() throws ConnectionException, IOException, + SQLException, CaosDBException, NoSuchAlgorithmException, Exception; @Post public Representation httpPost(final Representation entity) { @@ -294,9 +187,8 @@ public abstract class XMLServerResource extends AbstractCaosDBServerResource { return null; } - protected Representation httpDeleteInChildClass() - throws ConnectionException, SQLException, CaosDBException, IOException, - NoSuchAlgorithmException, Exception { + protected Representation httpDeleteInChildClass() throws ConnectionException, SQLException, + CaosDBException, IOException, NoSuchAlgorithmException, Exception { getResponse().setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED); return null; } @@ -312,7 +204,7 @@ public abstract class XMLServerResource extends AbstractCaosDBServerResource { protected Representation httpPostInChildClass(final Representation entity) throws ConnectionException, SQLException, CaosDBException, IOException, - NoSuchAlgorithmException, xmlNotWellFormedException, JDOMException, Exception { + NoSuchAlgorithmException, xmlNotWellFormedException, JDOMException, Exception { getResponse().setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED); return null; } @@ -331,11 +223,6 @@ public abstract class XMLServerResource extends AbstractCaosDBServerResource { } } - @Override - protected String getXSLScript() { - return this.utils.getWebinterfaceURI("webcaosdb.xsl"); - } - /** Wrap an element for an "OK" response. */ protected JdomRepresentation ok(Element root) { return ok(new Document(root)); @@ -350,8 +237,8 @@ public abstract class XMLServerResource extends AbstractCaosDBServerResource { } /** - * Return a Representation containing the error message and set the {@link Response}'s {@link - * Status}. + * Return a Representation containing the error message and set the {@link Response}'s + * {@link Status}. * * @param m - the error message. * @param status - the response status @@ -379,8 +266,8 @@ public abstract class XMLServerResource extends AbstractCaosDBServerResource { } /** - * Return a Representation containing the warning message but leave the {@link Response}'s {@link - * Status} where it is - which is usually 200 - OK when this method happens to be called. + * Return a Representation containing the warning message but leave the {@link Response}'s + * {@link Status} where it is - which is usually 200 - OK when this method happens to be called. * * @param m - the warning message. * @return A Representation of the warning. @@ -431,26 +318,6 @@ public abstract class XMLServerResource extends AbstractCaosDBServerResource { } } - @Override - public ArrayList<Integer> getRequestedIDs() { - return this.requestedIDs; - } - - @Override - public ArrayList<String> getRequestedNames() { - return this.requestedNames; - } - - @Override - public void setRequestedNames(final ArrayList<String> requestedNames) { - this.requestedNames = requestedNames; - } - - @Override - public HashMap<String, String> getFlags() { - return this.flags; - } - protected Element generateRootElement(Element... elements) { Element root = generateRootElement(); for (Element e : elements) { @@ -459,17 +326,4 @@ public abstract class XMLServerResource extends AbstractCaosDBServerResource { return root; } - /** - * Returns the client request ID, which can be set by the client. - * - * @return The cRID. - */ - public String getCRID() { - return cRID; - } - - public void setCRID(String cRID) { - this.cRID = cRID; - } - } diff --git a/src/main/java/caosdb/server/resource/transaction/AbstractEntityResource.java b/src/main/java/caosdb/server/resource/transaction/AbstractEntityResource.java new file mode 100644 index 0000000000000000000000000000000000000000..caf1d7c4f4a823939f39070670a8222e9b5eca67 --- /dev/null +++ b/src/main/java/caosdb/server/resource/transaction/AbstractEntityResource.java @@ -0,0 +1,110 @@ +package caosdb.server.resource.transaction; + + + +import static caosdb.server.utils.Utils.isNonNullInteger; +import static java.net.URLDecoder.decode; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.NoSuchAlgorithmException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import org.restlet.data.Form; +import org.restlet.data.Parameter; +import org.restlet.resource.Get; +import caosdb.server.CaosDBException; +import caosdb.server.database.backend.implementation.MySQL.ConnectionException; +import caosdb.server.entity.container.RetrieveContainer; +import caosdb.server.entity.container.TransactionContainer; +import caosdb.server.resource.AbstractCaosDBServerResource; +import caosdb.server.resource.transaction.handlers.RequestHandler; +import caosdb.server.resource.transaction.handlers.SimpleGetRequestHandler; +import caosdb.server.transaction.Retrieve; + +public abstract class AbstractEntityResource extends AbstractCaosDBServerResource { + + private ArrayList<Integer> requestedIDs = new ArrayList<Integer>(); + private ArrayList<String> requestedNames = new ArrayList<String>(); + + + public final ArrayList<Integer> getRequestedIDs() { + return this.requestedIDs; + } + + public final ArrayList<String> getRequestedNames() { + return this.requestedNames; + } + + protected RequestHandler<RetrieveContainer> getGetRequestHandler() { + return new SimpleGetRequestHandler(); + } + + @Get + protected final TransactionContainer httpGetInChildClass() throws ConnectionException, IOException, + SQLException, CaosDBException, NoSuchAlgorithmException, Exception { + + final long t1 = System.currentTimeMillis(); + + final RetrieveContainer entityContainer = + new RetrieveContainer(getUser(), getTimestamp(), getSRID(), getFlags()); + + getGetRequestHandler().handle(this, entityContainer); + + final Retrieve retrieve = new Retrieve(entityContainer); + retrieve.execute(); + + final long t2 = System.currentTimeMillis(); + entityContainer + .getTransactionBenchmark() + .addMeasurement(getClass().getSimpleName() + ".httpGetInChildClass", t2 - t1); + return entityContainer; + } + + public Map<String, String> getFlags() { + final Form queryAsForm = getRequest().getResourceRef().getQueryAsForm(true); + final Map<String, String> result = new HashMap<>(); + if (queryAsForm != null) { + for (final Parameter p : queryAsForm) { + result + .put( + p.getName(), + (p.getValue() == null || p.getValue().isEmpty() ? null : p.getValue())); + } + } + return result; + } + + @Override + public void doInit() { + String specifier = (String) getRequestAttributes().get("specifier"); + if (specifier != null && !specifier.equals("")) { + try { + specifier = decode(specifier, "UTF-8"); + } catch (final UnsupportedEncodingException e) { + // this should never happen + e.printStackTrace(); + System.exit(1); + } + + String[] requestedItems = specifier.split("&"); + for (final String requestedItem : requestedItems) { + if (isNonNullInteger(requestedItem)) { + final int id = Integer.parseInt(requestedItem); + if (id > 0) { + getRequestedIDs().add(id); + } + } else if (requestedItem.equalsIgnoreCase("all")) { + getRequestedNames().clear(); + getRequestedIDs().clear(); + getRequestedNames().add("all"); + break; + } else { + getRequestedNames().add(requestedItem); + } + } + } + } + +} diff --git a/src/main/java/caosdb/server/resource/transaction/EntityResource.java b/src/main/java/caosdb/server/resource/transaction/EntityResource.java index 367450fa053583df2a19b18b59d36bffbe465bbc..47d40918040ca85f0343d6cc5237618b1bb5d2c2 100644 --- a/src/main/java/caosdb/server/resource/transaction/EntityResource.java +++ b/src/main/java/caosdb/server/resource/transaction/EntityResource.java @@ -22,110 +22,29 @@ */ package caosdb.server.resource.transaction; -import java.io.IOException; -import java.security.NoSuchAlgorithmException; -import java.sql.SQLException; import org.jdom2.JDOMException; -import org.restlet.data.MediaType; -import org.restlet.data.Status; -import org.restlet.resource.Get; import org.restlet.resource.Post; import org.restlet.resource.Put; -import caosdb.server.CaosDBException; import caosdb.server.database.backend.implementation.MySQL.ConnectionException; import caosdb.server.entity.container.DeleteContainer; -import caosdb.server.entity.container.InsertContainer; -import caosdb.server.entity.container.RetrieveContainer; import caosdb.server.entity.container.TransactionContainer; -import caosdb.server.entity.container.UpdateContainer; -import caosdb.server.resource.AbstractCaosDBServerResource; -import caosdb.server.resource.transaction.handlers.FileUploadHandler; import caosdb.server.resource.transaction.handlers.IDHandler; import caosdb.server.resource.transaction.handlers.RequestHandler; -import caosdb.server.resource.transaction.handlers.SimpleGetRequestHandler; -import caosdb.server.resource.transaction.handlers.SimpleWriteHandler; import caosdb.server.transaction.Delete; import caosdb.server.transaction.Insert; -import caosdb.server.transaction.Retrieve; import caosdb.server.transaction.Update; -public class EntityResource extends AbstractCaosDBServerResource { +public class EntityResource extends AbstractEntityResource { - private final boolean get; - private final boolean post; - private final boolean put; - private final boolean delete; - - public EntityResource( - final boolean get, final boolean post, final boolean put, final boolean delete) { - this.get = get; - this.post = post; - this.put = put; - this.delete = delete; - } - - public EntityResource() { - this(true, true, true, true); - } - - protected RequestHandler<RetrieveContainer> getGetRequestHandler() { - return new SimpleGetRequestHandler(); - } protected RequestHandler<DeleteContainer> getDeleteRequestHandler() { return new IDHandler<DeleteContainer>(); } - protected RequestHandler<InsertContainer> getPostRequestHandler() { - if (getRequest().getEntity().getMediaType() != null - && getRequest().getEntity().getMediaType().equals(MediaType.MULTIPART_FORM_DATA, true)) { - return new FileUploadHandler<InsertContainer>(); - } else { - return new SimpleWriteHandler<InsertContainer>(); - } - } - - protected RequestHandler<UpdateContainer> getPutRequestHandler() { - if (getRequest().getEntity().getMediaType() != null - && getRequest().getEntity().getMediaType().equals(MediaType.MULTIPART_FORM_DATA, true)) { - return new FileUploadHandler<UpdateContainer>(); - } else { - return new SimpleWriteHandler<UpdateContainer>(); - } - } - - @Get - protected final TransactionContainer httpGetInChildClass() - throws ConnectionException, IOException, SQLException, CaosDBException, - NoSuchAlgorithmException, Exception { - - final long t1 = System.currentTimeMillis(); - if (!this.get) { - getResponse().setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED); - return null; - } - final RetrieveContainer entityContainer = - new RetrieveContainer(getUser(), getTimestamp(), getSRID(), getFlags()); - - getGetRequestHandler().handle(this, entityContainer); - - final Retrieve retrieve = new Retrieve(entityContainer); - retrieve.execute(); - - final long t2 = System.currentTimeMillis(); - entityContainer - .getTransactionBenchmark() - .addMeasurement(getClass().getSimpleName() + ".httpGetInChildClass", t2 - t1); - return entityContainer; - } @org.restlet.resource.Delete protected final TransactionContainer httpDeleteInChildClass() throws Exception { - if (!this.delete) { - getResponse().setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED); - return null; - } final DeleteContainer entityContainer = new DeleteContainer(getUser(), getTimestamp(), getSRID(), getFlags()); @@ -138,18 +57,9 @@ public class EntityResource extends AbstractCaosDBServerResource { } @Post - protected final TransactionContainer httpPostInChildClass(final TransactionContainer entities) + protected final TransactionContainer httpPostInChildClass(final TransactionContainer entityContainer) throws Exception { - if (!this.post) { - getResponse().setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED); - return null; - } - - final InsertContainer entityContainer = - new InsertContainer(getUser(), getTimestamp(), getSRID(), getFlags()); - - getPostRequestHandler().handle(this, entityContainer); final Insert insert = new Insert(entityContainer); insert.execute(); @@ -158,18 +68,9 @@ public class EntityResource extends AbstractCaosDBServerResource { } @Put - protected final TransactionContainer httpPutInChildClass(final TransactionContainer entities) + protected final TransactionContainer httpPutInChildClass(final TransactionContainer entityContainer) throws ConnectionException, JDOMException, Exception { - if (!this.put) { - getResponse().setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED); - return null; - } - - final UpdateContainer entityContainer = - new UpdateContainer(getUser(), getTimestamp(), getSRID(), getFlags()); - - getPutRequestHandler().handle(this, entityContainer); final Update update = new Update(entityContainer); update.execute(); diff --git a/src/main/java/caosdb/server/resource/transaction/handlers/FileUploadHandler.java b/src/main/java/caosdb/server/resource/transaction/handlers/FileUploadHandler.java deleted file mode 100644 index 48003f1525f006960cf155591bc14d9d684c1888..0000000000000000000000000000000000000000 --- a/src/main/java/caosdb/server/resource/transaction/handlers/FileUploadHandler.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header - */ -package caosdb.server.resource.transaction.handlers; - -import caosdb.server.FileSystem; -import caosdb.server.entity.FileProperties; -import caosdb.server.entity.container.WritableContainer; -import caosdb.server.resource.transaction.EntityResource; -import caosdb.server.utils.ServerMessages; -import java.io.IOException; -import org.apache.commons.fileupload.FileItemIterator; -import org.apache.commons.fileupload.FileItemStream; -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.jdom2.Element; -import org.restlet.data.MediaType; -import org.restlet.ext.fileupload.RestletFileUpload; - -public class FileUploadHandler<T extends WritableContainer> extends SimpleWriteHandler<T> { - - @Override - public void handle(final EntityResource t, final T container) throws Exception { - if (!t.getRequest().getEntity().getMediaType().equals(MediaType.MULTIPART_FORM_DATA, true)) { - throw new Exception("Wrong MEDIATYPE"); - } - final DiskFileItemFactory factory = new DiskFileItemFactory(); - factory.setSizeThreshold(1000240); - final RestletFileUpload upload = new RestletFileUpload(factory); - final FileItemIterator iter = upload.getItemIterator(t.getRequest().getEntity()); - - FileItemStream item = iter.next(); - - final Element element; - // First part of the multi-part form data entity must be the xml - // representation of the files. - // Name of the form field: FileRepresentation - if (item.isFormField()) { - if (item.getFieldName().equals("FileRepresentation")) { - element = t.parseEntity(item.openStream()).getRootElement(); - } else { - throw ServerMessages.NO_FILE_REPRESENTATION_SUBMITTED; - } - } else { - throw ServerMessages.FORM_CONTAINS_UNSUPPORTED_CONTENT; - } - - // Get files, store to tmp dir. - while (iter.hasNext()) { - item = iter.next(); - try { - final FileProperties file = FileSystem.upload(item, t.getSRID()); - container.addFile(item.getName(), file); - } catch (final IOException e) { - throw new FileUploadException(); - } - } - - // transform xml elements to entities and add them to the container. - processEntities(container, element); - } -} diff --git a/src/main/java/caosdb/server/resource/transaction/handlers/IDHandler.java b/src/main/java/caosdb/server/resource/transaction/handlers/IDHandler.java index e641ed416c86075d23a37d70ad791c26a820a966..00a2427237582ee28b02cde98fb728202d1e748f 100644 --- a/src/main/java/caosdb/server/resource/transaction/handlers/IDHandler.java +++ b/src/main/java/caosdb/server/resource/transaction/handlers/IDHandler.java @@ -23,12 +23,12 @@ package caosdb.server.resource.transaction.handlers; import caosdb.server.entity.container.EntityByIdContainer; -import caosdb.server.resource.transaction.EntityResource; +import caosdb.server.resource.transaction.AbstractEntityResource; public class IDHandler<T extends EntityByIdContainer> extends RequestHandler<T> { @Override - public void handle(final EntityResource t, final T container) throws Exception { + public void handle(final AbstractEntityResource t, final T container) throws Exception { for (final int id : t.getRequestedIDs()) { container.add(id); } diff --git a/src/main/java/caosdb/server/resource/transaction/handlers/RequestHandler.java b/src/main/java/caosdb/server/resource/transaction/handlers/RequestHandler.java index e1390fe81782b353ccf2e401a9918747c6084ab3..56ff94bcc76c4c164bb03f0a798c7c9761bf02b6 100644 --- a/src/main/java/caosdb/server/resource/transaction/handlers/RequestHandler.java +++ b/src/main/java/caosdb/server/resource/transaction/handlers/RequestHandler.java @@ -23,9 +23,9 @@ package caosdb.server.resource.transaction.handlers; import caosdb.server.entity.container.TransactionContainer; -import caosdb.server.resource.transaction.EntityResource; +import caosdb.server.resource.transaction.AbstractEntityResource; public abstract class RequestHandler<T extends TransactionContainer> { - public abstract void handle(final EntityResource t, T container) throws Exception; + public abstract void handle(final AbstractEntityResource t, T container) throws Exception; } diff --git a/src/main/java/caosdb/server/resource/transaction/handlers/RetrieveGlobalEntityPermissionsHandler.java b/src/main/java/caosdb/server/resource/transaction/handlers/RetrieveGlobalEntityPermissionsHandler.java index a1882857801659449516992b4a4cca34d643379c..f6f0553dcb5562a0f997f373d613fd488cee6394 100644 --- a/src/main/java/caosdb/server/resource/transaction/handlers/RetrieveGlobalEntityPermissionsHandler.java +++ b/src/main/java/caosdb/server/resource/transaction/handlers/RetrieveGlobalEntityPermissionsHandler.java @@ -24,12 +24,12 @@ package caosdb.server.resource.transaction.handlers; import caosdb.server.entity.container.RetrieveContainer; import caosdb.server.permissions.EntityPermission; -import caosdb.server.resource.transaction.EntityResource; +import caosdb.server.resource.transaction.AbstractEntityResource; public class RetrieveGlobalEntityPermissionsHandler extends SimpleGetRequestHandler { @Override - public void handle(final EntityResource t, final RetrieveContainer container) throws Exception { + public void handle(final AbstractEntityResource t, final RetrieveContainer container) throws Exception { super.handle(t, container); container.addMessage(EntityPermission.getAllEntityPermissions()); } diff --git a/src/main/java/caosdb/server/resource/transaction/handlers/RetriveOwnerRequestHandler.java b/src/main/java/caosdb/server/resource/transaction/handlers/RetriveOwnerRequestHandler.java deleted file mode 100644 index d942389a359b2c24eafc6ec4a98b230cbe33f226..0000000000000000000000000000000000000000 --- a/src/main/java/caosdb/server/resource/transaction/handlers/RetriveOwnerRequestHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header - */ -package caosdb.server.resource.transaction.handlers; - -import caosdb.server.entity.EntityInterface; -import caosdb.server.entity.container.RetrieveContainer; -import caosdb.server.resource.transaction.EntityResource; - -public class RetriveOwnerRequestHandler extends SimpleGetRequestHandler { - - @Override - public void handle(final EntityResource t, final RetrieveContainer container) throws Exception { - super.handle(t, container); - for (final EntityInterface e : container) { - e.setFlag("owner", null); - } - } -} diff --git a/src/main/java/caosdb/server/resource/transaction/handlers/SimpleGetRequestHandler.java b/src/main/java/caosdb/server/resource/transaction/handlers/SimpleGetRequestHandler.java index 8fbb9d25cb33d2d0a75ce8405a164c1e8c9ce0fd..3e712885f4e78449f5cb94b1db5f936989800751 100644 --- a/src/main/java/caosdb/server/resource/transaction/handlers/SimpleGetRequestHandler.java +++ b/src/main/java/caosdb/server/resource/transaction/handlers/SimpleGetRequestHandler.java @@ -23,12 +23,12 @@ package caosdb.server.resource.transaction.handlers; import caosdb.server.entity.container.RetrieveContainer; -import caosdb.server.resource.transaction.EntityResource; +import caosdb.server.resource.transaction.AbstractEntityResource; public class SimpleGetRequestHandler extends IDHandler<RetrieveContainer> { @Override - public void handle(final EntityResource t, final RetrieveContainer container) throws Exception { + public void handle(final AbstractEntityResource t, final RetrieveContainer container) throws Exception { super.handle(t, container); for (final String name : t.getRequestedNames()) { container.add(name); diff --git a/src/main/java/caosdb/server/resource/transaction/handlers/SimpleWriteHandler.java b/src/main/java/caosdb/server/resource/transaction/handlers/SimpleWriteHandler.java deleted file mode 100644 index 66afef752797d841bf498d088094703f26f82273..0000000000000000000000000000000000000000 --- a/src/main/java/caosdb/server/resource/transaction/handlers/SimpleWriteHandler.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * ** header v3.0 - * This file is a part of the CaosDB Project. - * - * Copyright (C) 2018 Research Group Biomedical Physics, - * Max-Planck-Institute for Dynamics and Self-Organization Göttingen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - * - * ** end header - */ -package caosdb.server.resource.transaction.handlers; - -import java.util.List; -import org.jdom2.Element; -import caosdb.server.entity.container.WritableContainer; -import caosdb.server.resource.transaction.EntityResource; - -public class SimpleWriteHandler<T extends WritableContainer> extends RequestHandler<T> { - - /** - * Transform child elements of parameter 'element' to entities and add them to the container. Iff - * parameter 'tag' is not null, only elements with that tag name will be transformed into - * entities. The others will be ignored. - * - * @param container - * @param element - * @param tag - * @throws Exception - */ - protected void processEntities(final WritableContainer container, final Element element) - throws Exception { - - final List<Element> insertEntities; - insertEntities = element.getChildren(); - - for (final Element e : insertEntities) { - container.add(e); - } - } - - @Override - public void handle(final EntityResource t, final T container) throws Exception { - final Element element = t.parseEntity(t.getRequest().getEntity()).getRootElement(); - processEntities(container, element); - } -} diff --git a/src/main/java/caosdb/server/transaction/Insert.java b/src/main/java/caosdb/server/transaction/Insert.java index 627ada52655c5e7802e98172d1c32f8280a95fb4..36ebf01272cf7f6d2f32ec05669664acd840210d 100644 --- a/src/main/java/caosdb/server/transaction/Insert.java +++ b/src/main/java/caosdb/server/transaction/Insert.java @@ -22,20 +22,19 @@ */ package caosdb.server.transaction; +import org.apache.shiro.SecurityUtils; import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.InsertEntity; import caosdb.server.entity.EntityInterface; import caosdb.server.entity.FileProperties; -import caosdb.server.entity.container.InsertContainer; import caosdb.server.entity.container.TransactionContainer; import caosdb.server.permissions.EntityACL; import caosdb.server.utils.EntityStatus; import caosdb.server.utils.ServerMessages; -import org.apache.shiro.SecurityUtils; -public class Insert extends WriteTransaction<InsertContainer> { +public class Insert extends WriteTransaction<TransactionContainer> { - public Insert(final InsertContainer container) { + public Insert(final TransactionContainer container) { super(container); } diff --git a/src/main/java/caosdb/server/transaction/Update.java b/src/main/java/caosdb/server/transaction/Update.java index 8edd27d0aa0250ffebadc8d9a9639490daf1e2c7..ae39ade73ae7d4982bc36aaa793cedc1ac81fcea 100644 --- a/src/main/java/caosdb/server/transaction/Update.java +++ b/src/main/java/caosdb/server/transaction/Update.java @@ -22,6 +22,12 @@ */ package caosdb.server.transaction; +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.util.HashSet; +import java.util.Set; +import org.apache.shiro.authz.AuthorizationException; +import com.google.common.base.Objects; import caosdb.server.CaosDBException; import caosdb.server.database.access.Access; import caosdb.server.database.backend.transaction.RetrieveFullEntity; @@ -31,23 +37,16 @@ import caosdb.server.entity.EntityInterface; import caosdb.server.entity.FileProperties; import caosdb.server.entity.RetrieveEntity; import caosdb.server.entity.container.TransactionContainer; -import caosdb.server.entity.container.UpdateContainer; import caosdb.server.entity.wrapper.Parent; import caosdb.server.entity.wrapper.Property; import caosdb.server.permissions.EntityPermission; import caosdb.server.permissions.Permission; import caosdb.server.utils.EntityStatus; import caosdb.server.utils.ServerMessages; -import com.google.common.base.Objects; -import java.io.IOException; -import java.security.NoSuchAlgorithmException; -import java.util.HashSet; -import java.util.Set; -import org.apache.shiro.authz.AuthorizationException; -public class Update extends WriteTransaction<UpdateContainer> { +public class Update extends WriteTransaction<TransactionContainer> { - public Update(final UpdateContainer container) { + public Update(final TransactionContainer container) { super(container); }