diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f381a93a..c7031dea 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -63,8 +63,8 @@ jobs: echo ENGINE PROPERTIES cat engine.jpar echo LOG4J - cat log4j2.xml - java -Dlog4j.configurationFile=./log4j2.xml -jar engine-1.0.0-SNAPSHOT.jar -engine engine.jpar -endpoint endpoint.jpar > log.txt & + cat log4j2-debug.xml + java -Dlog4j.configurationFile=./log4j2-debug.xml -jar engine-1.0.0-SNAPSHOT.jar -engine engine.jpar -endpoint endpoint.jpar > log.txt & shell: bash - name: wait for SEPA engine uses: nev7n/wait_for_response@v1 @@ -74,9 +74,10 @@ jobs: timeout: 20000 interval: 500 - name: verify - run: mvn verify -e - - name: Archive code coverage results + run: mvn verify -e -Dlog4j2.level=trace + - name: publish Engine log uses: actions/upload-artifact@v2 + if: always() with: name: engine-log path: engine/target/log.txt diff --git a/Dockerfile b/Dockerfile index dc12ae01..3b9c2b2c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,14 +14,16 @@ COPY --from=BUILD ./engine/src/main/resources/jmxremote.password /jmxremote.pass COPY --from=BUILD ./engine/src/main/resources/jmxremote.access /jmxremote.access COPY --from=BUILD ./engine/src/main/resources/jmx.properties /jmx.properties COPY --from=BUILD ./engine/src/main/resources/endpoint.jpar /endpoint.jpar - +# COPY ALL ENDPOINTS TO ALLOW CMD LINE CUSTOMIZATION +COPY --from=BUILD ./engine/src/main/resources/endpoints /endpoints RUN chmod 600 /jmxremote.password +ENV JMX_HOSTNAME=0.0.0.0 +ENV JMX_PORT=7090 + EXPOSE 8000 EXPOSE 9000 -EXPOSE 7091 - -ENV JMX_HOSTNAME=0.0.0.0 +EXPOSE ${JMX_PORT} -ENTRYPOINT java -Djava.rmi.server.hostname=${JMX_HOSTNAME} -Dcom.sun.management.config.file=jmx.properties -jar engine.jar +ENTRYPOINT java -Djava.rmi.server.hostname=${JMX_HOSTNAME} -Dcom.sun.management.jmxremote.port=${JMX_PORT} -Dcom.sun.management.jmxremote.rmi.port=${JMX_PORT} -Dcom.sun.management.config.file=jmx.properties -jar engine.jar diff --git a/client-api/src/main/java/it/unibo/arces/wot/sepa/commons/properties/SPARQL11SEProperties.java b/client-api/src/main/java/it/unibo/arces/wot/sepa/commons/properties/SPARQL11SEProperties.java index 11adc036..d721aea2 100644 --- a/client-api/src/main/java/it/unibo/arces/wot/sepa/commons/properties/SPARQL11SEProperties.java +++ b/client-api/src/main/java/it/unibo/arces/wot/sepa/commons/properties/SPARQL11SEProperties.java @@ -192,7 +192,7 @@ protected final void setParameter(String key,String value) { break; default: if (key.startsWith("-sparql11seprotocol.availableProtocols")) { - String[] token = key.split("."); + String[] token = key.split("\\."); if (token[3] == "path") this.sparql11seprotocol.availableProtocols.get(token[2]).path = value; else if (token[3] == "port") this.sparql11seprotocol.availableProtocols.get(token[2]).port = Integer.valueOf(value); else if (token[3] == "scheme") this.sparql11seprotocol.availableProtocols.get(token[2]).scheme = value; diff --git a/client-api/src/main/java/it/unibo/arces/wot/sepa/commons/sparql/Bindings.java b/client-api/src/main/java/it/unibo/arces/wot/sepa/commons/sparql/Bindings.java index f5d0c322..fee03431 100644 --- a/client-api/src/main/java/it/unibo/arces/wot/sepa/commons/sparql/Bindings.java +++ b/client-api/src/main/java/it/unibo/arces/wot/sepa/commons/sparql/Bindings.java @@ -26,6 +26,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; import it.unibo.arces.wot.sepa.commons.exceptions.SEPABindingsException; /** @@ -92,7 +93,9 @@ public RDFTerm getRDFTerm(String variable) throws SEPABindingsException { try { String type = getType(variable); String value = getValue(variable); - + + if (type == null || value == null) return null; + switch(type) { case "uri": return new RDFTermURI(value); @@ -105,7 +108,7 @@ public RDFTerm getRDFTerm(String variable) throws SEPABindingsException { } } catch(Exception e) { - throw new SEPABindingsException(e); + return null; } return null; @@ -221,7 +224,12 @@ public boolean isBNode(String variable) throws SEPABindingsException { * the value */ public void addBinding(String variable, RDFTerm value) { - solution.add(variable, value.toJson()); + if (value == null) { + JsonObject undefObject = new JsonObject(); + undefObject.add("value",null); + solution.add(variable,undefObject); + } + else solution.add(variable, value.toJson()); } /** diff --git a/client-api/src/main/java/it/unibo/arces/wot/sepa/commons/sparql/RDFTerm.java b/client-api/src/main/java/it/unibo/arces/wot/sepa/commons/sparql/RDFTerm.java index 7e7fefef..273e44ab 100644 --- a/client-api/src/main/java/it/unibo/arces/wot/sepa/commons/sparql/RDFTerm.java +++ b/client-api/src/main/java/it/unibo/arces/wot/sepa/commons/sparql/RDFTerm.java @@ -49,6 +49,7 @@ public boolean isBNode() { */ public String getValue() { if (!json.has("value")) return null; + if (json.get("value") == null) return null; return json.get("value").getAsString(); } diff --git a/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/Aggregator.java b/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/Aggregator.java index b46f242f..77066ed9 100644 --- a/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/Aggregator.java +++ b/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/Aggregator.java @@ -28,12 +28,14 @@ import it.unibo.arces.wot.sepa.commons.request.UpdateRequest; import it.unibo.arces.wot.sepa.commons.response.Response; +import java.util.ArrayList; + public abstract class Aggregator extends Consumer implements IConsumer, IProducer { private final String sparqlUpdate; protected final String updateId; private final ForcedBindings updateForcedBindings; private final SPARQL11Protocol sparql11; - + private MultipleForcedBindings multipleForcedBindings; public Aggregator(JSAP appProfile, String subscribeID, String updateID) throws SEPAProtocolException, SEPASecurityException, SEPAPropertiesException { super(appProfile, subscribeID); @@ -49,11 +51,11 @@ public Aggregator(JSAP appProfile, String subscribeID, String updateID) } updateId = updateID; - sparqlUpdate = appProfile.getSPARQLUpdate(updateID); updateForcedBindings = appProfile.getUpdateBindings(updateID); - + multipleForcedBindings = appProfile.getUpdateMultipleBindings(updateID); + sparql11 = new SPARQL11Protocol(sm); } @@ -77,7 +79,35 @@ public final Response update(long timeout,long nRetry) throws SEPASecurityExcept return retResponse; } + public final Response multipleUpdate(long timeout,long nRetry) + throws SEPASecurityException, SEPAPropertiesException, SEPABindingsException, SEPAProtocolException { + UpdateRequest req = new UpdateRequest(appProfile.getUpdateMethod(updateId), + appProfile.getUpdateProtocolScheme(updateId), appProfile.getUpdateHost(updateId), + appProfile.getUpdatePort(updateId), appProfile.getUpdatePath(updateId), + appProfile.addPrefixesAndReplaceMultipleBindings(sparqlUpdate, + addDefaultDatatype(multipleForcedBindings.getBindings(), updateId, false)), + appProfile.getUsingGraphURI(updateId), appProfile.getUsingNamedGraphURI(updateId), + (appProfile.isSecure() ? appProfile.getAuthenticationProperties().getBearerAuthorizationHeader() : null), timeout,nRetry); + + Logging.logger.trace(req); + + Response retResponse = sparql11.update(req); + + Logging.logger.trace(retResponse); + + return retResponse; + } + + public final Response multipleUpdate() + throws SEPASecurityException, SEPAProtocolException, SEPAPropertiesException, SEPABindingsException { + return multipleUpdate(TIMEOUT,NRETRY); + } + public final void setUpdateBindingValue(String variable, RDFTerm value) throws SEPABindingsException { updateForcedBindings.setBindingValue(variable, value); } + + public final void setUpdateMultipleBindings(ArrayList variables, ArrayList> values) throws SEPABindingsException { + multipleForcedBindings.setUpdateBindings(variables,values); + } } diff --git a/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/Client.java b/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/Client.java index d4c009ec..d8d99293 100644 --- a/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/Client.java +++ b/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/Client.java @@ -19,6 +19,7 @@ package it.unibo.arces.wot.sepa.pattern; import java.io.IOException; +import java.util.ArrayList; import it.unibo.arces.wot.sepa.commons.exceptions.SEPABindingsException; import it.unibo.arces.wot.sepa.commons.exceptions.SEPAPropertiesException; @@ -140,11 +141,16 @@ public void close() throws IOException { * **/ + protected ArrayList addDefaultDatatype(ArrayList bindings, String id, boolean query) throws SEPABindingsException { + ArrayList temp = new ArrayList<>(); + for (Bindings b : bindings) temp.add(addDefaultDatatype(b,id,query)); + return temp; + } protected Bindings addDefaultDatatype(Bindings bindings, String id, boolean query) throws SEPABindingsException { if (id == null) return bindings; if (bindings == null) - return bindings; + return null; // Forced bindings by JSAP Bindings jsap_template; @@ -154,9 +160,13 @@ protected Bindings addDefaultDatatype(Bindings bindings, String id, boolean quer jsap_template = appProfile.getUpdateBindings(id); // Add missing datatype, if any - Bindings retBindings = new Bindings(); + Bindings retBindings = new ForcedBindings(); for (String varString : bindings.getVariables()) { RDFTerm term = bindings.getRDFTerm(varString); + if (term == null) { + retBindings.addBinding(varString,null); + continue; + } if (term.isLiteral()) { RDFTermLiteral literal = (RDFTermLiteral) term; if (literal.getDatatype() == null && jsap_template.getDatatype(varString) != null) diff --git a/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/ForcedBindings.java b/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/ForcedBindings.java index ec82526c..9b60c04e 100644 --- a/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/ForcedBindings.java +++ b/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/ForcedBindings.java @@ -1,5 +1,6 @@ package it.unibo.arces.wot.sepa.pattern; +import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import it.unibo.arces.wot.sepa.commons.exceptions.SEPABindingsException; @@ -10,6 +11,13 @@ import it.unibo.arces.wot.sepa.commons.sparql.RDFTermURI; public class ForcedBindings extends Bindings { + public ForcedBindings(JsonObject solution) { + super(solution); + } + + public ForcedBindings() { + super(); + } /** * Sets the binding value. * diff --git a/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/JSAP.java b/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/JSAP.java index e30f6e7d..b6b5eabf 100644 --- a/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/JSAP.java +++ b/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/JSAP.java @@ -241,7 +241,11 @@ private void load(String uri, boolean replace) throws SEPAPropertiesException, S } if(path.isAbsolute()) load(child,false); - else load (Path.of(uri).getParent().toString()+File.separator+child,false); + else { + Path childPath = Path.of(uri); + if (childPath.getParent()!= null) load (childPath.getParent().toString()+File.separator+child,false); + else load(child,false); + } } } @@ -359,8 +363,6 @@ private HashMap mergeNamespaces(HashMap jsap, Ha return jsap; } - - public JsonObject getExtendedData() { return extended; } @@ -775,7 +777,7 @@ public ForcedBindings getUpdateBindings(String id) throws IllegalArgumentExcepti bindingValue = new RDFTermBNode(value); break; default: - Logging.logger.error("JSAP unknown type: " + binding); + Logging.logger.error("JSAP unknown type: " + binding.getValue().type); continue; } @@ -788,6 +790,49 @@ public ForcedBindings getUpdateBindings(String id) throws IllegalArgumentExcepti return ret; } + public MultipleForcedBindings getUpdateMultipleBindings(String id) throws IllegalArgumentException { + if (updates.get(id) == null) + throw new IllegalArgumentException("Update ID not found: " + id); + + MultipleForcedBindings ret = new MultipleForcedBindings(); + + if (updates.get(id).forcedBindings == null) + return ret; + + try { + for (Entry binding : updates.get(id).forcedBindings.entrySet()) { + if (binding.getValue().type == null) + continue; + + RDFTerm bindingValue = null; + String value = binding.getValue().value; + + switch (binding.getValue().type) { + case "literal": + String datatype = (binding.getValue().datatype == null ? null : binding.getValue().datatype); + String language = (binding.getValue().language == null ? null : binding.getValue().language); + + bindingValue = new RDFTermLiteral(value, datatype, language); + break; + case "uri": + bindingValue = new RDFTermURI(value); + break; + case "bnode": + bindingValue = new RDFTermBNode(value); + break; + default: + Logging.logger.error("JSAP unknown type: " + binding); + continue; + } + + ret.addBinding(binding.getKey(), bindingValue); + } + } catch (Exception e) { + Logging.logger.error("getUpdateBindings " + id + " exception: " + e.getMessage()); + } + + return ret; + } public ForcedBindings getQueryBindings(String id) throws IllegalArgumentException { if (queries.get(id) == null) throw new IllegalArgumentException("Query ID not found: " + id); @@ -836,10 +881,6 @@ public String toString() { return new Gson().toJson(this); } -// public String printParameters() { -// return this.toString(); -// } - public String getUpdateUrl(String id) throws IllegalArgumentException { if (updates.get(id) == null) throw new IllegalArgumentException("Update ID not found: " + id); @@ -885,6 +926,10 @@ public String addPrefixesAndReplaceBindings(String sparql, Bindings bindings) th return prefixes + replaceBindings(sparql, bindings); } + public String addPrefixesAndReplaceMultipleBindings(String sparql, ArrayList bindings) throws SEPABindingsException { + return prefixes + replaceMultipleBindings(sparql, bindings); + } + // TODO: use Jena? // private final String replaceBindings(String sparql, Bindings bindings) throws SEPABindingsException { // QuerySolutionMap initialBinding = new QuerySolutionMap(); @@ -1057,6 +1102,163 @@ public static final String replaceBindings(String sparql, Bindings bindings) thr return replacedSparql; } + public static final String replaceMultipleBindings(String sparql, ArrayList multipleBindings) throws SEPABindingsException { + if (multipleBindings == null || sparql == null) + return sparql; + + if (multipleBindings.isEmpty()) return sparql; + + ArrayList vars = new ArrayList<>(); + vars.addAll(multipleBindings.get(0).getVariables()); + + ArrayList> allValues = new ArrayList<>(); + + for(Bindings bindings : multipleBindings) { + ArrayList values = new ArrayList(); + for (String var : vars) { + String value = bindings.getValue(var); + if (value == null) { + // https://www.w3.org/TR/sparql11-query/#inline-data + // If a variable has no value for a particular solution in the VALUES clause, the keyword UNDEF is used instead of an RDF term. + values.add("UNDEF"); + continue; + } + + /* + * 4.1.2 Syntax for Literals + * + * The general syntax for literals is a string (enclosed in either double + * quotes, "...", or single quotes, '...'), with either an optional language tag + * (introduced by @) or an optional datatype IRI or prefixed name (introduced by + * ^^). + * + * As a convenience, integers can be written directly (without quotation marks + * and an explicit datatype IRI) and are interpreted as typed literals of + * datatype xsd:integer; decimal numbers for which there is '.' in the number + * but no exponent are interpreted as xsd:decimal; and numbers with exponents + * are interpreted as xsd:double. Values of type xsd:boolean can also be written + * as true or false. + * + * To facilitate writing literal values which themselves contain quotation marks + * or which are long and contain newline characters, SPARQL provides an + * additional quoting construct in which literals are enclosed in three single- + * or double-quotation marks. + * + * Examples of literal syntax in SPARQL include: + * + * - "chat" - 'chat'@fr with language tag "fr" - + * "xyz"^^ - "abc"^^appNS:appDataType - + * '''The librarian said, "Perhaps you would enjoy 'War and Peace'."''' - 1, + * which is the same as "1"^^xsd:integer - 1.3, which is the same as + * "1.3"^^xsd:decimal - 1.300, which is the same as "1.300"^^xsd:decimal - + * 1.0e6, which is the same as "1.0e6"^^xsd:double - true, which is the same as + * "true"^^xsd:boolean - false, which is the same as "false"^^xsd:boolean + * + * Tokens matching the productions INTEGER, DECIMAL, DOUBLE and BooleanLiteral + * are equivalent to a typed literal with the lexical value of the token and the + * corresponding datatype (xsd:integer, xsd:decimal, xsd:double, xsd:boolean). + */ + + if (bindings.isLiteral(var)) { + String datatype = bindings.getDatatype(var); + String lang = bindings.getLanguage(var); + + if (datatype == null) { + if (lang != null) + value += "@" + bindings.getLanguage(var); + else { + value = "'''" + StringEscapeUtils.escapeJava(value) + "'''"; + } + } else if (!numbersOrBoolean.contains(datatype)) { + // Check if datatype is a qname or not + URI uri = null; + try { + uri = new URI(datatype); + } catch (URISyntaxException e) { + Logging.logger.error(e.getMessage()); + } + + if (uri != null) { + if (uri.getSchemeSpecificPart().startsWith("/")) + datatype = "<" + datatype + ">"; + } + + value = "'''" + StringEscapeUtils.escapeJava(value) + "'''"; + value += "^^" + datatype; + } + } else if (bindings.isURI(var)) { + // See https://www.w3.org/TR/rdf-sparql-query/#QSynIRI + // https://docs.oracle.com/javase/7/docs/api/java/net/URI.html + + // [scheme:]scheme-specific-part[#fragment] + // An absolute URI specifies a scheme; a URI that is not absolute is said to be + // relative. + // URIs are also classified according to whether they are opaque or + // hierarchical. + + // An opaque URI is an absolute URI whose scheme-specific part does not begin + // with a slash character ('/'). + // Opaque URIs are not subject to further parsing. + + // A hierarchical URI is either an absolute URI whose scheme-specific part + // begins with a slash character, + // or a relative URI, that is, a URI that does not specify a scheme. + // A hierarchical URI is subject to further parsing according to the syntax + // [scheme:][//authority][path][?query][#fragment] + + URI uri = null; + try { + uri = new URI(value); + } catch (URISyntaxException e) { + Logging.logger.error(e.getMessage()); + } + + if (uri != null) { + if (uri.getSchemeSpecificPart().startsWith("/") || uri.getScheme().equals("urn")) + value = "<" + value + ">"; + } + } else { + // A blank node + Logging.logger.trace("Blank node: " + value); + + // Not a BLANK_NODE_LABEL + // [142] BLANK_NODE_LABEL ::= '_:' ( PN_CHARS_U | [0-9] ) ((PN_CHARS|'.')* + // PN_CHARS)? + if (!value.startsWith("_:")) + value = "<" + value + ">"; + } + + values.add(value); + } + + allValues.add(values); + } + + String replacedSparql = String.format("%s", sparql); + + // VALUES (?book ?title) + // { (UNDEF "SPARQL Tutorial") + // (:book2 UNDEF) + // } + String VARS = "("; + for (String var: vars) { + VARS += "?"+var+" "; + } + VARS += ")"; + String VALUES = "{"; + for(ArrayList values: allValues) { + VALUES += "("; + for (String value : values) { + VALUES += value+" "; + } + VALUES += ")"; + } + VALUES += "}"; + + int end = replacedSparql.lastIndexOf("}"); + return replacedSparql.substring(0,end) + " VALUES "+VARS+VALUES+"}"; + } + private static boolean isValidVarChar(int c) { return ((c == '_') || (c == 0x00B7) || (0x0300 <= c && c <= 0x036F) || (0x203F <= c && c <= 0x2040) || ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') diff --git a/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/MultipleForcedBindings.java b/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/MultipleForcedBindings.java new file mode 100644 index 00000000..0ff09fd5 --- /dev/null +++ b/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/MultipleForcedBindings.java @@ -0,0 +1,36 @@ +package it.unibo.arces.wot.sepa.pattern; + +import com.google.gson.JsonObject; +import it.unibo.arces.wot.sepa.commons.exceptions.SEPABindingsException; +import it.unibo.arces.wot.sepa.commons.sparql.Bindings; +import it.unibo.arces.wot.sepa.commons.sparql.RDFTerm; + +import java.util.ArrayList; + +public class MultipleForcedBindings extends ForcedBindings { + ArrayList multipleForcedBindings; + + public MultipleForcedBindings(JsonObject solution) { + super(solution); + multipleForcedBindings = new ArrayList(); + } + + public MultipleForcedBindings() { + super(); + multipleForcedBindings = new ArrayList(); + } + + public final void setUpdateBindings(ArrayList variables, ArrayList> values) throws SEPABindingsException { + for(ArrayList value:values) { + Bindings b = new Bindings(); + for(int i=0; i < variables.size(); i++) { + b.addBinding(variables.get(i),value.get(i)); + } + multipleForcedBindings.add(b); + } + } + + public final ArrayList getBindings() { + return multipleForcedBindings; + } +} diff --git a/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/Producer.java b/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/Producer.java index b60ac264..7ad54e1f 100644 --- a/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/Producer.java +++ b/client-api/src/main/java/it/unibo/arces/wot/sepa/pattern/Producer.java @@ -19,7 +19,10 @@ package it.unibo.arces.wot.sepa.pattern; import java.io.IOException; +import java.lang.reflect.Array; +import java.util.ArrayList; +import it.unibo.arces.wot.sepa.commons.sparql.Bindings; import it.unibo.arces.wot.sepa.commons.sparql.RDFTerm; import it.unibo.arces.wot.sepa.logging.Logging; import it.unibo.arces.wot.sepa.api.SPARQL11Protocol; @@ -29,12 +32,13 @@ import it.unibo.arces.wot.sepa.commons.exceptions.SEPASecurityException; import it.unibo.arces.wot.sepa.commons.request.UpdateRequest; import it.unibo.arces.wot.sepa.commons.response.Response; +import org.apache.commons.rdf.api.RDF; public class Producer extends Client implements IProducer { protected String sparqlUpdate = null; protected String SPARQL_ID = ""; private ForcedBindings forcedBindings; - + private MultipleForcedBindings multipleForcedBindings; private SPARQL11Protocol client; public Producer(JSAP appProfile, String updateID) @@ -51,6 +55,7 @@ public Producer(JSAP appProfile, String updateID) sparqlUpdate = appProfile.getSPARQLUpdate(updateID); forcedBindings = appProfile.getUpdateBindings(updateID); + multipleForcedBindings = appProfile.getUpdateMultipleBindings(updateID); client = new SPARQL11Protocol(sm); } @@ -75,49 +80,34 @@ public final Response update(long timeout,long nRetry) Response retResponse = client.update(req); Logging.logger.trace(retResponse); - -// if (appProfile.isSecure() && retResponse.isError()) { -// ErrorResponse errorResponse = (ErrorResponse) retResponse; -// if (errorResponse.isTokenExpiredError()) { -// sm.refreshToken(); -// req.setAuthorizationHeader(appProfile.getAuthenticationProperties().getBearerAuthorizationHeader()); -// retResponse = client.update(req); -// } -// } - -// while (isSecure() && retResponse.isError()) { -// -// ErrorResponse errorResponse = (ErrorResponse) retResponse; -// -// if (errorResponse.isTokenExpiredError()) { -// try { -// sm.refreshToken(); -// } catch (SEPAPropertiesException | SEPASecurityException e) { -// Logging.logger.error("Failed to refresh token: " + e.getMessage()); -// } -// } else { -// Logging.logger.error(errorResponse); -// return errorResponse; -// } -// -// authorizationHeader = sm.getAuthorizationHeader(); -// -// Logging.logger.debug("Authorization header: "+authorizationHeader); -// -// req = new UpdateRequest(appProfile.getUpdateMethod(SPARQL_ID), -// appProfile.getUpdateProtocolScheme(SPARQL_ID), appProfile.getUpdateHost(SPARQL_ID), -// appProfile.getUpdatePort(SPARQL_ID), appProfile.getUpdatePath(SPARQL_ID), -// appProfile.addPrefixesAndReplaceBindings(sparqlUpdate, -// addDefaultDatatype(forcedBindings, SPARQL_ID, false)), -// appProfile.getUsingGraphURI(SPARQL_ID), appProfile.getUsingNamedGraphURI(SPARQL_ID), -// authorizationHeader, timeout,nRetry); -// -// retResponse = client.update(req); -// } return retResponse; } + public final Response multipleUpdate(long timeout,long nRetry) + throws SEPASecurityException, SEPAPropertiesException, SEPABindingsException, SEPAProtocolException { + UpdateRequest req = new UpdateRequest(appProfile.getUpdateMethod(SPARQL_ID), + appProfile.getUpdateProtocolScheme(SPARQL_ID), appProfile.getUpdateHost(SPARQL_ID), + appProfile.getUpdatePort(SPARQL_ID), appProfile.getUpdatePath(SPARQL_ID), + appProfile.addPrefixesAndReplaceMultipleBindings(sparqlUpdate, + addDefaultDatatype(multipleForcedBindings.getBindings(), SPARQL_ID, false)), + appProfile.getUsingGraphURI(SPARQL_ID), appProfile.getUsingNamedGraphURI(SPARQL_ID), + (appProfile.isSecure() ? appProfile.getAuthenticationProperties().getBearerAuthorizationHeader() : null), timeout,nRetry); + + Logging.logger.trace(req); + + Response retResponse = client.update(req); + + Logging.logger.trace(retResponse); + + return retResponse; + } + + public final Response multipleUpdate() + throws SEPASecurityException, SEPAProtocolException, SEPAPropertiesException, SEPABindingsException { + return multipleUpdate(TIMEOUT,NRETRY); + } + @Override public void close() throws IOException { super.close(); @@ -127,4 +117,8 @@ public void close() throws IOException { public final void setUpdateBindingValue(String variable, RDFTerm value) throws SEPABindingsException { forcedBindings.setBindingValue(variable, value); } + + public final void setUpdateMultipleBindings(ArrayList variables, ArrayList> values) throws SEPABindingsException { + multipleForcedBindings.setUpdateBindings(variables,values); + } } diff --git a/client-api/src/test/java/it/unibo/arces/wot/sepa/ConfigurationProvider.java b/client-api/src/test/java/it/unibo/arces/wot/sepa/ConfigurationProvider.java index a7ae7d6f..b3810c39 100644 --- a/client-api/src/test/java/it/unibo/arces/wot/sepa/ConfigurationProvider.java +++ b/client-api/src/test/java/it/unibo/arces/wot/sepa/ConfigurationProvider.java @@ -49,10 +49,10 @@ public ConfigurationProvider() throws SEPAPropertiesException, SEPASecurityExcep throw new SEPAPropertiesException("File not found: " + jsapPath); } - Logging.logger.debug("Loading JSAP from: " + jsapPath); + Logging.logger.debug("Loading JSAP from: " + f.getPath()); try { - appProfile = new JSAP(jsapPath); + appProfile = new JSAP(f.getPath()); } catch (SEPAPropertiesException e) { Logging.logger.error(e.getMessage()); throw new RuntimeException(e); diff --git a/client-api/src/test/java/it/unibo/arces/wot/sepa/Sync.java b/client-api/src/test/java/it/unibo/arces/wot/sepa/Sync.java index 791c5f30..b20af8fb 100644 --- a/client-api/src/test/java/it/unibo/arces/wot/sepa/Sync.java +++ b/client-api/src/test/java/it/unibo/arces/wot/sepa/Sync.java @@ -49,14 +49,15 @@ public synchronized long getUnsubscribes() { return unsubscribes; } - public void waitSubscribes(int total) { + public synchronized void waitSubscribes(int total) { synchronized (subscribesMutex) { while (subscribes < total) { try { - Logging.logger.trace("waitSubscribes"); + Logging.logger.trace("Thread id "+Thread.currentThread().getId()+ " waitSubscribes"); subscribesMutex.wait(); + Logging.logger.trace("Thread id "+Thread.currentThread().getId()+ " awaken from waitSubscribes"); } catch (InterruptedException e) { - break; + throw new RuntimeException(e.getCause()); } } } @@ -83,27 +84,28 @@ public void waitConnections(int total) { } } - public void waitEvents(int total) { + public synchronized void waitEvents(int total) { synchronized (eventsMutex) { while (events < total) { try { - Logging.logger.trace("waitEvents"); + Logging.logger.trace("Thread id "+Thread.currentThread().getId()+ " waitEvents"); eventsMutex.wait(); + Logging.logger.trace("Thread id "+Thread.currentThread().getId()+ " awaken from waitEvents"); } catch (InterruptedException e) { - break; + throw new RuntimeException(e.getCause()); } } } } - public void waitUnsubscribes(int total) { + public synchronized void waitUnsubscribes(int total) { synchronized (unsubscribesMutex) { while (unsubscribes < total) { try { Logging.logger.trace("waitUnsubscribes"); unsubscribesMutex.wait(); } catch (InterruptedException e) { - break; + throw new RuntimeException(e.getCause()); } } } diff --git a/client-api/src/test/java/it/unibo/arces/wot/sepa/api/ITSPARQL11SEProtocol.java b/client-api/src/test/java/it/unibo/arces/wot/sepa/api/ITSPARQL11SEProtocol.java index 2b0c2291..0dc97c7c 100644 --- a/client-api/src/test/java/it/unibo/arces/wot/sepa/api/ITSPARQL11SEProtocol.java +++ b/client-api/src/test/java/it/unibo/arces/wot/sepa/api/ITSPARQL11SEProtocol.java @@ -31,6 +31,7 @@ public class ITSPARQL11SEProtocol { private static SubscriptionProtocol protocol; @BeforeEach + @Timeout(5) public void beginTest() throws IOException, SEPAProtocolException, SEPAPropertiesException, SEPASecurityException, URISyntaxException, InterruptedException { provider = new ConfigurationProvider(); diff --git a/client-api/src/test/java/it/unibo/arces/wot/sepa/pattern/ITPattern.java b/client-api/src/test/java/it/unibo/arces/wot/sepa/pattern/ITPattern.java index f10a0fcd..2cdf4354 100644 --- a/client-api/src/test/java/it/unibo/arces/wot/sepa/pattern/ITPattern.java +++ b/client-api/src/test/java/it/unibo/arces/wot/sepa/pattern/ITPattern.java @@ -4,12 +4,7 @@ import it.unibo.arces.wot.sepa.ConsumerTestUnit; import it.unibo.arces.wot.sepa.Sync; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.RepeatedTest; -import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.api.*; import it.unibo.arces.wot.sepa.ConfigurationProvider; import it.unibo.arces.wot.sepa.commons.exceptions.SEPABindingsException; @@ -119,6 +114,7 @@ public void notification() throws InterruptedException, SEPASecurityException, I } @RepeatedTest(ConfigurationProvider.REPEATED_TEST) + @Disabled @Timeout(10) public void aggregation() throws InterruptedException, SEPASecurityException, IOException, SEPAPropertiesException, SEPAProtocolException, SEPABindingsException { diff --git a/client-api/src/test/resources/log4j2.xml b/client-api/src/test/resources/log4j2.xml index b8b53f3b..f7491e7b 100644 --- a/client-api/src/test/resources/log4j2.xml +++ b/client-api/src/test/resources/log4j2.xml @@ -1,5 +1,9 @@ + + output + error + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/engine/src/main/resources/log4j2.xml b/engine/src/main/resources/log4j2.xml index 83ce3ea8..43360691 100644 --- a/engine/src/main/resources/log4j2.xml +++ b/engine/src/main/resources/log4j2.xml @@ -1,5 +1,8 @@ + + output +