001/** 002 * Copyright 2015 DuraSpace, Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.fcrepo.camel; 017 018import static org.apache.commons.lang3.StringUtils.normalizeSpace; 019import static org.fcrepo.camel.integration.FcrepoTestUtils.getFcrepoEndpointUri; 020import static org.fcrepo.camel.integration.FcrepoTestUtils.getN3Document; 021import static org.fcrepo.camel.integration.FcrepoTestUtils.getTurtleDocument; 022import static java.net.URLEncoder.encode; 023 024import java.io.IOException; 025import java.util.HashMap; 026import java.util.Map; 027 028import org.apache.camel.EndpointInject; 029import org.apache.camel.Exchange; 030import org.apache.camel.Processor; 031import org.apache.camel.Produce; 032import org.apache.camel.ProducerTemplate; 033import org.apache.camel.builder.RouteBuilder; 034import org.apache.camel.component.mock.MockEndpoint; 035import org.apache.camel.test.junit4.CamelTestSupport; 036import org.fcrepo.camel.processor.SparqlUpdateProcessor; 037import org.junit.Test; 038 039/** 040 * Test adding a non-RDF resource 041 * @author Aaron Coburn 042 * @since November 7, 2014 043 */ 044public class SparqlUpdateProcessorTest extends CamelTestSupport { 045 046 @EndpointInject(uri = "mock:result") 047 protected MockEndpoint resultEndpoint; 048 049 @Produce(uri = "direct:start") 050 protected ProducerTemplate template; 051 052 @Test 053 public void testNamedGraph() throws IOException, InterruptedException { 054 final String base = "http://localhost/rest"; 055 final String path = "/path/a/b/c"; 056 final String graph = "foo"; 057 final String document = getN3Document(); 058 // Reverse the lines as the RDF may be serialized in opposite order 059 060 final String responsePrefix = 061 "DELETE WHERE { GRAPH <" + graph + "> { <" + base + path + "> ?p ?o } };\n" + 062 "DELETE WHERE { GRAPH <" + graph + "> { <" + base + path + "/fcr:export?format=jcr/xml> ?p ?o } };\n" + 063 "INSERT DATA { GRAPH <" + graph + "> { "; 064 final String responseSuffix = "\n} }"; 065 066 // Assertions 067 resultEndpoint.allMessages().body().startsWith("update=" + encode(responsePrefix, "UTF-8")); 068 resultEndpoint.allMessages().body().endsWith(encode(responseSuffix, "UTF-8")); 069 for (final String s : document.split("\n")) { 070 resultEndpoint.expectedBodyReceived().body().contains(encode(s, "UTF-8")); 071 } 072 resultEndpoint.expectedBodyReceived().body().contains( 073 encode("<" + base + path + "> dc:title \"some title\" .", "UTF-8")); 074 resultEndpoint.expectedHeaderReceived("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); 075 resultEndpoint.expectedHeaderReceived(Exchange.HTTP_METHOD, "POST"); 076 077 // Test 078 final Map<String, Object> headers = new HashMap<>(); 079 headers.put(FcrepoHeaders.FCREPO_BASE_URL, base + "/"); 080 headers.put(FcrepoHeaders.FCREPO_IDENTIFIER, path); 081 headers.put(FcrepoHeaders.FCREPO_NAMED_GRAPH, graph); 082 headers.put(Exchange.CONTENT_TYPE, "application/n-triples"); 083 template.sendBodyAndHeaders(document, headers); 084 085 headers.clear(); 086 headers.put(JmsHeaders.BASE_URL, base + "/"); 087 headers.put(JmsHeaders.IDENTIFIER, path); 088 headers.put(FcrepoHeaders.FCREPO_NAMED_GRAPH, graph); 089 headers.put(Exchange.CONTENT_TYPE, "text/turtle"); 090 template.sendBodyAndHeaders(getTurtleDocument(), headers); 091 092 headers.clear(); 093 headers.put(JmsHeaders.BASE_URL, base); 094 headers.put(FcrepoHeaders.FCREPO_IDENTIFIER, path); 095 headers.put(FcrepoHeaders.FCREPO_NAMED_GRAPH, graph); 096 headers.put(Exchange.CONTENT_TYPE, "application/n-triples"); 097 template.sendBodyAndHeaders(document, headers); 098 099 headers.clear(); 100 headers.put(FcrepoHeaders.FCREPO_BASE_URL, base); 101 headers.put(JmsHeaders.IDENTIFIER, path); 102 headers.put(FcrepoHeaders.FCREPO_NAMED_GRAPH, graph); 103 headers.put(Exchange.CONTENT_TYPE, "application/n-triples"); 104 template.sendBodyAndHeaders(document, headers); 105 106 // Confirm that assertions passed 107 resultEndpoint.expectedMessageCount(4); 108 resultEndpoint.assertIsSatisfied(); 109 } 110 111 @Test 112 public void testUpdate() throws IOException, InterruptedException { 113 final String base = "http://localhost/rest"; 114 final String path = "/path/a/b/c"; 115 final String document = getN3Document(); 116 // Reverse the lines as the RDF may be serialized in opposite order 117 118 final String responsePrefix = 119 "DELETE WHERE { <" + base + path + "> ?p ?o };\n" + 120 "DELETE WHERE { <" + base + path + "/fcr:export?format=jcr/xml> ?p ?o };\n" + 121 "INSERT DATA { "; 122 final String responseSuffix = "\n}"; 123 124 // Assertions 125 resultEndpoint.allMessages().body().startsWith("update=" + encode(responsePrefix, "UTF-8")); 126 resultEndpoint.allMessages().body().endsWith(encode(responseSuffix, "UTF-8")); 127 for (final String s : document.split("\n")) { 128 resultEndpoint.expectedBodyReceived().body().contains(encode(s, "UTF-8")); 129 } 130 resultEndpoint.expectedBodyReceived().body().contains( 131 encode("<" + base + path + "> dc:title \"some title\" .", "UTF-8")); 132 resultEndpoint.expectedHeaderReceived("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); 133 resultEndpoint.expectedHeaderReceived(Exchange.HTTP_METHOD, "POST"); 134 135 // Test 136 final Map<String, Object> headers = new HashMap<>(); 137 headers.put(FcrepoHeaders.FCREPO_BASE_URL, base + "/"); 138 headers.put(FcrepoHeaders.FCREPO_IDENTIFIER, path); 139 headers.put(Exchange.CONTENT_TYPE, "application/n-triples"); 140 template.sendBodyAndHeaders(document, headers); 141 142 headers.clear(); 143 headers.put(JmsHeaders.BASE_URL, base + "/"); 144 headers.put(JmsHeaders.IDENTIFIER, path); 145 headers.put(Exchange.CONTENT_TYPE, "text/turtle"); 146 template.sendBodyAndHeaders(getTurtleDocument(), headers); 147 148 headers.clear(); 149 headers.put(JmsHeaders.BASE_URL, base); 150 headers.put(FcrepoHeaders.FCREPO_IDENTIFIER, path); 151 headers.put(Exchange.CONTENT_TYPE, "application/n-triples"); 152 template.sendBodyAndHeaders(document, headers); 153 154 headers.clear(); 155 headers.put(FcrepoHeaders.FCREPO_BASE_URL, base); 156 headers.put(JmsHeaders.IDENTIFIER, path); 157 headers.put(Exchange.CONTENT_TYPE, "application/n-triples"); 158 template.sendBodyAndHeaders(document, headers); 159 160 // Confirm that assertions passed 161 resultEndpoint.expectedMessageCount(4); 162 resultEndpoint.assertIsSatisfied(); 163 } 164 165 @Override 166 protected RouteBuilder createRouteBuilder() { 167 return new RouteBuilder() { 168 @Override 169 public void configure() throws IOException { 170 171 final String fcrepo_uri = getFcrepoEndpointUri(); 172 173 from("direct:start") 174 .process(new SparqlUpdateProcessor()) 175 // Normalize the whitespace to make it easier to compare 176 .process(new Processor() { 177 public void process(final Exchange exchange) throws Exception { 178 final String payload = exchange.getIn().getBody(String.class); 179 exchange.getIn().setBody(normalizeSpace(payload)); 180 } 181 }) 182 .to("mock:result"); 183 } 184 }; 185 } 186}