diff --git a/.travis.yml b/.travis.yml index df26cdc0..a311838b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,3 +9,7 @@ after_success: arch: - amd64 - ppc64le + +cache: + directories: + - $HOME/.m2 diff --git a/README.md b/README.md index d1f5a5cc..f1102e69 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ From Maven com.github.jsonld-java jsonld-java - 0.13.2 + 0.13.5 Code example @@ -323,11 +323,11 @@ Here is the basic outline for what your module's pom.xml should look like com.github.jsonld-java jsonld-java-parent - 0.13.2 + 0.13.5 4.0.0 jsonld-java-{your module} - 0.13.2-SNAPSHOT + 0.13.5-SNAPSHOT JSONLD Java :: {your module name} JSON-LD Java integration module for {RDF Library your module integrates} jar @@ -449,6 +449,24 @@ Alternatively, we can also host your repository in the jsonld-java organisation CHANGELOG ========= +### 2023-11-06 +* Release 0.13.6 +* Bump Jackson-databind version to latest for security update + +### 2023-11-03 +* Release 0.13.5 +* Bump Jackson and Guava versions to latest for security updates + +### 2021-12-13 +* Release 0.13.4 +* Switch test logging from log4j to logback (Patch by @ansell) +* Improve Travis CI build Performance (Patch by @YunLemon) + +### 2021-03-06 +* Release 0.13.3 +* Fix @type when subject and object are the same (Reported by @barthanssens, Patch by @umbreak) +* Ignore @base if remote context is not relative (Reported by @whikloj, Patch by @dr0i) +* Fix throwing recursive context inclusion (Patch by @umbreak) ### 2020-09-24 * Release 0.13.2 diff --git a/core/pom.xml b/core/pom.xml index b771cbee..f14fb287 100755 --- a/core/pom.xml +++ b/core/pom.xml @@ -4,7 +4,7 @@ jsonld-java-parent com.github.jsonld-java - 0.13.3-SNAPSHOT + 0.13.6 4.0.0 jsonld-java @@ -53,8 +53,8 @@ test - org.slf4j - slf4j-log4j12 + ch.qos.logback + logback-classic test diff --git a/core/src/main/java/com/github/jsonldjava/core/Context.java b/core/src/main/java/com/github/jsonldjava/core/Context.java index bff79d8c..4e563d78 100644 --- a/core/src/main/java/com/github/jsonldjava/core/Context.java +++ b/core/src/main/java/com/github/jsonldjava/core/Context.java @@ -9,6 +9,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; import com.github.jsonldjava.core.JsonLdError.Error; import com.github.jsonldjava.utils.JsonLdUrl; @@ -25,6 +26,7 @@ public class Context extends LinkedHashMap { private static final long serialVersionUID = 2894534897574805571L; + private static final Pattern URL_PATTERN = Pattern.compile("^https?://.*$", Pattern.CASE_INSENSITIVE); private JsonLdOptions options; private Map termDefinitions; public Map inverse = null; @@ -141,8 +143,10 @@ && getTermDefinition(activeProperty).containsKey(JsonLdConsts.LANGUAGE) * @throws JsonLdError * If there is an error parsing the contexts. */ - @SuppressWarnings("unchecked") public Context parse(Object localContext, List remoteContexts) throws JsonLdError { + if (remoteContexts == null) { + remoteContexts = new ArrayList(); + } return parse(localContext, remoteContexts, false); } @@ -163,11 +167,8 @@ public Context parse(Object localContext, List remoteContexts) throws Js * @throws JsonLdError * If there is an error parsing the contexts. */ - private Context parse(Object localContext, List remoteContexts, + private Context parse(Object localContext, final List remoteContexts, boolean parsingARemoteContext) throws JsonLdError { - if (remoteContexts == null) { - remoteContexts = new ArrayList(); - } // 1. Initialize result to the result of cloning active context. Context result = this.clone(); // TODO: clone? // 2) @@ -187,13 +188,18 @@ private Context parse(Object localContext, List remoteContexts, } // 3.2) else if (context instanceof String) { - String uri = (String) result.get(JsonLdConsts.BASE); + String uri = null; + // @base is ignored when processing remote contexts, https://github.com/jsonld-java/jsonld-java/issues/304 + if (!URL_PATTERN.matcher(context.toString()).matches()) { + uri = (String) result.get(JsonLdConsts.BASE); + } uri = JsonLdUrl.resolve(uri, (String) context); // 3.2.2 if (remoteContexts.contains(uri)) { throw new JsonLdError(Error.RECURSIVE_CONTEXT_INCLUSION, uri); } - remoteContexts.add(uri); + List nextRemoteContexts = new ArrayList<>(remoteContexts); + nextRemoteContexts.add(uri); // 3.2.3: Dereference context final RemoteDocument rd = this.options.getDocumentLoader().loadDocument(uri); @@ -208,7 +214,7 @@ else if (context instanceof String) { .get(JsonLdConsts.CONTEXT); // 3.2.4 - result = result.parse(tempContext, remoteContexts, true); + result = result.parse(tempContext, nextRemoteContexts, true); // 3.2.5 continue; } else if (!(context instanceof Map)) { diff --git a/core/src/main/java/com/github/jsonldjava/core/JsonLdApi.java b/core/src/main/java/com/github/jsonldjava/core/JsonLdApi.java index 74cea926..2195d09a 100644 --- a/core/src/main/java/com/github/jsonldjava/core/JsonLdApi.java +++ b/core/src/main/java/com/github/jsonldjava/core/JsonLdApi.java @@ -2001,7 +2001,8 @@ public List fromRDF(final RDFDataset dataset, boolean noDuplicatesInData // 3.5.4) if (RDF_TYPE.equals(predicate) && (object.isIRI() || object.isBlankNode()) - && !opts.getUseRdfType() && !nodes.containsKey(object.getValue())) { + && !opts.getUseRdfType() && + (!nodes.containsKey(object.getValue()) || subject.equals(object.getValue()))) { JsonLdUtils.mergeValue(node, JsonLdConsts.TYPE, object.getValue()); continue; } diff --git a/core/src/test/java/com/github/jsonldjava/core/ContextRecursionTest.java b/core/src/test/java/com/github/jsonldjava/core/ContextRecursionTest.java new file mode 100644 index 00000000..d6610121 --- /dev/null +++ b/core/src/test/java/com/github/jsonldjava/core/ContextRecursionTest.java @@ -0,0 +1,75 @@ +package com.github.jsonldjava.core; + +import com.github.jsonldjava.utils.JsonUtils; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + + +public class ContextRecursionTest { + + @BeforeClass + public static void setup() { + System.setProperty(DocumentLoader.DISALLOW_REMOTE_CONTEXT_LOADING, "true"); + } + + @AfterClass + public static void tearDown() { + System.setProperty(DocumentLoader.DISALLOW_REMOTE_CONTEXT_LOADING, "false"); + } + + @Test + public void testIssue302_allowedRecursion() throws IOException { + + final String contextB = "{\"@context\": [\"http://localhost/d\", {\"b\": \"http://localhost/b\"} ] }"; + final String contextC = "{\"@context\": [\"http://localhost/d\", {\"c\": \"http://localhost/c\"} ] }"; + final String contextD = "{\"@context\": [\"http://localhost/e\", {\"d\": \"http://localhost/d\"} ] }"; + final String contextE = "{\"@context\": {\"e\": \"http://localhost/e\"} }"; + + final DocumentLoader dl = new DocumentLoader(); + dl.addInjectedDoc("http://localhost/b", contextB); + dl.addInjectedDoc("http://localhost/c", contextC); + dl.addInjectedDoc("http://localhost/d", contextD); + dl.addInjectedDoc("http://localhost/e", contextE); + final JsonLdOptions options = new JsonLdOptions(); + options.setDocumentLoader(dl); + + final String jsonString = "{\"@context\": [\"http://localhost/d\", \"http://localhost/b\", \"http://localhost/c\", {\"a\": \"http://localhost/a\"} ], \"a\": \"A\", \"b\": \"B\", \"c\": \"C\", \"d\": \"D\"}"; + final Object json = JsonUtils.fromString(jsonString); + final Object expanded = JsonLdProcessor.expand(json, options); + assertEquals( + "[{http://localhost/a=[{@value=A}], http://localhost/b=[{@value=B}], http://localhost/c=[{@value=C}], http://localhost/d=[{@value=D}]}]", + expanded.toString()); + } + + @Test + public void testCyclicRecursion() throws IOException { + + final String contextC = "{\"@context\": [\"http://localhost/d\", {\"c\": \"http://localhost/c\"} ] }"; + final String contextD = "{\"@context\": [\"http://localhost/e\", {\"d\": \"http://localhost/d\"} ] }"; + final String contextE = "{\"@context\": [\"http://localhost/c\", {\"e\": \"http://localhost/e\"} ] }"; + + final DocumentLoader dl = new DocumentLoader(); + dl.addInjectedDoc("http://localhost/c", contextC); + dl.addInjectedDoc("http://localhost/d", contextD); + dl.addInjectedDoc("http://localhost/e", contextE); + final JsonLdOptions options = new JsonLdOptions(); + options.setDocumentLoader(dl); + + final String jsonString = "{\"@context\": [\"http://localhost/c\", {\"a\": \"http://localhost/a\"} ]}"; + final Object json = JsonUtils.fromString(jsonString); + try { + JsonLdProcessor.expand(json, options); + fail("it should throw"); + } catch(JsonLdError err) { + assertEquals(JsonLdError.Error.RECURSIVE_CONTEXT_INCLUSION, err.getType()); + assertEquals("recursive context inclusion: http://localhost/c", err.getMessage()); + } + } + +} diff --git a/core/src/test/java/com/github/jsonldjava/core/DocumentLoaderTest.java b/core/src/test/java/com/github/jsonldjava/core/DocumentLoaderTest.java index c16d40b5..57b8f5ce 100644 --- a/core/src/test/java/com/github/jsonldjava/core/DocumentLoaderTest.java +++ b/core/src/test/java/com/github/jsonldjava/core/DocumentLoaderTest.java @@ -381,11 +381,19 @@ public void testDisallowRemoteContexts() throws Exception { } @Test - public void injectContext() throws Exception { + public void testInjectContext() throws Exception { + injectContext(new JsonLdOptions()); + } + + @Test + public void testIssue304_remoteContextAndBaseIri() throws Exception { + injectContext(new JsonLdOptions("testing:baseIri")); + } + + private void injectContext(final JsonLdOptions options) throws Exception { final Object jsonObject = JsonUtils.fromString( "{ \"@context\":\"http://nonexisting.example.com/thing\", \"pony\":5 }"); - final JsonLdOptions options = new JsonLdOptions(); // Verify fails to find context by default try { diff --git a/core/src/test/java/com/github/jsonldjava/core/JsonLdToRdfTest.java b/core/src/test/java/com/github/jsonldjava/core/JsonLdToRdfTest.java new file mode 100644 index 00000000..7586c1c6 --- /dev/null +++ b/core/src/test/java/com/github/jsonldjava/core/JsonLdToRdfTest.java @@ -0,0 +1,31 @@ +package com.github.jsonldjava.core; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class JsonLdToRdfTest { + + @Test + public void testIssue301() throws JsonLdError { + final RDFDataset rdf = new RDFDataset(); + rdf.addTriple( + "http://www.w3.org/2002/07/owl#Class", + "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", + "http://www.w3.org/2002/07/owl#Class"); + final JsonLdOptions opts = new JsonLdOptions(); + opts.setUseRdfType(Boolean.FALSE); + opts.setProcessingMode(JsonLdOptions.JSON_LD_1_0); + + final Object out = new JsonLdApi(opts).fromRDF(rdf, true); + assertEquals("[{@id=http://www.w3.org/2002/07/owl#Class, @type=[http://www.w3.org/2002/07/owl#Class]}]", + out.toString()); + + opts.setUseRdfType(Boolean.TRUE); + + final Object out2 = new JsonLdApi(opts).fromRDF(rdf, true); + assertEquals("[{@id=http://www.w3.org/2002/07/owl#Class, http://www.w3.org/1999/02/22-rdf-syntax-ns#type=[{@id=http://www.w3.org/2002/07/owl#Class}]}]", + out2.toString()); + } + +} diff --git a/core/src/test/resources/custom/base-0001-in.jsonld b/core/src/test/resources/custom/base-0001-in.jsonld index f9bd58fd..12a082af 100644 --- a/core/src/test/resources/custom/base-0001-in.jsonld +++ b/core/src/test/resources/custom/base-0001-in.jsonld @@ -1,6 +1,6 @@ { - "@context": [ -"https://raw.githubusercontent.com/monarch-initiative/monarch-app/master/conf/monarch-context.jsonld", + "@context": [ + "https://raw.githubusercontent.com/jsonld-java/jsonld-java/master/core/src/test/resources/custom/monarch-context.jsonld", { "@base": "http://example.org/base/", "ex": "http://example.org/", @@ -13,4 +13,5 @@ "ex:name": "Jim", "ex:friendOf": "1234", "@type": "Person" -} \ No newline at end of file +} + diff --git a/core/src/test/resources/custom/base-0002-in.jsonld b/core/src/test/resources/custom/base-0002-in.jsonld index 4b2e3848..d533f432 100644 --- a/core/src/test/resources/custom/base-0002-in.jsonld +++ b/core/src/test/resources/custom/base-0002-in.jsonld @@ -1,5 +1,5 @@ { - "@context": [ + "@context": [ { "@base": "http://example.org/base/", "ex": "http://example.org/", @@ -7,10 +7,11 @@ "@type": "@id" } }, - "https://raw.githubusercontent.com/monarch-initiative/monarch-app/master/conf/monarch-context.jsonld" + "https://raw.githubusercontent.com/jsonld-java/jsonld-java/master/core/src/test/resources/custom/monarch-context.jsonld" ], "@id": "3456", "ex:name": "Jim", "ex:friendOf": "1234", "@type": "Person" -} \ No newline at end of file +} + diff --git a/core/src/test/resources/custom/monarch-context.jsonld b/core/src/test/resources/custom/monarch-context.jsonld new file mode 100644 index 00000000..472f4153 --- /dev/null +++ b/core/src/test/resources/custom/monarch-context.jsonld @@ -0,0 +1,149 @@ +{ + "@context" : { + "EFO" : "http://purl.obolibrary.org/obo/EFO_", + "obo" : "http://purl.obolibrary.org/obo/", + "inheritance" : "monarch:mode_of_inheritance", + "@base" : "http://monarch-initiative.org/", + "email" : "foaf:mbox", + "BIND" : "http://identifiers.org/bind/bind:", + "morpholino" : "GENO:0000417", + "GENO" : "http://purl.obolibrary.org/obo/GENO_", + "UMLS" : "http://purl.obolibrary.org/obo/UMLS_", + "dcat" : "http://www.w3.org/ns/dcat#", + "PMID" : "http://www.ncbi.nlm.nih.gov/pubmed/", + "MP" : "http://purl.obolibrary.org/obo/MP_", + "ISBN-10" : "http://monarch-initiative.org/publications/ISBN:", + "rdf" : "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + "title" : "dc:title", + "Class" : "owl:Class", + "FBbt" : "http://purl.obolibrary.org/obo/FBbt_", + "pathway_associations" : "rdfs:seeAlso", + "FBInternalGT" : "http://monarchinitiative.org/genotype/", + "has_genotype" : "GENO:0000222", + "genotype" : "GENO:0000000", + "void" : "http://rdfs.org/ns/void#", + "has_phenotype" : "RO:0002200", + "reference_locus" : "GENO:0000036", + "dbVar" : "http://identifiers.org/dbVar_", + "AQTLTrait" : "http://purl.obolibrary.org/obo/AQTLTrait_", + "phenotype_associations" : "rdfs:seeAlso", + "ECO" : "http://purl.obolibrary.org/obo/ECO_", + "WB" : "http://identifiers.org/WormBase:", + "rdfs" : "http://www.w3.org/2000/01/rdf-schema#", + "variant_loci" : "GENO:0000027", + "MedGen" : "http://purl.obolibrary.org/obo/MedGen_", + "creator" : { + "@id" : "dc:creator", + "@type" : "@id" + }, + "SIO" : "http://semanticscience.org/resource/SIO_", + "DOID" : "http://purl.obolibrary.org/obo/DOID_", + "Ensembl" : "http://identifiers.org/ensembl:", + "id" : "@id", + "publisher" : "dc:publisher", + "depiction" : { + "@id" : "foaf:depiction", + "@type" : "@id" + }, + "ENSEMBL" : "http://identifiers.org/ensembl:", + "monarch" : "http://monarchinitiative.org/", + "ORPHANET" : "http://purl.obolibrary.org/obo/ORPHANET_", + "owl" : "http://www.w3.org/2002/07/owl#", + "GeneReviews" : "http://www.ncbi.nlm.nih.gov/books/", + "SNOMED_CT" : "http://purl.obolibrary.org/obo/SNOMED_", + "chromosomal_region" : "GENO:0000390", + "EOM" : "http://purl.obolibrary.org/obo/EOM_", + "type" : { + "@id" : "rdf:type", + "@type" : "@id" + }, + "FlyBase" : "http://identifiers.org/flybase:", + "DECIPHER" : "http://purl.obolibrary.org/obo/DECIPHER_", + "faldo" : "http://biohackathon.org/resource/faldo#", + "prov" : "http://www.w3.org/ns/prov#", + "MIM" : "http://purl.obolibrary.org/obo/OMIM_", + "genomic_variation_complement" : "GENO:0000009", + "evidence" : "monarch:evidence", + "BioGRID" : "http://purl.obolibrary.org/BioGRID_", + "dcterms" : "http://purl.org/dc/terms/", + "sequence_alteration" : "SO:0001059", + "RO" : "http://purl.obolibrary.org/obo/RO_", + "created" : { + "@id" : "dc:created", + "@type" : "xsd:dateTime" + }, + "Orphanet" : "http://purl.obolibrary.org/obo/ORPHANET_", + "oa" : "http://www.w3.org/ns/oa#", + "SGD" : "http://identifiers.org/mgd/sgd:", + "Gene" : "http://purl.obolibrary.org/obo/NCBIGene_", + "PomBase" : "http://identifiers.org/PomBase:", + "genotype_associations" : "rdfs:seeAlso", + "xsd" : "http://www.w3.org/2001/XMLSchema#", + "OMIABreed" : "http://purl.obolibrary.org/obo/OMIA_", + "TAIR" : "http://identifiers.org/mgd/tair:", + "oboInOwl" : "http://www.geneontology.org/formats/oboInOwl#", + "description" : "dc:description", + "disease" : "monarch:disease", + "OMIAPub" : "http://purl.obolibrary.org/obo/OMIAPub_", + "foaf" : "http://xmlns.com/foaf/0.1/", + "idot" : "http://identifiers.org/", + "subClassOf" : "owl:subClassOf", + "source" : "dc:source", + "keyword" : "dcat:keyword", + "onset" : "monarch:age_of_onset", + "genomic_background" : "GENO:0000010", + "dictyBase" : "http://identifiers.org/dictyBase:", + "OMIA" : "http://purl.obolibrary.org/obo/OMIA_", + "has_part" : "BFO:0000051", + "ClinVarVariant" : "http://identifiers.org/ClinVarVariant_", + "gene_locus" : "GENO:0000014", + "effective_genotype" : "GENO:0000525", + "VT" : "http://purl.obolibrary.org/obo/VT_", + "Association" : "SIO:000897", + "resource" : "monarch:nif-resource", + "KEGG" : "http://identifiers.org/kegg:", + "Annotation" : "oa:Annotation", + "FBdv" : "http://purl.obolibrary.org/obo/FBdv_", + "GeneID" : "http://purl.obolibrary.org/obo/NCBIGene_", + "has_background" : "GENO:0000010", + "BFO" : "http://purl.obolibrary.org/obo/BFO_", + "FB" : "http://identifiers.org/flybase:", + "frequency" : "monarch:frequency", + "ZP" : "http://purl.obolibrary.org/obo/ZP_", + "OMIM" : "http://purl.obolibrary.org/obo/OMIM_", + "MGI" : "http://identifiers.org/mgd/MGI:", + "dc" : "http://purl.org/dc/terms/", + "MONARCH" : "http://monarchinitiative.org/MONARCH_", + "ClinVarHaplotype" : "http://identifiers.org/ClinVarHaplotype_", + "homepage" : { + "@id" : "foaf:homepage", + "@type" : "@id" + }, + "RGD" : "http://identifiers.org/mgd/rgd:", + "CORIELL" : "http://purl.obolibrary.org/obo/CORIELL_", + "label" : "rdfs:label", + "NCBIGene" : "http://purl.obolibrary.org/obo/NCBIGene_", + "intrinsic_genotype" : "GENO:0000000", + "FBcv" : "http://purl.obolibrary.org/obo/FBcv_", + "WBStrain" : "http://identifiers.org/WormBase:", + "sequence_alteration_collection" : "GENO:0000025", + "reference" : "dc:publication", + "zygosity" : "GENO:0000133", + "chromosome" : "GENO:0000323", + "WormBase" : "http://identifiers.org/WormBase:", + "HPRD" : "http://identifiers.org/hprd/hprd:", + "ClinVar" : "http://purl.obolibrary.org/obo/ClinVar_", + "ISBN-13" : "http://monarch-initiative.org/publications/ISBN:", + "extrinsic_genotype" : "GENO:0000524", + "NCBITaxon" : "http://purl.obolibrary.org/obo/NCBITaxon_", + "environment" : "GENO:0000099", + "variant_locus" : "GENO:0000481", + "comment" : "rdfs:comment", + "SO" : "http://purl.obolibrary.org/obo/SO_", + "phenotype" : "monarch:phenotype", + "ZFIN" : "http://identifiers.org/zfin:", + "HP" : "http://purl.obolibrary.org/obo/HP_", + "MESH" : "http://purl.obolibrary.org/obo/MESH_", + "dbSNP" : "http://identifiers.org/dbSNP_" + } +} diff --git a/core/src/test/resources/log4j.properties b/core/src/test/resources/log4j.properties deleted file mode 100644 index 6cebabb1..00000000 --- a/core/src/test/resources/log4j.properties +++ /dev/null @@ -1,5 +0,0 @@ -log4j.rootLogger=INFO, R - -log4j.appender.R=org.apache.log4j.ConsoleAppender -log4j.appender.R.layout=org.apache.log4j.PatternLayout -log4j.appender.R.layout.ConversionPattern=[%d] %-5p (%c:%L) %m%n diff --git a/pom.xml b/pom.xml index 5bddbf03..de5316fa 100755 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.github.jsonld-java jsonld-java-parent - 0.13.3-SNAPSHOT + 0.13.6 JSONLD Java :: Parent Json-LD Java Parent POM pom @@ -39,11 +39,13 @@ UTF-8 UTF-8 - 4.5.12 - 4.4.13 - 2.11.2 - 4.13 - 1.7.30 + 4.5.13 + 4.4.14 + 2.12.7 + 2.12.7.1 + 4.13.2 + 1.7.32 + 1.2.7 0.11.0 @@ -65,7 +67,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson.version} + ${jackson-databind.version} com.fasterxml.jackson.core @@ -96,9 +98,9 @@ runtime - org.slf4j - slf4j-log4j12 - ${slf4j.version} + ch.qos.logback + logback-classic + ${logback.version} test @@ -210,7 +212,7 @@ com.google.guava guava - 29.0-jre + 32.1.3-jre @@ -351,7 +353,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.0 + 3.2.1 attach-source @@ -401,7 +403,7 @@ com.github.siom79.japicmp japicmp-maven-plugin - 0.14.2 + 0.14.4 @@ -448,7 +450,7 @@ org.jacoco jacoco-maven-plugin - 0.8.5 + 0.8.6 prepare-agent