diff --git a/src/main/java/caosdb/server/CaosDBServer.java b/src/main/java/caosdb/server/CaosDBServer.java index 2586c2df7a388061a0986a4ff3a40f94b8657f1b..c68ae31c1fbfe8487bce082e545222ec9647b188 100644 --- a/src/main/java/caosdb/server/CaosDBServer.java +++ b/src/main/java/caosdb/server/CaosDBServer.java @@ -49,12 +49,11 @@ import caosdb.server.resource.ScriptingResource; import caosdb.server.resource.ServerLogsResource; import caosdb.server.resource.ServerPropertiesResource; import caosdb.server.resource.SharedFileResource; -import caosdb.server.resource.TestCaseFileSystemResource; -import caosdb.server.resource.TestCaseResource; import caosdb.server.resource.ThumbnailsResource; import caosdb.server.resource.UserResource; import caosdb.server.resource.UserRolesResource; import caosdb.server.resource.Webinterface; +import caosdb.server.resource.WebinterfaceBuildNumber; import caosdb.server.resource.transaction.EntityResource; import caosdb.server.terminal.CaosDBTerminal; import caosdb.server.terminal.StatsPanel; @@ -581,39 +580,8 @@ public class CaosDBServer extends Application { } }; - // -- Section only for debug mode -- - if (isDebugMode()) { - baseRouter.attach("/TestCase/", DefaultResource.class); - - final Variable pathVariable = - baseRouter - .attach( - "/TestCase/FileSystem/{path}", - baseRouter.createFinder(TestCaseFileSystemResource.class)) - .getTemplate() - .getDefaultVariable(); - pathVariable.setRequired(false); - pathVariable.setType(Variable.TYPE_URI_PATH); - pathVariable.setDefaultValue(""); - - baseRouter - .attach("/TestCase/Thumbnails/{path}", ThumbnailsResource.class) - .getTemplate() - .getDefaultVariable() - .setType(Variable.TYPE_URI_PATH); - - baseRouter - .attach("/TestCase/webinterface/{path}", Webinterface.class) - .getTemplate() - .getDefaultVariable() - .setType(Variable.TYPE_URI_PATH); - baseRouter.attach("/TestCase/Entity", TestCaseResource.class); - baseRouter.attach("/TestCase/Entity/", TestCaseResource.class); - baseRouter.attach("/TestCase/Entity/{specifier}", TestCaseResource.class); - } - // -- End of debug section -- - // These routes can be used without logging in: + baseRouter.attach("/webinterface/version/build", WebinterfaceBuildNumber.class); baseRouter .attach("/webinterface/{path}", Webinterface.class) .getTemplate() diff --git a/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java b/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java index 948b4eab2fda1c906f4acf2802c0d83184b875bc..ea4e65f0a60d72cb5da6cb03b2cec44848dbc3c6 100644 --- a/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java +++ b/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java @@ -33,6 +33,7 @@ import caosdb.server.accessControl.UserSources; import caosdb.server.database.backend.implementation.MySQL.ConnectionException; import caosdb.server.entity.Message; import caosdb.server.utils.ServerMessages; +import caosdb.server.utils.WebinterfaceUtils; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; @@ -55,7 +56,6 @@ import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; import org.restlet.data.Form; import org.restlet.data.Header; -import org.restlet.data.MediaType; import org.restlet.data.Parameter; import org.restlet.data.Status; import org.restlet.representation.Representation; @@ -81,7 +81,12 @@ public abstract class AbstractCaosDBServerResource extends ServerResource { private String[] requestedItems = null; private ArrayList<Integer> requestedIDs = new ArrayList<Integer>(); private ArrayList<String> requestedNames = new ArrayList<String>(); - private String xslScript = "webcaosdb.xsl"; + private WebinterfaceUtils utils; + + /** Return the {@link WebinterfaceUtils} instance for this resource. */ + public WebinterfaceUtils getUtils() { + return this.utils; + } public static class xmlNotWellFormedException extends Exception { private static final long serialVersionUID = -6836378704013776849L; @@ -116,6 +121,8 @@ public abstract class AbstractCaosDBServerResource extends ServerResource { getRequest().setEntity(r); } + this.utils = WebinterfaceUtils.getInstance(getHostRef()); + this.timestamp = getRequest().getDate().getTime(); this.sRID = getRequest().getAttributes().get("SRID").toString(); @@ -325,11 +332,7 @@ public abstract class AbstractCaosDBServerResource extends ServerResource { } protected String getXSLScript() { - return this.xslScript; - } - - protected void setXSLScript(final String s) { - this.xslScript = s; + return this.utils.getWebinterfaceURI("webcaosdb.xsl"); } /** Wrap an element for an "OK" response. */ @@ -337,18 +340,28 @@ public abstract class AbstractCaosDBServerResource extends ServerResource { return ok(new Document(root)); } + /** + * Return a JDomRepresentation of the document and leave the {@link Response}'s {@link Status} + * where it is - which is usually 200 - OK when this method happens to be called. + */ protected JdomRepresentation ok(final Document doc) { - return new JdomRepresentation(doc, MediaType.TEXT_XML, " ", getReference(), getXSLScript()); + return new JdomRepresentation(doc, " ", getXSLScript()); } + /** + * 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 + * @return A Representation of the error. + */ protected Representation error(final Message m, final Status status) { final Document doc = new Document(); final Element root = generateRootElement(); root.addContent(m.toElement().setName("Error")); doc.setRootElement(root); - return error( - new JdomRepresentation(doc, MediaType.TEXT_XML, " ", getReference(), getXSLScript()), - status); + return error(new JdomRepresentation(doc, " ", getXSLScript()), status); } protected Representation error(Representation entity, Status status) { @@ -364,12 +377,19 @@ public abstract class AbstractCaosDBServerResource extends ServerResource { return error((Representation) null, status); } + /** + * 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. + */ protected JdomRepresentation warning(final Message m) { final Document doc = new Document(); final Element root = generateRootElement(); root.addContent(m.toElement().setName("Warning")); doc.setRootElement(root); - return new JdomRepresentation(doc, MediaType.TEXT_XML, " ", getReference(), getXSLScript()); + return new JdomRepresentation(doc, " ", getXSLScript()); } protected Representation noWellFormedNess() { diff --git a/src/main/java/caosdb/server/resource/JdomRepresentation.java b/src/main/java/caosdb/server/resource/JdomRepresentation.java index 2443b95c20b3f659d6a2f9e88c0dd9fabb563088..04fbdac3fdd13f9e5c4f025cb2364386deac71f0 100644 --- a/src/main/java/caosdb/server/resource/JdomRepresentation.java +++ b/src/main/java/caosdb/server/resource/JdomRepresentation.java @@ -56,30 +56,21 @@ public class JdomRepresentation extends WriterRepresentation { private final Document document; private final String indent; - private final Reference reference; - private final String xslPath; /** * Constructor. * - * @param mediaType This should be TEXT_XML, but we'll leave it open to use others. * @param document A JDOM Document parsed from elsewhere. - * @param indent To make that representation better to read by a human. - * @param reference + * @param indent Usually a number of whitespaces for better human readbility. * @param xslPath A String containing a meaningful path to a xslt file. */ - public JdomRepresentation( - final Document document, - final MediaType mediaType, - final String indent, - final Reference reference, - final String xslPath) { - super(mediaType); - this.xslPath = xslPath; - this.reference = reference; + public JdomRepresentation(final Document document, final String indent, final String xslPath) { + super(MediaType.TEXT_XML); this.indent = indent; this.document = document; - addStyleSheet(); + if (xslPath != null && document != null) { + addStyleSheet(document, xslPath); + } } public static final String getWebUIRef(final Reference reference) { @@ -89,14 +80,10 @@ public class JdomRepresentation extends WriterRepresentation { } /** adds the xslt processing instruction to the document. */ - protected final void addStyleSheet() { - if (this.document != null) { - final ProcessingInstruction pi = - new ProcessingInstruction( - "xml-stylesheet", - "type=\"text/xsl\" href=\"" + getWebUIRef(this.reference) + this.xslPath + "\" "); - this.document.getContent().add(0, pi); - } + protected final void addStyleSheet(Document document, String xslPath) { + final ProcessingInstruction pi = + new ProcessingInstruction("xml-stylesheet", "type=\"text/xsl\" href=\"" + xslPath + "\" "); + document.getContent().add(0, pi); } @Override diff --git a/src/main/java/caosdb/server/resource/ScriptingResource.java b/src/main/java/caosdb/server/resource/ScriptingResource.java index 57ada4aa7b4ed2a588e7de6e50c85de1b7fb6670..b23a9593918ead75a6b38216838995e09ac67bc7 100644 --- a/src/main/java/caosdb/server/resource/ScriptingResource.java +++ b/src/main/java/caosdb/server/resource/ScriptingResource.java @@ -214,6 +214,7 @@ public class ScriptingResource extends AbstractCaosDBServerResource { public int callScript( List<String> commandLine, Integer timeoutMs, List<FileProperties> files, Object authToken) throws Message { + // TODO getUser().checkPermission("SCRIPTING:EXECUTE:" + commandLine.get(0)); caller = new ServerSideScriptingCaller( commandLine.toArray(new String[commandLine.size()]), timeoutMs, files, authToken); diff --git a/src/main/java/caosdb/server/resource/ServerPropertiesResource.java b/src/main/java/caosdb/server/resource/ServerPropertiesResource.java index 9b878e3338a9d0b0c74704acb412ac92ceb1f0c4..347919d9c7d0f604734790f2ea09b5e2bac54042 100644 --- a/src/main/java/caosdb/server/resource/ServerPropertiesResource.java +++ b/src/main/java/caosdb/server/resource/ServerPropertiesResource.java @@ -13,7 +13,11 @@ public class ServerPropertiesResource extends AbstractCaosDBServerResource { @Override protected void doInit() { super.doInit(); - setXSLScript("xsl/server_properties.xsl"); + } + + @Override + protected String getXSLScript() { + return getUtils().getWebinterfaceURI("xsl/server_properties.xsl"); } @Override diff --git a/src/main/java/caosdb/server/resource/TestCaseFileSystemResource.java b/src/main/java/caosdb/server/resource/TestCaseFileSystemResource.java deleted file mode 100644 index 903ef0d5aca9a91eaeaff3693b7f77ef51e6cc46..0000000000000000000000000000000000000000 --- a/src/main/java/caosdb/server/resource/TestCaseFileSystemResource.java +++ /dev/null @@ -1,73 +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; - -import caosdb.server.accessControl.Principal; -import caosdb.server.entity.FileProperties; -import caosdb.server.utils.FileUtils; -import java.io.File; -import org.jdom2.Element; - -public class TestCaseFileSystemResource extends FileSystemResource { - - @Override - protected void doInit() { - super.doInit(); - setXSLScript("webcaosdb.xsl"); - } - - private static final String BASEPATH = "./testfiles/"; - - @Override - protected File getFile(final String path) throws Exception { - final File f = new File(BASEPATH + path); - return (f != null && f.exists() ? f : null); - } - - @Override - protected String getEntityID(final String path) throws Exception { - return "123412341234"; - } - - @Override - protected Element generateRootElement() { - final Element retRoot = new Element("Response"); - - if (getUser() != null && getUser().isAuthenticated()) { - retRoot.setAttribute("username", ((Principal) getUser().getPrincipal()).getUsername()); - retRoot.setAttribute("realm", ((Principal) getUser().getPrincipal()).getRealm()); - } - retRoot.setAttribute("srid", getSRID()); - if (this.getCRID() != null) { - retRoot.setAttribute("crid", this.getCRID()); - } - retRoot.setAttribute("timestamp", getTimestamp().toString()); - retRoot.setAttribute("baseuri", getRootRef().toString() + "/TestCase/"); - return retRoot; - } - - public static FileProperties getFileProperties(final String path) { - final File f = new File(BASEPATH + path); - return new FileProperties(FileUtils.getChecksum(f), path, f.length()); - } -} diff --git a/src/main/java/caosdb/server/resource/TestCaseResource.java b/src/main/java/caosdb/server/resource/TestCaseResource.java deleted file mode 100644 index e8aef1f00e57335185b7b204c8de081570e6e188..0000000000000000000000000000000000000000 --- a/src/main/java/caosdb/server/resource/TestCaseResource.java +++ /dev/null @@ -1,481 +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; - -import caosdb.datetime.DateTimeFactory2; -import caosdb.datetime.UTCDateTime; -import caosdb.server.CaosDBException; -import caosdb.server.database.backend.implementation.MySQL.ConnectionException; -import caosdb.server.datatype.AbstractCollectionDatatype; -import caosdb.server.datatype.AbstractDatatype; -import caosdb.server.datatype.BooleanDatatype; -import caosdb.server.datatype.BooleanValue; -import caosdb.server.datatype.CollectionValue; -import caosdb.server.datatype.DateTimeDatatype; -import caosdb.server.datatype.DoubleDatatype; -import caosdb.server.datatype.GenericValue; -import caosdb.server.datatype.IntegerDatatype; -import caosdb.server.datatype.ListDatatype; -import caosdb.server.datatype.ReferenceDatatype2; -import caosdb.server.datatype.ReferenceValue; -import caosdb.server.datatype.TextDatatype; -import caosdb.server.datatype.Value; -import caosdb.server.entity.Entity; -import caosdb.server.entity.EntityInterface; -import caosdb.server.entity.MagicTypes; -import caosdb.server.entity.Message; -import caosdb.server.entity.Message.MessageType; -import caosdb.server.entity.RetrieveEntity; -import caosdb.server.entity.Role; -import caosdb.server.entity.StatementStatus; -import caosdb.server.entity.container.PropertyContainer; -import caosdb.server.entity.wrapper.Parent; -import caosdb.server.entity.wrapper.Property; -import caosdb.server.entity.xml.ToElementable; -import caosdb.server.query.Query; -import caosdb.server.query.Query.ParsingException; -import caosdb.server.utils.ServerMessages; -import caosdb.server.utils.TransactionLogMessage; -import java.io.IOException; -import java.security.NoSuchAlgorithmException; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.Collection; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import org.jdom2.Document; -import org.jdom2.Element; -import org.restlet.representation.Representation; - -public class TestCaseResource extends AbstractCaosDBServerResource { - - @Override - protected void doInit() { - super.doInit(); - setXSLScript("webcaosdb.xsl"); - } - - @Override - protected Element generateRootElement() { - final Element retRoot = new Element("Response"); - - retRoot.setAttribute("username", "TestUser"); - retRoot.setAttribute("realm", "PAM"); - retRoot.setAttribute("srid", getSRID()); - if (this.getCRID() != null) { - retRoot.setAttribute("crid", this.getCRID()); - } - retRoot.setAttribute("timestamp", getTimestamp().toString()); - retRoot.setAttribute("baseuri", getRootRef().toString() + "/TestCase/"); - return retRoot; - } - - @Override - protected synchronized Representation httpGetInChildClass() - throws ConnectionException, IOException, SQLException, CaosDBException, - NoSuchAlgorithmException, Exception { - - final Element rootElem = generateRootElement(); - final Document doc = new Document(); - - final Collection<ToElementable> selectedTestCases = getSelectedTestCase(); - rootElem.setAttribute("count", Integer.toString(selectedTestCases.size())); - - int from = 0; - int len = Integer.MAX_VALUE; - if (getFlags().containsKey("query")) { - final String queryStr = getFlags().get("query"); - if (queryStr != null && !queryStr.isEmpty()) { - final Query query = new Query(queryStr); - try { - query.parse(); - query.addToElement(rootElem); - } catch (final ParsingException e) { - query.addToElement(rootElem); - rootElem.addContent(ServerMessages.QUERY_PARSING_ERROR.toElement()); - doc.setRootElement(rootElem); - return ok(doc); - } - } - } - if (getFlags().containsKey("P")) { - final String[] split = getFlags().get("P").split("L"); - from = Integer.valueOf(split[0]); - len = Integer.valueOf(split[1]); - } - int i = 0; - for (final ToElementable e : selectedTestCases) { - if (i++ >= from && i <= from + len) { - e.addToElement(rootElem); - } - } - // testEntities = null; - // entityCounter = 1; - - doc.setRootElement(rootElem); - return ok(doc); - } - - private Collection<ToElementable> getSelectedTestCase() { - final HashMap<String, ToElementable> testCases = getTestCase(); - if (getFlags().containsKey("query")) { - final String queryStr = getFlags().get("query"); - if (queryStr.startsWith("FIND Annotation WHICH REFERENCES")) { - final LinkedList<ToElementable> ret = new LinkedList<ToElementable>(); - for (final ToElementable e : testCases.values()) { - if (e instanceof Entity - && ((Entity) e).hasParents() - && ((Entity) e).getParents().get(0).getName().equals("Annotation")) { - ret.add(e); - } - } - return ret; - } - } - if (getFlags().containsKey("all")) { - final LinkedList<ToElementable> ret = new LinkedList<ToElementable>(); - for (final ToElementable e : testCases.values()) { - if (e instanceof Entity) { - if (getFlags().get("all").equalsIgnoreCase("Entity")) { - ret.add(e); - } else { - final Entity entity = (Entity) e; - if (entity.getRole().toString().equalsIgnoreCase(getFlags().get("all"))) { - ret.add(e); - } - } - } - } - return ret; - } - if (!getRequestedIDs().isEmpty() || !getRequestedNames().isEmpty()) { - final LinkedList<ToElementable> ret = new LinkedList<ToElementable>(); - for (final Integer id : getRequestedIDs()) { - for (final ToElementable e : testCases.values()) { - if (e instanceof Entity) { - if (((Entity) e).getId().equals(id)) { - ret.add(e); - } - } - } - } - for (final String name : getRequestedNames()) { - for (final ToElementable e : testCases.values()) { - if (e instanceof Entity) { - if (((Entity) e).getName().equals(name)) { - ret.add(e); - } - } - } - } - return ret; - } - return testCases.values(); - } - - private HashMap<String, ToElementable> getTestCase() { - if (testEntities == null) { - testEntities = new HashMap<String, ToElementable>(); - - final Entity lp1 = - createProperty( - "LIST" - + AbstractCollectionDatatype.LEFT_DELIMITER - + "TEXT" - + AbstractCollectionDatatype.RIGHT_DELIMITER); - final Entity lp2 = - createProperty( - "LIST" - + AbstractCollectionDatatype.LEFT_DELIMITER - + "INTEGER" - + AbstractCollectionDatatype.RIGHT_DELIMITER, - "meter"); - final Entity lp4 = - createProperty( - "LIST" - + AbstractCollectionDatatype.LEFT_DELIMITER - + "BOOLEAN" - + AbstractCollectionDatatype.RIGHT_DELIMITER); - final Entity tp1 = createProperty("TEXT"); - final Entity dp1 = createProperty("DOUBLE", "meter"); - final Entity dtp1 = createProperty("DATETIME"); - final Entity tp2 = createProperty("TEXT"); - final Entity ip1 = createProperty("INTEGER", "meter"); - final Entity bp1 = createProperty("BOOLEAN"); - final Entity fp1 = createProperty("FILE"); - - final Entity rt1 = createRecordType(new Entity[] {}, new Entity[] {}); - final Entity rt2 = createRecordType(new Entity[] {}, new Entity[] {tp2, ip1, bp1}); - - final Entity rp1 = createProperty(rt2); - final Entity lp3 = - createProperty( - "LIST" - + AbstractCollectionDatatype.LEFT_DELIMITER - + rt2.getName() - + AbstractCollectionDatatype.RIGHT_DELIMITER); - final Entity rt3 = - createRecordType( - new Entity[] {rt1}, new Entity[] {lp1, tp1, dp1, dtp1, rp1, lp2, lp3, lp4}); - - createRecordFromRecordType(rt2); - createRecordFromRecordType(rt3); - - createFileRecord("lorem_ipsum.txt"); - createFileRecord("testsubfolder/lorem_ipsum.txt"); - final Entity pngFile = createFileRecord("testimg.png"); - createFileRecord("testimg.jpg"); - createFileRecord("testimg.svg"); - createFileRecord("testimg.gif"); - - createRecordWithPngFile(pngFile, fp1, rt1); - - /* Test Error, Warning, Info */ - createError(); - createWarning(); - createInfo(); - - /* Entities with Error, Warning, Info */ - createRecordFromRecordType(rt2) - .addError( - new Message( - MessageType.Error, - 666, - "Description of this error", - "Further information about this error.")); - createRecordFromRecordType(rt2) - .addWarning( - new Message( - MessageType.Warning, - 346, - "Description of this warning", - "Further information about this warning.")); - createRecordFromRecordType(rt2) - .addInfo( - new Message( - MessageType.Info, - 0, - "Description of this info", - "Further information about this info.")); - - createAnnotation(); - } - return testEntities; - } - - private void createAnnotation() { - final Entity annotationOf = createEntity(Role.Property, "annotationOf"); - annotationOf.setDatatype("REFERENCE"); - final Entity comment = createEntity(Role.Property, "comment"); - comment.setDatatype("TEXT"); - final Entity annotation = createEntity(Role.RecordType, "Annotation"); - annotation.addProperty(new Property(annotationOf)); - annotation.addProperty(new Property(comment)); - - final Entity rec = createRecordFromRecordType(annotation); - rec.addTransactionLog( - new TransactionLogMessage( - "INSERT", - rec, - "Adam", - UTCDateTime.SystemMillisToUTCDateTime(System.currentTimeMillis()))); - } - - private Entity createRecordWithPngFile( - final Entity pngFile, final Entity property, final Entity parent) { - final Entity entity = createRecordFromRecordType(parent); - final Property newP = new Property(property.toElement()); - newP.setValue(new ReferenceValue(pngFile)); - entity.addProperty(newP); - return entity; - } - - private Entity createFileRecord(final String path) { - final Entity entity = createEntity(Role.File, "TestFile"); - entity.setFileProperties(TestCaseFileSystemResource.getFileProperties(path)); - return entity; - } - - private Entity createProperty(final Entity rt2) { - final Entity entity = createProperty("REFERENCE"); - entity.setDatatype(rt2.getName()); - return entity; - } - - private Value generateValue(final AbstractDatatype dt) { - if (dt instanceof IntegerDatatype) { - return new GenericValue(1337); - } else if (dt instanceof DoubleDatatype) { - return new GenericValue(3.14); - } else if (dt instanceof DateTimeDatatype) { - return DateTimeFactory2.valueOf(new GregorianCalendar()); - } else if (dt instanceof BooleanDatatype) { - return BooleanValue.valueOf(entityCounter % 2 == 0); - } else if (dt instanceof TextDatatype) { - return new GenericValue("Don't panic."); - } else if (dt instanceof ReferenceDatatype2) { - final ReferenceDatatype2 dt2 = (ReferenceDatatype2) dt; - dt2.getId(); - for (final ToElementable e : testEntities.values()) { - if (e instanceof Entity && ((Entity) e).getRole() == Role.Record) { - return new ReferenceValue((Entity) e); - } - } - } else if (dt instanceof ListDatatype) { - final AbstractDatatype dt2 = ((ListDatatype) dt).getDatatype(); - final CollectionValue v = new CollectionValue(); - for (int i = 0; i < 25; i++) { - v.add(generateValue(dt2)); - } - return v; - } - return null; - } - - private Entity createRecordFromRecordType(final Entity rt2) { - final Entity entity = createEntity(Role.Record, "TestRecord"); - addParentsAndProperties(entity, rt2, rt2.getProperties(), "FIX"); - for (final Property p : entity.getProperties()) { - p.setValue(generateValue(p.getDatatype())); - } - return entity; - } - - private void addParentsAndProperties( - final Entity entity, - final Entity parent, - final PropertyContainer properties, - final String importance) { - final List<Entity> par = new LinkedList<Entity>(); - par.add(parent); - addParentsAndProperties(entity, par, properties, importance); - } - - private void addParentsAndProperties( - final Entity entity, - final Collection<? extends EntityInterface> parents, - final Collection<? extends EntityInterface> properties, - final String importance) { - for (final EntityInterface p : properties) { - final Property newP = new Property(p.toElement()); - if (importance != null) { - newP.setStatementStatus(StatementStatus.valueOf(importance)); - } - entity.addProperty(newP); - } - for (final EntityInterface p : parents) { - entity.addParent(new Parent(p.toElement())); - } - } - - private Message createError() { - return createMessage( - MessageType.Error.toString(), - "This is a description of the error", - "Here is additional info about the error.", - 666); - } - - private Message createWarning() { - return createMessage( - MessageType.Warning.toString(), - "This is a description of the warning", - "Here is additional info about the warning.", - 333); - } - - private Message createInfo() { - return createMessage( - MessageType.Info.toString(), - "Here is useful information about the last activity of the user.", - "Here is additional information.", - null); - } - - private Message createMessage( - String type, final String description, final String body, final Integer code) { - final Message m = new Message(type, code, description, body); - if (testEntities.containsKey(type)) { - int i = 0; - while (testEntities.containsKey(type + "-" + i)) { - i++; - } - type += "-" + i; - } - testEntities.put(type, m); - return m; - } - - private static HashMap<String, ToElementable> testEntities = null; - private static int entityCounter = 1; - - private Entity createProperty(final String datatype) { - return createProperty(datatype, null); - } - - private Entity createRecordType(final Entity[] parents, final Entity[] properties) { - final Entity entity = createEntity(Role.RecordType, "TestRecordType"); - addParentsAndProperties(entity, parents, properties, "OBLIGATORY"); - return entity; - } - - private void addParentsAndProperties( - final Entity entity, - final EntityInterface[] parents, - final EntityInterface[] properties, - final String importance) { - addParentsAndProperties(entity, Arrays.asList(parents), Arrays.asList(properties), importance); - } - - private Entity createProperty(final String datatype, final String unit) { - final Entity entity = createEntity(Role.Property, "Test" + datatype + "Property"); - entity.setDatatype(datatype); - if (unit != null) { - final EntityInterface magicUnit = MagicTypes.UNIT.getEntity(); - final Property unitProp = new Property(); - unitProp.setId(magicUnit.getId()); - unitProp.setValue(new GenericValue(unit)); - entity.addProperty(unitProp); - } - return entity; - } - - private Entity createEntity(final Role role, String name) { - final Entity entity = new RetrieveEntity(entityCounter++); - entity.setRole(role); - entity.setDescription( - "An informative description of the idea, meaning, and purpose of this entity."); - if (testEntities.containsKey(name)) { - int i = 0; - while (testEntities.containsKey(name + "-" + i)) { - i++; - } - name += "-" + i; - } - testEntities.put(name, entity); - entity.setName(name); - return entity; - } -} diff --git a/src/main/java/caosdb/server/resource/UserResource.java b/src/main/java/caosdb/server/resource/UserResource.java index 5cae0da2efa4716293407497fd896bf0b880f233..b77ff8a49035d2be930a3f957e743ed2f0dae067 100644 --- a/src/main/java/caosdb/server/resource/UserResource.java +++ b/src/main/java/caosdb/server/resource/UserResource.java @@ -42,7 +42,6 @@ import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.restlet.data.Form; -import org.restlet.data.MediaType; import org.restlet.data.Status; import org.restlet.representation.Representation; @@ -84,7 +83,7 @@ public class UserResource extends AbstractCaosDBServerResource { } doc.setRootElement(rootElem); - return new JdomRepresentation(doc, MediaType.TEXT_XML, " ", getReference(), getXSLScript()); + return ok(doc); } @Override @@ -125,7 +124,7 @@ public class UserResource extends AbstractCaosDBServerResource { rootElem.addContent(t.getUserElement()); doc.setRootElement(rootElem); - return new JdomRepresentation(doc, MediaType.TEXT_XML, " ", getReference(), getXSLScript()); + return ok(doc); } catch (final Message m) { if (m == ServerMessages.ACCOUNT_DOES_NOT_EXIST) { return error(m, Status.CLIENT_ERROR_NOT_FOUND); @@ -177,7 +176,7 @@ public class UserResource extends AbstractCaosDBServerResource { rootElem.addContent(t.getUserElement()); doc.setRootElement(rootElem); - return new JdomRepresentation(doc, MediaType.TEXT_XML, " ", getReference(), getXSLScript()); + return ok(doc); } @Override @@ -200,6 +199,6 @@ public class UserResource extends AbstractCaosDBServerResource { rootElem.addContent(t.getUserElement()); doc.setRootElement(rootElem); - return new JdomRepresentation(doc, MediaType.TEXT_XML, " ", getReference(), getXSLScript()); + return ok(doc); } } diff --git a/src/main/java/caosdb/server/resource/Webinterface.java b/src/main/java/caosdb/server/resource/Webinterface.java index 7343fc5ff681a56f1dcba633bd7f3de4ba27f813..f05ae4e6b9a98aba1c925677e0fc8e90a74e57e6 100644 --- a/src/main/java/caosdb/server/resource/Webinterface.java +++ b/src/main/java/caosdb/server/resource/Webinterface.java @@ -24,6 +24,7 @@ package caosdb.server.resource; import caosdb.server.CaosDBServer; import caosdb.server.ServerProperties; +import caosdb.server.utils.WebinterfaceUtils; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -42,13 +43,14 @@ import org.restlet.util.Series; public class Webinterface extends ServerResource { + private WebinterfaceUtils utils; + @Override protected void doInit() throws ResourceException { + this.utils = WebinterfaceUtils.getInstance(getHostRef()); super.doInit(); } - private static final File PUBLIC_DIRECTORY = new File("caosdb-webui/public/").getAbsoluteFile(); - @Get public Representation deliver() throws IOException { final String path = (String) getRequest().getAttributes().get("path"); @@ -57,23 +59,15 @@ public class Webinterface extends ServerResource { getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND); return null; } - final File file = new File(this.PUBLIC_DIRECTORY.getAbsolutePath() + "/" + path); - // TODO if (!FileUtils.isSubDirSymlinkSave(file, this.PUBLIC_DIRECTORY.getParentFile())) { - // getResponse().setStatus(Status.CLIENT_ERROR_FORBIDDEN); - // return null; - // } - if (!file.exists()) { + + final File file = utils.getPublicFile(path); + + if (file == null) { getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND); return null; } - Series<Header> headers = getRequest().getHeaders(); - if (headers == null) { - headers = new Series<Header>(Header.class); - getResponse().getAttributes().put(HeaderConstants.ATTRIBUTE_HEADERS, headers); - } - headers.set("Access-Control-Allow-Origin", getHostRef().toString()); - + // TODO move to FileUtils and use a third-party library final MediaType mt = path.endsWith(".json") ? MediaType.APPLICATION_JSON @@ -91,6 +85,13 @@ public class Webinterface extends ServerResource { final FileRepresentation ret = new FileRepresentation(file, mt); + Series<Header> headers = getRequest().getHeaders(); + if (headers == null) { + headers = new Series<Header>(Header.class); + getResponse().getAttributes().put(HeaderConstants.ATTRIBUTE_HEADERS, headers); + } + headers.set("Access-Control-Allow-Origin", getHostRef().toString()); + List<CacheDirective> cacheDirectives = new ArrayList<>(); cacheDirectives.add( new CacheDirective( diff --git a/src/main/java/caosdb/server/resource/WebinterfaceBuildNumber.java b/src/main/java/caosdb/server/resource/WebinterfaceBuildNumber.java new file mode 100644 index 0000000000000000000000000000000000000000..b61a61846f188d16ba7f13c61dd47d422e93e89f --- /dev/null +++ b/src/main/java/caosdb/server/resource/WebinterfaceBuildNumber.java @@ -0,0 +1,60 @@ +/** + * ** header v3.0 This file is a part of the CaosDB Project. + * + * <p>Copyright (c) 2019 IndiScale GmbH Copyright (c) 2019 Daniel Hornung <d.hornung@indiscale.com> + * + * <p>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. + * + * <p>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. + * + * <p>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/>. + * + * <p>** end header + */ +package caosdb.server.resource; + +import caosdb.server.utils.WebinterfaceUtils; +import org.restlet.data.Status; +import org.restlet.resource.Get; +import org.restlet.resource.ServerResource; + +/** + * This {@link ServerResource} exposes the current build number of the web interface. + * + * <p>It is mainly used for testing and debugging. A User can determine the current build number of + * the web interface. + * + * @author Timm Fitschen (t.fitschen@indiscale.com) + */ +public class WebinterfaceBuildNumber extends ServerResource { + + private WebinterfaceUtils utils; + + public WebinterfaceBuildNumber() { + this.utils = WebinterfaceUtils.getInstance(getHostRef()); + } + + /** + * Return the current build number of the web interface. + * + * <p>If the build number could not be determined the server responds with 404 - Not Found. + * Reasons for this include an out-dated web interface, the web interface has not been build yet + * or the web interface is not available at all. + * + * @return the current build number. + */ + @Get("text") + public String getBuildNumber() { + String buildNumber = utils.getBuildNumber(); + + if (buildNumber == null) { + setStatus(Status.CLIENT_ERROR_NOT_FOUND, "Build number could not be determined."); + } + return buildNumber; + } +} diff --git a/src/main/java/caosdb/server/resource/transaction/EntityResource.java b/src/main/java/caosdb/server/resource/transaction/EntityResource.java index f55c2b7ae0cb736305086ae131c3a3eeac1ba0ab..54882bcab6211bdbbd6921871ef4709413738543 100644 --- a/src/main/java/caosdb/server/resource/transaction/EntityResource.java +++ b/src/main/java/caosdb/server/resource/transaction/EntityResource.java @@ -29,7 +29,6 @@ import caosdb.server.entity.container.InsertContainer; import caosdb.server.entity.container.RetrieveContainer; import caosdb.server.entity.container.UpdateContainer; import caosdb.server.resource.AbstractCaosDBServerResource; -import caosdb.server.resource.JdomRepresentation; import caosdb.server.resource.transaction.handlers.FileUploadHandler; import caosdb.server.resource.transaction.handlers.IDHandler; import caosdb.server.resource.transaction.handlers.RequestHandler; @@ -120,7 +119,7 @@ public class EntityResource extends AbstractCaosDBServerResource { final Element rootElem = generateRootElement(); entityContainer.addToElement(rootElem); doc.setRootElement(rootElem); - return new JdomRepresentation(doc, MediaType.TEXT_XML, " ", getReference(), getXSLScript()); + return ok(doc); } @Override @@ -143,7 +142,7 @@ public class EntityResource extends AbstractCaosDBServerResource { entityContainer.addToElement(rootElem); doc.setRootElement(rootElem); - return new JdomRepresentation(doc, MediaType.TEXT_XML, " ", getReference(), getXSLScript()); + return ok(doc); } @Override @@ -167,7 +166,8 @@ public class EntityResource extends AbstractCaosDBServerResource { final Element rootElem = generateRootElement(); entityContainer.addToElement(rootElem); doc.setRootElement(rootElem); - return new JdomRepresentation(doc, MediaType.TEXT_XML, " ", getReference(), getXSLScript()); + + return ok(doc); } @Override @@ -191,6 +191,7 @@ public class EntityResource extends AbstractCaosDBServerResource { final Element rootElem = generateRootElement(); entityContainer.addToElement(rootElem); doc.setRootElement(rootElem); - return new JdomRepresentation(doc, MediaType.TEXT_XML, " ", getReference(), getXSLScript()); + + return ok(doc); } } diff --git a/src/main/java/caosdb/server/transaction/Transaction.java b/src/main/java/caosdb/server/transaction/Transaction.java index de1e5e279ee4b1cd252dda0fdf6bb23e8f93e57f..3e511257b239627c61064acc5d011d79516bbb08 100644 --- a/src/main/java/caosdb/server/transaction/Transaction.java +++ b/src/main/java/caosdb/server/transaction/Transaction.java @@ -191,7 +191,6 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra this.getClass().getSimpleName() + ".commit", System.currentTimeMillis() - t1); } catch (final Exception e) { - e.printStackTrace(); rollBack(); throw e; } finally { diff --git a/src/main/java/caosdb/server/utils/WebinterfaceUtils.java b/src/main/java/caosdb/server/utils/WebinterfaceUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..ecf0b08630e58662c0abad5c5fe71a0c5b1a8889 --- /dev/null +++ b/src/main/java/caosdb/server/utils/WebinterfaceUtils.java @@ -0,0 +1,293 @@ +/** + * ** header v3.0 This file is a part of the CaosDB Project. + * + * <p>Copyright (c) 2019 IndiScale GmbH Copyright (c) 2019 Daniel Hornung <d.hornung@indiscale.com> + * + * <p>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. + * + * <p>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. + * + * <p>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/>. + * + * <p>** end header + */ +package caosdb.server.utils; + +import caosdb.server.CaosDBServer; +import caosdb.server.ServerProperties; +import caosdb.server.resource.AbstractCaosDBServerResource; +import caosdb.server.resource.Webinterface; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.restlet.data.Reference; + +/** + * This class is responsible for two things: + * <li>Resolving relative paths of files of the web interface to {@link File} objects. + * <li>Generating URIs to public files of the web interface from relative string paths. + * + * <p>Especially the {@link AbstractCaosDBServerResource} and the {@link Webinterface} use this + * class for these tasks. + * + * @author Timm Fitschen (t.fitschen@indiscale.com) + */ +public class WebinterfaceUtils { + + private Logger logger = LogManager.getLogger(this.getClass()); + public static final String DEFAULT_WEBUI_PUBLIC = "caosdb-webui/public"; + public static final String DEFAULT_BUILD_NUMBER_FILE = ".build_number"; + public static final String DEFAULT_ROUTE = "webinterface"; + private final String host; + private final String publicDir; + private final String route; + private final Path buildNumberFile; + private final String contextRoot; + private String buildNumber = null; + private long buildNumberDate; + private static final Map<String, WebinterfaceUtils> instances = new HashMap<>(); + + /** + * Retrieve an instance of {@link WebinterfaceUtils} for the host. The instance can be shared with + * other callers. + * + * @param host + * @return a shared instance of {@link WebinterfaceUtils}. + */ + public static WebinterfaceUtils getInstance(Reference host) { + return getInstance(host.getHostIdentifier()); + } + + /** + * Retrieve an instance of {@link WebinterfaceUtils} for the host. The instance can be shared with + * other callers. + * + * @param host + * @return a shared instance of {@link WebinterfaceUtils}. + */ + public static WebinterfaceUtils getInstance(String host) { + synchronized (instances) { + WebinterfaceUtils ret = instances.get(host); + if (ret == null) { + ret = new WebinterfaceUtils(host); + instances.put(host, ret); + } + return ret; + } + } + + /** + * Create a utility class for creating references to resources of the web interface. + * + * @param host + * @param contextRoot + * @param publicDir + * @param route + * @param buildNumberFile + */ + WebinterfaceUtils( + String host, String contextRoot, String publicDir, String route, String buildNumberFile) { + this.host = host; + this.contextRoot = contextRoot; + this.publicDir = publicDir; + this.route = route; + this.buildNumberFile = getPublicRootPath().resolve(buildNumberFile); + } + + /** + * Create a utility class for creating references to resources of the web interface. + * + * <p>The route to the web interface, the build number file and the public folder of the web + * interface build directory are set to default values ({@link #DEFAULT_BUILD_NUMBER_FILE}, {@link + * #DEFAULT_ROUTE}, and {@link #DEFAULT_WEBUI_PUBLIC}). + * + * <p>The contextRoute defaults to the server property {@link ServerProperties.KEY_CONTEXT_ROOT}. + * + * @param host - the host of the web interface. + * @see {@link WebinterfaceUtils#WebinterfaceUtils(String, String, String, String)}. + */ + WebinterfaceUtils(Reference host) { + this(host.getHostIdentifier()); + } + + /** + * Create a utility class for creating references to resources of the web interface. + * + * <p>The route to the web interface, the build number file and the public folder of the web + * interface build directory are set to default values ({@link #DEFAULT_BUILD_NUMBER_FILE}, {@link + * #DEFAULT_ROUTE}, and {@link #DEFAULT_WEBUI_PUBLIC}). + * + * <p>The contextRoute defaults to the server property {@link ServerProperties.KEY_CONTEXT_ROOT}. + * + * @param host - the host of the web interface. + * @see {@link WebinterfaceUtils#WebinterfaceUtils(String, String, String, String)}. + */ + WebinterfaceUtils(String host) { + this( + host, + CaosDBServer.getServerProperty(ServerProperties.KEY_CONTEXT_ROOT), + DEFAULT_WEBUI_PUBLIC, + DEFAULT_ROUTE, + DEFAULT_BUILD_NUMBER_FILE); + } + + /** + * Return the server root reference. + * + * <p>The server root is composed of the scheme (https://) the host name (example.com) the port if + * necessary (:10443) and the context root of the application (beta). + * + * @return the server root reference e.g. https://example.com:10443/beta. + */ + public String getServerRootURI() { + if (contextRoot == null || contextRoot.length() == 0) { + return host; + } + return host + "/" + contextRoot; + } + + /** + * Return the root reference for the web interface. + * + * <p>The root reference for the web interface is the server root reference ({@link + * #getServerRootURI()}) plus the route to the resource which routes to the individual resources + * of the web interface ({@link Webinterface}). + * + * @return root reference for the web interface. + */ + public String getWebinterfaceRootURI() { + return getServerRootURI() + "/" + this.route + "/" + getBuildNumber(); + } + + /** + * Return the absolute path of the root of the public directory of the webui. + * + * @return Public directory of webui. + */ + public Path getPublicRootPath() { + return Paths.get(this.publicDir).toAbsolutePath(); + } + + /** + * return the Path of the build number file. + * + * @return + */ + public Path getBuildNumberFile() { + return this.buildNumberFile; + } + + /** + * Determine the build number of the webui. Returns null if the build number could not be + * determined. + * + * <p>Because opening and reading the {@link #buildNumberFile} content is expensive, the + * buildNumber is cached. + * + * <p>The cached buildNumber invalidates when the files modified time stamp is younger than the + * {@link #buildNumberDate}. The validity of the cache is checked once every minute with a {@link + * CronJob}. + * + * @return Build number or null. + */ + public String getBuildNumber() { + validateBuildNumber(); + if (this.buildNumber == null) { + this.buildNumberDate = System.currentTimeMillis(); + this.buildNumber = readBuildNumber(); + } + return this.buildNumber; + } + + /** + * Return the latest buildNumber, freshly read from the buildNumberfile. + * + * @return fresh build number. + */ + public String readBuildNumber() { + Path buildNumberFile = getBuildNumberFile(); + StringBuilder contentBuilder = new StringBuilder(); + try (Stream<String> stream = Files.lines(buildNumberFile, StandardCharsets.UTF_8)) { + stream.forEach(s -> contentBuilder.append(s)); + } catch (IOException e) { + logger.error(e); + return null; + } + return contentBuilder.toString(); + } + + /** + * Return the public file or null if the file does not exists or is not in the public directory of + * the web interface. + * + * <p>This method is used to resolve requests for files of the web interface. + * + * @param path + * @return The file or null + */ + public File getPublicFile(String path) { + Path publicFilePath = getPublicFilePath(path); + if (publicFilePath != null) { + File publicFile = publicFilePath.toFile(); + if (publicFile.exists() && !publicFile.isDirectory() && publicFile.canRead()) + return publicFile; + } + return null; + } + + /** + * Return the absolute path to the public file denoted by the path. + * + * <p>This method is used to resolve requests for files of the web interface. + * + * @param path - path to the file of the web interface, relative to the public directory of the + * web interface. + * @return The absolute path of the web interface file. + */ + public Path getPublicFilePath(String path) { + Path root = getPublicRootPath(); + Path resolved = root.resolve(path).toAbsolutePath().normalize(); + if (resolved.startsWith(root)) { + return resolved; + } + return null; + } + + /** + * Return a URI to a public file of the web interface. + * + * <p>This method is used to generate references for *.xsl files or other resources of the web + * interface. + * + * @param publicFile - the path of the public file, relative to the public directory of the web + * interface. + * @return a URI for the public file of the web interface. + */ + public String getWebinterfaceURI(String publicFile) { + return getWebinterfaceRootURI() + "/" + publicFile; + } + + /** + * Check the validity of the buildNumber and invalidate the buildNumber if the buildNumberDate is + * older than the {@link File#lastModified} time stamp of the buildNumberFile. + */ + public void validateBuildNumber() { + if (buildNumber != null + && getBuildNumberFile().toFile().lastModified() > this.buildNumberDate) { + this.buildNumber = null; + } + } +} diff --git a/src/test/java/caosdb/server/resource/TestScriptingResource.java b/src/test/java/caosdb/server/resource/TestScriptingResource.java index 8ea1cc2e888ceacd51213ef1d1516ede498a8267..353a2ea220984705b2612e01fe8460d5c2d7b457 100644 --- a/src/test/java/caosdb/server/resource/TestScriptingResource.java +++ b/src/test/java/caosdb/server/resource/TestScriptingResource.java @@ -178,6 +178,7 @@ public class TestScriptingResource { request.setRootRef(new Reference("bla")); request.getAttributes().put("SRID", "asdf1234"); request.setDate(new Date()); + request.setHostRef("bla"); resource.init(null, request, new Response(null)); resource.handle(); diff --git a/src/test/java/caosdb/server/utils/WebinterfaceUtilsTest.java b/src/test/java/caosdb/server/utils/WebinterfaceUtilsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4ff5d7185d43704e4bc97ef435a5c853e58e3eb8 --- /dev/null +++ b/src/test/java/caosdb/server/utils/WebinterfaceUtilsTest.java @@ -0,0 +1,45 @@ +package caosdb.server.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import caosdb.server.CaosDBServer; +import java.io.IOException; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.restlet.data.Reference; + +public class WebinterfaceUtilsTest { + + @Rule public ExpectedException exceptionRule = ExpectedException.none(); + + @BeforeClass + public static void setup() throws IOException { + CaosDBServer.initServerProperties(); + } + + @Test + public void testGetWebinterfaceReference() { + WebinterfaceUtils utils = new WebinterfaceUtils(new Reference("https://host:2345/some_path")); + String buildNumber = utils.getBuildNumber(); + String ref = utils.getWebinterfaceURI("sub"); + assertEquals("https://host:2345/webinterface/" + buildNumber + "/sub", ref); + } + + @Test + public void testGetPublicFile() { + WebinterfaceUtils utils = new WebinterfaceUtils(new Reference("https://host:2345/some_path")); + assertNull(utils.getPublicFile("../")); + } + + @Test + public void testGetPublicFilePath() { + WebinterfaceUtils utils = new WebinterfaceUtils(new Reference("https://host:2345/some_path")); + assertNull(utils.getPublicFilePath("../")); + assertNotNull(utils.getPublicFilePath("./")); + assertNotNull(utils.getPublicFilePath("bla")); + } +}