diff --git a/pom.xml b/pom.xml index 502b5bab4eb850fda88d5c7c80cd7a3add30a59f..ca35415fb2aedacd3e960132a9afc099bb701bf8 100644 --- a/pom.xml +++ b/pom.xml @@ -50,6 +50,11 @@ </repository> </repositories> <dependencies> + <dependency> + <groupId>org.codehaus.jettison</groupId> + <artifactId>jettison</artifactId> + <version>1.4.0</version> + </dependency> <dependency> <groupId>de.timmfitschen</groupId> <artifactId>easy-units</artifactId> diff --git a/src/main/java/caosdb/server/CaosDBServer.java b/src/main/java/caosdb/server/CaosDBServer.java index 07a57c5918405f7ef5f8fd6949d9dfd32bd08434..18e20aa3d35a3572560037df4b59efe3bdd3f92f 100644 --- a/src/main/java/caosdb/server/CaosDBServer.java +++ b/src/main/java/caosdb/server/CaosDBServer.java @@ -27,6 +27,7 @@ import caosdb.server.accessControl.OneTimeTokenRealm; import caosdb.server.accessControl.Principal; import caosdb.server.accessControl.SessionToken; import caosdb.server.accessControl.SessionTokenRealm; +import caosdb.server.converter.misc.EntityJsonConverterHelper; import caosdb.server.converter.misc.HttpStatusConverter; import caosdb.server.converter.misc.MultipartContainerConverter; import caosdb.server.converter.xml.EntityXMLConverterHelper; @@ -348,13 +349,20 @@ public class CaosDBServer extends Application { init.release(); Engine.getInstance().getRegisteredConverters().clear(); - Engine.getInstance().getRegisteredConverters().add(new DefaultConverter()); // add XML Converters EntityXMLConverterHelper xmlConverter = new EntityXMLConverterHelper(); Engine.getInstance().getRegisteredConverters().add(xmlConverter); - Engine.getInstance().getRegisteredConverters().add(new MultipartContainerConverter()); Engine.getInstance().getRegisteredConverters().add(new HttpStatusConverter(xmlConverter)); + // add JSON Converters + EntityJsonConverterHelper jsonConverter = new EntityJsonConverterHelper(); + Engine.getInstance().getRegisteredConverters().add(jsonConverter); + Engine.getInstance().getRegisteredConverters().add(new HttpStatusConverter(jsonConverter)); + + // other + Engine.getInstance().getRegisteredConverters().add(new MultipartContainerConverter()); + Engine.getInstance().getRegisteredConverters().add(new DefaultConverter()); + if (INSECURE) { runHTTPServer(port_http, initialConnections, maxTotalConnections); } else { diff --git a/src/main/java/caosdb/server/converter/misc/AbstractContainerHelper.java b/src/main/java/caosdb/server/converter/misc/AbstractContainerHelper.java index 01afb30b8e481d1b05e74ff64909baa7bd57bce5..9bace44d7756ff95ed523cc7be1f87275d175d67 100644 --- a/src/main/java/caosdb/server/converter/misc/AbstractContainerHelper.java +++ b/src/main/java/caosdb/server/converter/misc/AbstractContainerHelper.java @@ -66,4 +66,55 @@ public abstract class AbstractContainerHelper extends ConverterHelper { return null; } + + /* + ********************************************************************** + * 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 + * ******************************************************************** + */ + /** + * Indicates if the given variant is compatible with the media types supported by this converter. + * + * @param variant The variant. + * @return True if the given variant is compatible with the media types supported by this + * converter. + */ + protected boolean isCompatible(Variant variant) { + if (variant != null) { + for (VariantInfo v : variants) { + if (v.isCompatible(variant)) { + return true; + } + } + } + return false; + } + + /* + ********************************************************************** + * 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 final float score(Object source, Variant target, Resource resource) { + float result = -1.0F; + + if (source instanceof TransactionContainer && isCompatible(target)) { + result = 1.0F; + } + + return result; + } } diff --git a/src/main/java/caosdb/server/converter/misc/CaosDBStatusService.java b/src/main/java/caosdb/server/converter/misc/CaosDBStatusService.java index f0acd7a16c38fe0281ebb40335987b31c9117934..ef0f88cd07b92573fde8229a1b8649126efc4171 100644 --- a/src/main/java/caosdb/server/converter/misc/CaosDBStatusService.java +++ b/src/main/java/caosdb/server/converter/misc/CaosDBStatusService.java @@ -2,6 +2,4 @@ package caosdb.server.converter.misc; import org.restlet.service.StatusService; -public class CaosDBStatusService extends StatusService { - -} +public class CaosDBStatusService extends StatusService {} diff --git a/src/main/java/caosdb/server/converter/misc/EntityJsonConverterHelper.java b/src/main/java/caosdb/server/converter/misc/EntityJsonConverterHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..47af9457405755733e557b8423c4f40d63577e75 --- /dev/null +++ b/src/main/java/caosdb/server/converter/misc/EntityJsonConverterHelper.java @@ -0,0 +1,114 @@ +package caosdb.server.converter.misc; + +import caosdb.server.converter.xml.EntityXMLConverterHelper; +import caosdb.server.entity.container.TransactionContainer; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import org.apache.commons.io.output.XmlStreamWriter; +import org.codehaus.jettison.badgerfish.BadgerFishXMLStreamReader; +import org.codehaus.jettison.badgerfish.BadgerFishXMLStreamWriter; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.jdom2.Document; +import org.jdom2.JDOMException; +import org.jdom2.input.StAXStreamBuilder; +import org.jdom2.output.StAXStreamOutputter; +import org.restlet.data.MediaType; +import org.restlet.engine.resource.VariantInfo; +import org.restlet.representation.Representation; +import org.restlet.representation.Variant; +import org.restlet.representation.WriterRepresentation; +import org.restlet.resource.Resource; + +public class EntityJsonConverterHelper extends AbstractContainerHelper { + + public static final VariantInfo VARIANT_APPLICATION_JSON = + new VariantInfo(MediaType.APPLICATION_JSON); + private EntityXMLConverterHelper xmlConverter; + + public EntityJsonConverterHelper() { + super(VARIANT_APPLICATION_JSON); + this.xmlConverter = new EntityXMLConverterHelper(); + } + + @SuppressWarnings("unchecked") + @Override + public <T> T toObject(Representation source, Class<T> target, Resource resource) + throws IOException { + + try { + Document doc = toXML(source); + return (T) xmlConverter.toContainer(doc, resource); + } catch (JSONException | XMLStreamException | JDOMException e) { + throw new IOException(e); + } + } + + private Document toXML(Representation source) + throws JSONException, IOException, XMLStreamException, JDOMException { + JSONObject json = new JSONObject(source.getText()); + return toXML(json); + } + + @Override + public Representation toRepresentation(Object source, Variant target, Resource resource) + throws IOException { + try { + return toJsonRepresentation((TransactionContainer) source, resource); + } catch (JSONException | XMLStreamException e) { + throw new IOException(e); + } + } + + public String toJsonString(Document doc) throws UnsupportedEncodingException, XMLStreamException { + ByteArrayOutputStream o = new ByteArrayOutputStream(); + BadgerFishXMLStreamWriter w = new BadgerFishXMLStreamWriter(new XmlStreamWriter(o)); + + StAXStreamOutputter outputter2 = new StAXStreamOutputter(); + outputter2.getFormat().setExpandEmptyElements(true); + outputter2.output(doc, w); + + return o.toString("utf-8"); + } + + public JSONObject toJson(Document doc) throws IOException, JSONException, XMLStreamException { + return new JSONObject(toJsonString(doc)); + } + + public Document toXML(JSONObject json) + throws JDOMException, IOException, XMLStreamException, JSONException { + + XMLStreamReader r = new BadgerFishXMLStreamReader(json); + + StAXStreamBuilder b = new StAXStreamBuilder(); + Document doc = b.build(r); + + return doc; + } + + private Representation toJsonRepresentation(TransactionContainer source, Resource resource) + throws IOException, JSONException, XMLStreamException { + Document document = xmlConverter.toDocument(source, resource); + JSONObject jsonObject = toJson(document); + return toJsonRepresentation(jsonObject, resource); + } + + private Representation toJsonRepresentation(JSONObject jsonObject, Resource resource) { + // TODO move to own class + return new WriterRepresentation(MediaType.APPLICATION_JSON) { + + @Override + public void write(Writer writer) throws IOException { + try { + jsonObject.write(writer); + } catch (JSONException e) { + throw new IOException(e); + } + } + }; + } +} diff --git a/src/main/java/caosdb/server/converter/misc/HttpStatusConverter.java b/src/main/java/caosdb/server/converter/misc/HttpStatusConverter.java index 926a61e1ea54645584290800850b488ffbe8c829..d58f0280eb2e8a94228b9b876c7505e48ec7e000 100644 --- a/src/main/java/caosdb/server/converter/misc/HttpStatusConverter.java +++ b/src/main/java/caosdb/server/converter/misc/HttpStatusConverter.java @@ -1,5 +1,8 @@ package caosdb.server.converter.misc; +import caosdb.server.entity.Message; +import caosdb.server.entity.container.TransactionContainer; +import caosdb.server.utils.ServerMessages; import java.io.IOException; import java.util.List; import org.apache.shiro.SecurityUtils; @@ -11,9 +14,6 @@ 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.Message; -import caosdb.server.entity.container.TransactionContainer; -import caosdb.server.utils.ServerMessages; public class HttpStatusConverter extends ConverterHelper { @@ -88,8 +88,12 @@ public class HttpStatusConverter extends ConverterHelper { if (status.getCode() == 500) { t.addMessage(ServerMessages.UNKNOWN_ERROR(requestId)); } else { - t.addMessage(new Message((Status.valueOf(status.getCode()).isError() ? "Error" : "Info"), - status.getCode(), status.getReasonPhrase(), status.getDescription())); + t.addMessage( + new Message( + (Status.valueOf(status.getCode()).isError() ? "Error" : "Info"), + status.getCode(), + status.getReasonPhrase(), + status.getDescription())); } return containerConverter.toRepresentation(t, target, resource); } diff --git a/src/main/java/caosdb/server/converter/misc/MultipartContainerConverter.java b/src/main/java/caosdb/server/converter/misc/MultipartContainerConverter.java index 7a336295eb39fe507667e9fc5036c4daa37f64de..cd5b7b3fc9f28f00e491ead3f008692c9a7b0c0e 100644 --- a/src/main/java/caosdb/server/converter/misc/MultipartContainerConverter.java +++ b/src/main/java/caosdb/server/converter/misc/MultipartContainerConverter.java @@ -39,12 +39,6 @@ public class MultipartContainerConverter extends AbstractContainerHelper { super(VARIANT_MULTIPART_FORMDATA); } - @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 { diff --git a/src/main/java/caosdb/server/converter/xml/EntityXMLConverterHelper.java b/src/main/java/caosdb/server/converter/xml/EntityXMLConverterHelper.java index 5baaea4cc1ce780962f516c44e8ba50529db0d94..69c316331415e2a6950a6c038b69739d4d04fe87 100644 --- a/src/main/java/caosdb/server/converter/xml/EntityXMLConverterHelper.java +++ b/src/main/java/caosdb/server/converter/xml/EntityXMLConverterHelper.java @@ -1,5 +1,12 @@ package caosdb.server.converter.xml; +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.container.TransactionContainer; +import caosdb.server.resource.JdomRepresentation; import java.io.IOException; import java.util.Collection; import org.apache.shiro.subject.Subject; @@ -14,15 +21,6 @@ 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 AbstractContainerHelper { @@ -39,9 +37,9 @@ public class EntityXMLConverterHelper extends AbstractContainerHelper { @Override public <T> T toObject(Representation source, Class<T> target, Resource resource) throws IOException { - Document xml; try { - xml = xmlParser.parse(source.getStream()); + Document xml = toDocument(source); + return (T) toContainer(xml, resource); } catch (JDOMException e) { throw new ResourceException( new Status(Status.CLIENT_ERROR_BAD_REQUEST, "Could not parse XML."), @@ -49,10 +47,13 @@ public class EntityXMLConverterHelper extends AbstractContainerHelper { resource.getRequest(), resource.getResponse()); } - return (T) createContainer(xml, resource); } - private Container<? extends EntityInterface> createContainer(Document xml, Resource resource) { + public Document toDocument(Representation source) throws JDOMException, IOException { + return xmlParser.parse(source.getStream()); + } + + public TransactionContainer toContainer(Document xml, Resource resource) { TransactionContainer result = createContainer(resource); for (Element e : xml.getRootElement().getChildren()) { result.add(new Entity(e)); @@ -70,9 +71,11 @@ public class EntityXMLConverterHelper extends AbstractContainerHelper { private Representation toJdomRepresentation(TransactionContainer container, Resource resource) { Document doc = toDocument(container, resource); - String xsl = resource.getResponseAttributes().get("xsl").toString(); - if (xsl != null) { - addStyleSheet(doc, xsl); + if (resource != null) { + Object xsl = resource.getResponseAttributes().get("xsl"); + if (xsl != null) { + addStyleSheet(doc, xsl.toString()); + } } return new JdomRepresentation(doc, " "); @@ -98,13 +101,19 @@ public class EntityXMLConverterHelper extends AbstractContainerHelper { * <li>A timestamp * <li>The URI to this resource. */ - protected Document toDocument(TransactionContainer container, Resource resource) { + public Document toDocument(TransactionContainer container, Resource resource) { final Element root = new Element("Response"); addUserInfo(root, container.getOwner()); - root.setAttribute("srid", container.getRequestId()); - root.setAttribute("timestamp", container.getTimestamp().toString()); - root.setAttribute("baseuri", resource.getRootRef().toString()); + if (container.getRequestId() != null) { + root.setAttribute("srid", container.getRequestId()); + } + if (container.getTimestamp() != null) { + root.setAttribute("timestamp", container.getTimestamp().toString()); + } + if (resource != null) { + root.setAttribute("baseuri", resource.getRootRef().toString()); + } container.addToElement(root); @@ -162,50 +171,4 @@ public class EntityXMLConverterHelper extends AbstractContainerHelper { userInfo.setAttribute("username", ((Principal) user.getPrincipal()).getUsername()); userInfo.setAttribute("realm", ((Principal) user.getPrincipal()).getRealm()); } - - /* - ********************************************************************** - * 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 - * ******************************************************************** - */ - /** - * Indicates if the given variant is compatible with the media types supported by this converter. - * - * @param variant The variant. - * @return True if the given variant is compatible with the media types supported by this - * converter. - */ - protected boolean isCompatible(Variant variant) { - return (variant != null) - && (VARIANT_TEXT_XML.isCompatible(variant) - || VARIANT_APPLICATION_XML.isCompatible(variant)); - } - - /* - ********************************************************************** - * 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 float score(Object source, Variant target, Resource resource) { - float result = -1.0F; - - if (source instanceof TransactionContainer && isCompatible(target)) { - result = 1.0F; - } - - return result; - } } diff --git a/src/main/java/caosdb/server/entity/Message.java b/src/main/java/caosdb/server/entity/Message.java index b57d6166df3df7a8913605a0af105907bd7be3f6..63b3ae4ad3d20bd5eb87e183e52232af77004389 100644 --- a/src/main/java/caosdb/server/entity/Message.java +++ b/src/main/java/caosdb/server/entity/Message.java @@ -22,9 +22,9 @@ */ package caosdb.server.entity; +import caosdb.server.entity.xml.ToElementable; import org.jdom2.Element; import org.restlet.data.Status; -import caosdb.server.entity.xml.ToElementable; public class Message extends Exception implements Comparable<Message>, ToElementable { @@ -40,9 +40,13 @@ public class Message extends Exception implements Comparable<Message>, ToElement Error, Info }; - + public Message(Status status) { - this(status.isError()? "Error" : "Info", status.getCode(), status.getReasonPhrase(), status.getDescription()); + this( + status.isError() ? "Error" : "Info", + status.getCode(), + status.getReasonPhrase(), + status.getDescription()); } @Override diff --git a/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java b/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java index 339e6ac01283fbad53a8ba4f9fe6004fa7f75b29..aac90f5a28cac89fe0ec4fe3b26fef33a7fb4f63 100644 --- a/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java +++ b/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java @@ -23,6 +23,7 @@ */ package caosdb.server.resource; +import caosdb.server.utils.WebinterfaceUtils; import java.io.IOException; import java.util.List; import java.util.logging.Level; @@ -34,7 +35,6 @@ import org.restlet.engine.application.StatusInfo; import org.restlet.representation.Representation; import org.restlet.representation.Variant; import org.restlet.resource.ServerResource; -import caosdb.server.utils.WebinterfaceUtils; /** * Base class for all CaosDB Server Resources. @@ -43,6 +43,10 @@ import caosdb.server.utils.WebinterfaceUtils; */ public abstract class AbstractCaosDBServerResource extends ServerResource { + public AbstractCaosDBServerResource() { + this.getConnegService().setStrict(true); + } + private WebinterfaceUtils utils; /** Return the {@link WebinterfaceUtils} instance for this resource. */ @@ -93,38 +97,37 @@ public abstract class AbstractCaosDBServerResource extends ServerResource { public final String getSRID() { return getRequest().getAttributes().get("SRID").toString(); } - + /* * Stolen from Restlet and adapted to our needs. */ @Override protected void doCatch(Throwable throwable) { - Level level = Level.INFO; - Status status = getStatusService().toStatus(throwable, this); - - if (status.isServerError()) { - level = Level.SEVERE; - } else if (status.isConnectorError()) { - level = Level.INFO; - } else if (status.isClientError()) { - level = Level.FINE; - } - - getLogger().log(level, "Exception or error caught in server resource", - throwable); - - if (getResponse() != null) { - getResponse().setStatus(status); - - List<Variant> variants = getVariants(getMethod()); - Variant preferredVariant = getPreferredVariant(variants); - try { - Representation errorEntity; - errorEntity = toRepresentation(new StatusInfo(status), preferredVariant); - getResponse().setEntity(errorEntity); - } catch (IOException e) { - getLogger().log(Level.SEVERE, "Exception during serialization of another error.", e); - } - } + Level level = Level.INFO; + Status status = getStatusService().toStatus(throwable, this); + + if (status.isServerError()) { + level = Level.SEVERE; + } else if (status.isConnectorError()) { + level = Level.INFO; + } else if (status.isClientError()) { + level = Level.FINE; + } + + getLogger().log(level, "Exception or error caught in server resource", throwable); + + if (getResponse() != null) { + getResponse().setStatus(status); + + List<Variant> variants = getVariants(getMethod()); + Variant preferredVariant = getPreferredVariant(variants); + try { + Representation errorEntity; + errorEntity = toRepresentation(new StatusInfo(status), preferredVariant); + getResponse().setEntity(errorEntity); + } catch (IOException e) { + getLogger().log(Level.SEVERE, "Exception during serialization of another error.", e); + } + } } } diff --git a/src/main/java/caosdb/server/resource/FileSystemResource.java b/src/main/java/caosdb/server/resource/FileSystemResource.java index c066e1a70aace980417fa89780cc5adaa7177c3a..cc8d8df75d96ea4b53ce26a5b1a2ec859d543d6d 100644 --- a/src/main/java/caosdb/server/resource/FileSystemResource.java +++ b/src/main/java/caosdb/server/resource/FileSystemResource.java @@ -24,17 +24,7 @@ package caosdb.server.resource; import static caosdb.server.FileSystem.getFromFileSystem; import static java.net.URLDecoder.decode; -import java.io.File; -import java.io.IOException; -import org.jdom2.Attribute; -import org.jdom2.Document; -import org.jdom2.Element; -import org.jdom2.JDOMException; -import org.restlet.data.Disposition; -import org.restlet.data.MediaType; -import org.restlet.data.Status; -import org.restlet.representation.FileRepresentation; -import org.restlet.representation.Representation; + import caosdb.server.database.backend.implementation.MySQL.ConnectionException; import caosdb.server.database.exceptions.EntityDoesNotExistException; import caosdb.server.database.misc.TransactionBenchmark; @@ -49,6 +39,17 @@ import caosdb.server.transaction.RetrieveSparseEntityByPath; import caosdb.server.transaction.Transaction; import caosdb.server.utils.FileUtils; import caosdb.server.utils.ServerMessages; +import java.io.File; +import java.io.IOException; +import org.jdom2.Attribute; +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.JDOMException; +import org.restlet.data.Disposition; +import org.restlet.data.MediaType; +import org.restlet.data.Status; +import org.restlet.representation.FileRepresentation; +import org.restlet.representation.Representation; /** * Download files via GET method from the file system directly without making the detour through the @@ -221,5 +222,4 @@ public class FileSystemResource extends XMLServerResource { this.setStatus(org.restlet.data.Status.CLIENT_ERROR_METHOD_NOT_ALLOWED); return null; } - } diff --git a/src/main/java/caosdb/server/resource/JdomRepresentation.java b/src/main/java/caosdb/server/resource/JdomRepresentation.java index 1eef69e6b8d5206763026f7201543baacb885d13..29210904645dc3f2e2c0d1630c87e312b670d0d0 100644 --- a/src/main/java/caosdb/server/resource/JdomRepresentation.java +++ b/src/main/java/caosdb/server/resource/JdomRepresentation.java @@ -23,7 +23,6 @@ package caosdb.server.resource; import java.io.IOException; -import java.io.OutputStream; import java.io.Writer; import org.jdom2.Document; import org.jdom2.output.Format; @@ -78,17 +77,4 @@ public class JdomRepresentation extends WriterRepresentation { outputter.output(this.document, writer); } } - - @Override - public void write(final OutputStream out) throws IOException { - if (this.document != null && this.document.hasRootElement()) { - final XMLOutputter outputter = new XMLOutputter(); - final Format newFormat = Format.getPrettyFormat(); - if (this.indent != null) { - newFormat.setIndent(this.indent); - } - outputter.setFormat(newFormat); - outputter.output(this.document, out); - } - } } diff --git a/src/main/java/caosdb/server/resource/XMLServerResource.java b/src/main/java/caosdb/server/resource/XMLServerResource.java index 70b69b8d20bf7def01849372454858c6b18cda22..66ed8c5ba5cf61b3e44d5de6d29252507f9c43d2 100644 --- a/src/main/java/caosdb/server/resource/XMLServerResource.java +++ b/src/main/java/caosdb/server/resource/XMLServerResource.java @@ -19,6 +19,14 @@ */ package caosdb.server.resource; +import caosdb.server.CaosDBException; +import caosdb.server.accessControl.AuthenticationUtils; +import caosdb.server.accessControl.Principal; +import caosdb.server.accessControl.UserSources; +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 java.io.IOException; import java.io.InputStream; import java.security.NoSuchAlgorithmException; @@ -39,14 +47,6 @@ import org.restlet.resource.Delete; import org.restlet.resource.Get; import org.restlet.resource.Post; import org.restlet.resource.Put; -import caosdb.server.CaosDBException; -import caosdb.server.accessControl.AuthenticationUtils; -import caosdb.server.accessControl.Principal; -import caosdb.server.accessControl.UserSources; -import caosdb.server.converter.xml.XMLParser; -import caosdb.server.database.backend.implementation.MySQL.ConnectionException; -import caosdb.server.entity.Message; -import caosdb.server.utils.ServerMessages; /** * This is a temporary bridge class. It contains all code which is necessary for any resources that @@ -326,14 +326,13 @@ public abstract class XMLServerResource extends AbstractCaosDBServerResource { } return root; } - + public Representation toJdomRepresentation(Document doc) { String xsl = getXSLScript(); - if(xsl!=null) { - addStyleSheet(doc, xsl); + if (xsl != null) { + addStyleSheet(doc, xsl); } return new JdomRepresentation(doc, " "); - } /** adds the xslt processing instruction to the document. */ @@ -342,6 +341,4 @@ public abstract class XMLServerResource extends AbstractCaosDBServerResource { new ProcessingInstruction("xml-stylesheet", "type=\"text/xsl\" href=\"" + xslPath + "\" "); document.getContent().add(0, pi); } - - } diff --git a/src/main/java/caosdb/server/resource/transaction/AbstractEntityResource.java b/src/main/java/caosdb/server/resource/transaction/AbstractEntityResource.java index a1f072814b9b882b170adc345fccb3590914fc47..e5ca0e8b05711ef3229eb7ac70146ea016ee1748 100644 --- a/src/main/java/caosdb/server/resource/transaction/AbstractEntityResource.java +++ b/src/main/java/caosdb/server/resource/transaction/AbstractEntityResource.java @@ -40,7 +40,7 @@ public abstract class AbstractEntityResource extends AbstractCaosDBServerResourc } @Get - public final TransactionContainer httpGetInChildClass() + public final TransactionContainer retrieve() throws ConnectionException, IOException, SQLException, CaosDBException, NoSuchAlgorithmException, Exception { diff --git a/src/test/java/caosdb/server/converter/TestJsonXmlConversion.java b/src/test/java/caosdb/server/converter/TestJsonXmlConversion.java new file mode 100644 index 0000000000000000000000000000000000000000..9a06dd87b3e84bbe0cae3aeb7db6711485468de0 --- /dev/null +++ b/src/test/java/caosdb/server/converter/TestJsonXmlConversion.java @@ -0,0 +1,87 @@ +package caosdb.server.converter; + +import static org.junit.Assert.assertEquals; + +import caosdb.server.converter.misc.EntityJsonConverterHelper; +import java.io.IOException; +import java.io.StringReader; +import javax.xml.stream.XMLStreamException; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.JDOMException; +import org.jdom2.input.SAXBuilder; +import org.junit.Test; + +public class TestJsonXmlConversion { + + @Test + public void testSimple() throws IOException, JDOMException, JSONException, XMLStreamException { + EntityJsonConverterHelper c = new EntityJsonConverterHelper(); + Element root = new Element("Root"); + Document doc = new Document(root); + org.codehaus.jettison.json.JSONObject json = c.toJson(doc); + assertEquals("{\"Root\":{}}", json.toString()); + + root = c.toXML(json).getRootElement(); + assertEquals("Root", root.getName()); + } + + @Test + public void testAttribute() throws IOException, JDOMException, JSONException, XMLStreamException { + EntityJsonConverterHelper c = new EntityJsonConverterHelper(); + Element root = new Element("Root"); + root.setAttribute("attr", "val"); + assertEquals("val", root.getAttributeValue("attr")); + + Document doc = new Document(root); + JSONObject json = c.toJson(doc); + String attr = json.getJSONObject("Root").getString("@attr"); + assertEquals("val", attr); + + root = c.toXML(json).getRootElement(); + assertEquals("Root", root.getName()); + + assertEquals("val", root.getAttributeValue("attr")); + } + + @Test + public void testList() throws IOException, JDOMException, JSONException, XMLStreamException { + EntityJsonConverterHelper c = new EntityJsonConverterHelper(); + Element root = new Element("Root"); + for (int i = 0; i < 3; i++) { + Element child = new Element("Child"); + child.setAttribute("id", Integer.toString(i)); + root.addContent(child); + } + assertEquals( + "[[Element: <Child/>], [Element: <Child/>], [Element: <Child/>]]", + root.getChildren().toString()); + + Document doc = new Document(root); + JSONObject json = c.toJson(doc); + JSONArray child = json.getJSONObject("Root").getJSONArray("Child"); + assertEquals("[{\"@id\":\"0\"},{\"@id\":\"1\"},{\"@id\":\"2\"}]", child.toString()); + + root = c.toXML(json).getRootElement(); + assertEquals("Root", root.getName()); + + assertEquals( + "[[Element: <Child/>], [Element: <Child/>], [Element: <Child/>]]", + root.getChildren().toString()); + } + + @Test + public void testJettison() throws JDOMException, IOException, JSONException, XMLStreamException { + String xml = "<A><B c=\"d\"/><B c=\"e\"/></A>"; + + SAXBuilder b = new SAXBuilder(); + StringReader r = new StringReader(xml); + Document doc = b.build(r); + + EntityJsonConverterHelper c = new EntityJsonConverterHelper(); + assertEquals("{\"A\":{\"B\":[{\"@c\":\"d\"},{\"@c\":\"e\"}]}}", c.toJsonString(doc)); + } +} diff --git a/src/test/java/caosdb/server/resource/TestScriptingResource.java b/src/test/java/caosdb/server/resource/TestScriptingResource.java index 2edfb82b53b56324996293a469fadf807264d86c..6a979c926e7179ae7ab13b9f81f3dd49ec9949f8 100644 --- a/src/test/java/caosdb/server/resource/TestScriptingResource.java +++ b/src/test/java/caosdb/server/resource/TestScriptingResource.java @@ -194,6 +194,7 @@ public class TestScriptingResource { entity.setMediaType(MediaType.TEXT_ALL); Request request = new Request(Method.POST, "../test", entity); request.getAttributes().put("SRID", "asdf1234"); + request.getClientInfo().accept(MediaType.ALL); request.setDate(new Date()); resource.init(null, request, new Response(null)); resource.handle(); @@ -208,6 +209,7 @@ public class TestScriptingResource { Representation entity = new StringRepresentation("asdf"); entity.setMediaType(MediaType.TEXT_ALL); Request request = new Request(Method.POST, "../test", entity); + request.getClientInfo().accept(MediaType.ALL); request.setRootRef(new Reference("bla")); request.getAttributes().put("SRID", "asdf1234"); request.setDate(new Date());