From: <tho...@us...> - 2011-04-15 16:24:25
|
Revision: 4403 http://bigdata.svn.sourceforge.net/bigdata/?rev=4403&view=rev Author: thompsonbry Date: 2011-04-15 16:24:17 +0000 (Fri, 15 Apr 2011) Log Message: ----------- Added support for POST with URIs and unit tests for same. Added logic to verify mutation counters to the unit tests. Still need to add support for default-graph-uri and named-graph-uri protocol parameters. Just about read to wrap as a deployable webapp. Removed an old test helper class which was not used by anything anymore. Modified Paths: -------------- branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/test/com/bigdata/bop/rdf/TestAll.java branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServlet.java branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataServlet.java branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/DeleteServlet.java branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/RESTServlet.java branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/UpdateServlet.java branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/TestNanoSparqlServer.java Added Paths: ----------- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/InsertServlet.java Removed Paths: ------------- branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/test/com/bigdata/rdf/store/RDFLoadAndValidateHelper.java Modified: branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/test/com/bigdata/bop/rdf/TestAll.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/test/com/bigdata/bop/rdf/TestAll.java 2011-04-15 14:02:24 UTC (rev 4402) +++ branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/test/com/bigdata/bop/rdf/TestAll.java 2011-04-15 16:24:17 UTC (rev 4403) @@ -61,6 +61,8 @@ final TestSuite suite = new TestSuite("RDF operators"); + suite.addTestSuite(TestBOpUtility.class); + // Aggregate operators (COUNT, SUM, MIN, MAX, etc.) suite.addTest(com.bigdata.bop.rdf.aggregate.TestAll.suite()); Deleted: branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/test/com/bigdata/rdf/store/RDFLoadAndValidateHelper.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/test/com/bigdata/rdf/store/RDFLoadAndValidateHelper.java 2011-04-15 14:02:24 UTC (rev 4402) +++ branches/QUADS_QUERY_BRANCH/bigdata-rdf/src/test/com/bigdata/rdf/store/RDFLoadAndValidateHelper.java 2011-04-15 16:24:17 UTC (rev 4403) @@ -1,213 +0,0 @@ -/** - -The Notice below must appear in each file of the Source Code of any -copy you distribute of the Licensed Product. Contributors to any -Modifications may add their own copyright notices to identify their -own contributions. - -License: - -The contents of this file are subject to the CognitiveWeb Open Source -License Version 1.1 (the License). You may not copy or use this file, -in either source code or executable form, except in compliance with -the License. You may obtain a copy of the License from - - http://www.CognitiveWeb.org/legal/license/ - -Software distributed under the License is distributed on an AS IS -basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -the License for the specific language governing rights and limitations -under the License. - -Copyrights: - -Portions created by or assigned to CognitiveWeb are Copyright -(c) 2003-2003 CognitiveWeb. All Rights Reserved. Contact -information for CognitiveWeb is available at - - http://www.CognitiveWeb.org - -Portions Copyright (c) 2002-2003 Bryan Thompson. - -Acknowledgements: - -Special thanks to the developers of the Jabber Open Source License 1.0 -(JOSL), from which this License was derived. This License contains -terms that differ from JOSL. - -Special thanks to the CognitiveWeb Open Source Contributors for their -suggestions and support of the Cognitive Web. - -Modifications: - -*/ -/* - * Created on May 8, 2008 - */ - -package com.bigdata.rdf.store; - -import java.io.File; -import java.io.FilenameFilter; -import java.util.concurrent.TimeUnit; - -import org.openrdf.rio.RDFFormat; - -import com.bigdata.counters.CounterSet; -import com.bigdata.rdf.load.ConcurrentDataLoader; -import com.bigdata.rdf.load.FileSystemLoader; -import com.bigdata.rdf.load.RDFLoadTaskFactory; -import com.bigdata.rdf.load.RDFVerifyTaskFactory; -import com.bigdata.rdf.rio.RDFParserOptions; -import com.bigdata.service.IBigdataFederation; - -/** - * Helper class for concurrent data load and post-load verification. - * - * @author <a href="mailto:tho...@us...">Bryan Thompson</a> - * @version $Id$ - */ -public class RDFLoadAndValidateHelper { - - final IBigdataFederation fed; - - final int nthreads; - - final int bufferCapacity; - - final ConcurrentDataLoader service; - - final File file; - - final FilenameFilter filter; - - final RDFParserOptions parserOptions; - - final RDFFormat fallback = RDFFormat.RDFXML; - - final int nclients; - - final int clientNum; - - public RDFLoadAndValidateHelper(IBigdataFederation fed, int nthreads, - int bufferCapacity, File file, FilenameFilter filter) { - - this(fed,nthreads,bufferCapacity,file, filter, 1/*nclients*/,0/*clientNum*/); - - } - - public RDFLoadAndValidateHelper(IBigdataFederation fed, int nthreads, - int bufferCapacity, File file, FilenameFilter filter, int nclients, - int clientNum) { - - this.fed = fed; - - this.nthreads = nthreads; - - this.bufferCapacity = bufferCapacity; - - service = new ConcurrentDataLoader(fed, nthreads); - - this.file = file; - - this.filter = filter; - - this.nclients = nclients; - - this.clientNum = clientNum; - - this.parserOptions = new RDFParserOptions(); - - parserOptions.setVerifyData(false); - - } - - public void load(final AbstractTripleStore db) throws InterruptedException { - - // Note: no write buffer for 'verify' since it is not doing any writes! - final RDFLoadTaskFactory loadTaskFactory = new RDFLoadTaskFactory(db, - bufferCapacity, parserOptions, false/* deleteAfter */, fallback); - - final FileSystemLoader scanner = new FileSystemLoader(service, - nclients, clientNum); - - /* - * Note: Add the counters to be reported to the client's counter - * set. The added counters will be reported when the client reports its - * own counters. - */ - final CounterSet serviceRoot = fed.getServiceCounterSet(); - - final String relPath = "Concurrent Data Loader"; - - synchronized (serviceRoot) { - - if (serviceRoot.getPath(relPath) == null) { - - // Create path to CDL counter set. - final CounterSet tmp = serviceRoot.makePath(relPath); - - // Attach CDL counters. - tmp.attach(service.getCounters()); - - // Attach task factory counters. - tmp.attach(loadTaskFactory.getCounters()); - - } - - } - - // notify will run tasks. - loadTaskFactory.notifyStart(); - - // read files and run tasks. - scanner.process(file, filter, loadTaskFactory); - - // await completion of all tasks. - service.awaitCompletion(Long.MAX_VALUE, TimeUnit.MILLISECONDS); - - // notify did run tasks. - loadTaskFactory.notifyEnd(); - - System.err.println(loadTaskFactory.reportTotals()); - - } - - public void validate(AbstractTripleStore db) throws InterruptedException { - - final RDFVerifyTaskFactory verifyTaskFactory = new RDFVerifyTaskFactory( - db, bufferCapacity, parserOptions, false/*deleteAfter*/, fallback); - - final FileSystemLoader scanner = new FileSystemLoader(service, - nclients, clientNum); - - // notify will run tasks. - verifyTaskFactory.notifyStart(); - - // read files and run tasks. - scanner.process(file, filter, verifyTaskFactory); - - // await completion of all tasks. - service.awaitCompletion(Long.MAX_VALUE, TimeUnit.MILLISECONDS); - - // notify did run tasks. - verifyTaskFactory.notifyEnd(); - - // Report on #terms and #stmts parsed, found, and not found - System.err.println(verifyTaskFactory.reportTotals()); - - } - - public void shutdownNow() { - - service.shutdownNow(); - - } - - protected void finalize() throws Throwable { - - service.shutdownNow(); - - } - -} Modified: branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServlet.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServlet.java 2011-04-15 14:02:24 UTC (rev 4402) +++ branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataRDFServlet.java 2011-04-15 16:24:17 UTC (rev 4403) @@ -252,6 +252,18 @@ } + /** + * Report a mutation count and elapsed time back to the user agent. + * + * @param resp + * The response. + * @param nmodified + * The mutation count. + * @param elapsed + * The elapsed time (milliseconds). + * + * @throws IOException + */ protected void reportModifiedCount(final HttpServletResponse resp, final long nmodified, final long elapsed) throws IOException { @@ -260,7 +272,7 @@ t.root("data").attr("modified", nmodified) .attr("milliseconds", elapsed).close(); - buildResponse(resp, HTTP_OK, MIME_TEXT_XML, t.toString()); + buildResponse(resp, HTTP_OK, MIME_APPLICATION_XML, t.toString()); } Modified: branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataServlet.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataServlet.java 2011-04-15 14:02:24 UTC (rev 4402) +++ branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/BigdataServlet.java 2011-04-15 16:24:17 UTC (rev 4403) @@ -6,6 +6,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.io.Writer; import javax.servlet.ServletContext; import javax.servlet.http.HttpServlet; @@ -49,22 +50,23 @@ * Some HTTP response status codes */ public static final transient int - HTTP_OK = HttpServletResponse.SC_ACCEPTED, - HTTP_REDIRECT = HttpServletResponse.SC_TEMPORARY_REDIRECT, - HTTP_FORBIDDEN = HttpServletResponse.SC_FORBIDDEN, - HTTP_NOTFOUND = HttpServletResponse.SC_NOT_FOUND, + HTTP_OK = HttpServletResponse.SC_OK, +// HTTP_ACCEPTED = HttpServletResponse.SC_ACCEPTED, +// HTTP_REDIRECT = HttpServletResponse.SC_TEMPORARY_REDIRECT, +// HTTP_FORBIDDEN = HttpServletResponse.SC_FORBIDDEN, +// HTTP_NOTFOUND = HttpServletResponse.SC_NOT_FOUND, HTTP_BADREQUEST = HttpServletResponse.SC_BAD_REQUEST, HTTP_METHOD_NOT_ALLOWED = HttpServletResponse.SC_METHOD_NOT_ALLOWED, HTTP_INTERNALERROR = HttpServletResponse.SC_INTERNAL_SERVER_ERROR, HTTP_NOTIMPLEMENTED = HttpServletResponse.SC_NOT_IMPLEMENTED; /** - * Common mime types for dynamic content + * Common MIME types for dynamic content. */ public static final transient String MIME_TEXT_PLAIN = "text/plain", MIME_TEXT_HTML = "text/html", - MIME_TEXT_XML = "text/xml", +// MIME_TEXT_XML = "text/xml", MIME_DEFAULT_BINARY = "application/octet-stream", MIME_APPLICATION_XML = "application/xml", MIME_TEXT_JAVASCRIPT = "text/javascript", @@ -92,8 +94,8 @@ } - static protected void buildResponse(HttpServletResponse resp, int status, - String mimeType) throws IOException { + static protected void buildResponse(final HttpServletResponse resp, + final int status, final String mimeType) throws IOException { resp.setStatus(status); @@ -101,22 +103,31 @@ } - static protected void buildResponse(HttpServletResponse resp, int status, - String mimeType, String content) throws IOException { + static protected void buildResponse(final HttpServletResponse resp, final int status, + final String mimeType, final String content) throws IOException { buildResponse(resp, status, mimeType); - resp.getWriter().print(content); + final Writer w = resp.getWriter(); + w.write(content); + + w.flush(); + } - static protected void buildResponse(HttpServletResponse resp, int status, - String mimeType, InputStream content) throws IOException { + static protected void buildResponse(final HttpServletResponse resp, + final int status, final String mimeType, final InputStream content) + throws IOException { buildResponse(resp, status, mimeType); - copyStream(content, resp.getOutputStream()); + final OutputStream os = resp.getOutputStream(); + copyStream(content, os); + + os.flush(); + } /** Modified: branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/DeleteServlet.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/DeleteServlet.java 2011-04-15 14:02:24 UTC (rev 4402) +++ branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/DeleteServlet.java 2011-04-15 16:24:17 UTC (rev 4403) @@ -121,7 +121,7 @@ namespace); /* - * FIXME The RDF for the *query* will be generated using the + * TODO The RDF for the *query* will be generated using the * MIME type negotiated based on the Accept header (if any) * in the DELETE request. That means that we need to look at * the Accept header here and chose the right RDFFormat for Added: branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/InsertServlet.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/InsertServlet.java (rev 0) +++ branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/InsertServlet.java 2011-04-15 16:24:17 UTC (rev 4403) @@ -0,0 +1,407 @@ +package com.bigdata.rdf.sail.webapp; + +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.util.Arrays; +import java.util.Vector; +import java.util.concurrent.atomic.AtomicLong; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.openrdf.model.Resource; +import org.openrdf.model.Statement; +import org.openrdf.rio.RDFFormat; +import org.openrdf.rio.RDFHandlerException; +import org.openrdf.rio.RDFParser; +import org.openrdf.rio.RDFParserFactory; +import org.openrdf.rio.RDFParserRegistry; +import org.openrdf.rio.helpers.RDFHandlerBase; +import org.openrdf.sail.SailException; + +import com.bigdata.rdf.sail.BigdataSailRepositoryConnection; +import com.bigdata.rdf.sail.BigdataSail.BigdataSailConnection; + +/** + * Handler for INSERT operations. + * + * @author martyncutcher + */ +public class InsertServlet extends BigdataRDFServlet { + + /** + * + */ + private static final long serialVersionUID = 1L; + + static private final transient Logger log = Logger.getLogger(InsertServlet.class); + + public InsertServlet() { + + } + + /** + * <p> + * Perform an HTTP-POST, which corresponds to the basic CRUD operation + * "create" according to the generic interaction semantics of HTTP REST. The + * operation will be executed against the target namespace per the URI. + * </p> + * + * <pre> + * POST [/namespace/NAMESPACE] + * ... + * Content-Type: + * ... + * + * BODY + * </pre> + * <p> + * Where <code>BODY</code> is the new RDF content using the representation + * indicated by the <code>Content-Type</code>. + * </p> + * <p> + * -OR- + * </p> + * + * <pre> + * POST [/namespace/NAMESPACE] ?uri=URL + * </pre> + * <p> + * Where <code>URI</code> identifies a resource whose RDF content will be + * inserted into the database. The <code>uri</code> query parameter may + * occur multiple times. All identified resources will be loaded within a + * single native transaction. Bigdata provides snapshot isolation so you can + * continue to execute queries against the last commit point while this + * operation is executed. + * </p> + */ + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) { + try { + if (req.getParameter("uri") != null) { + doPostWithURIs(req, resp); + return; + } else { + doPostWithBody(req, resp); + return; + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * POST with request body containing statements to be inserted. + * + * @param req + * The request. + * + * @return The response. + * + * @throws Exception + */ + private void doPostWithBody(final HttpServletRequest req, + final HttpServletResponse resp) throws Exception { + + final long begin = System.currentTimeMillis(); + + final String baseURI = "";// @todo baseURI query parameter? + + final String namespace = getNamespace(req.getRequestURI()); + + final String contentType = req.getContentType(); + + if (log.isInfoEnabled()) + log.info("Request body: " + contentType); + + final RDFFormat format = RDFFormat.forMIMEType(contentType); + + if (format == null) { + + buildResponse(resp, HTTP_BADREQUEST, MIME_TEXT_PLAIN, + "Content-Type not recognized as RDF: " + contentType); + + return; + + } + + if (log.isInfoEnabled()) + log.info("RDFFormat=" + format); + + final RDFParserFactory rdfParserFactory = RDFParserRegistry + .getInstance().get(format); + + if (rdfParserFactory == null) { + + buildResponse(resp, HTTP_INTERNALERROR, MIME_TEXT_PLAIN, + "Parser factory not found: Content-Type=" + + contentType + ", format=" + format); + + return; + + } + + try { + + final AtomicLong nmodified = new AtomicLong(0L); + + BigdataSailRepositoryConnection conn = null; + try { + + conn = getBigdataRDFContext() + .getUnisolatedConnection(namespace); + + /* + * There is a request body, so let's try and parse it. + */ + + final RDFParser rdfParser = rdfParserFactory.getParser(); + + rdfParser.setValueFactory(conn.getTripleStore() + .getValueFactory()); + + rdfParser.setVerifyData(true); + + rdfParser.setStopAtFirstError(true); + + rdfParser + .setDatatypeHandling(RDFParser.DatatypeHandling.IGNORE); + + rdfParser.setRDFHandler(new AddStatementHandler(conn + .getSailConnection(), nmodified)); + + /* + * Run the parser, which will cause statements to be inserted. + */ + rdfParser.parse(req.getInputStream(), baseURI); + + // Commit the mutation. + conn.commit(); + + final long elapsed = System.currentTimeMillis() - begin; + + reportModifiedCount(resp, nmodified.get(), elapsed); + + return; + + } finally { + + if (conn != null) + conn.close(); + + } + + } catch (Exception ex) { + + // Will be rendered as an INTERNAL_ERROR. + throw new RuntimeException(ex); + + } + + } + + /** + * POST with URIs of resources to be inserted (loads the referenced + * resources). + * + * @param req + * The request. + * + * @return The response. + * + * @throws Exception + */ + private void doPostWithURIs(final HttpServletRequest req, + final HttpServletResponse resp) throws Exception { + + final long begin = System.currentTimeMillis(); + + final String namespace = getNamespace(req.getRequestURI()); + + final String[] uris = req.getParameterValues("uri"); + + if (uris == null) + throw new UnsupportedOperationException(); + + if (uris.length == 0) { + + reportModifiedCount(resp, 0L/* nmodified */, System + .currentTimeMillis() + - begin); + + return; + + } + + if (log.isInfoEnabled()) + log.info("URIs: " + Arrays.toString(uris)); + + // Before we do anything, make sure we have valid URLs. + final Vector<URL> urls = new Vector<URL>(uris.length); + + for (String uri : uris) { + + urls.add(new URL(uri)); + + } + + try { + + final AtomicLong nmodified = new AtomicLong(0L); + + BigdataSailRepositoryConnection conn = null; + try { + + conn = getBigdataRDFContext().getUnisolatedConnection( + namespace); + + for (URL url : urls) { + + URLConnection hconn = null; + try { + + hconn = url.openConnection(); + if (hconn instanceof HttpURLConnection) { + ((HttpURLConnection) hconn).setRequestMethod("GET"); + } + hconn.setDoInput(true); + hconn.setDoOutput(false); + hconn.setReadTimeout(0);// no timeout? http param? + + /* + * There is a request body, so let's try and parse it. + */ + + final String contentType = hconn.getContentType(); + + final RDFFormat format = RDFFormat + .forMIMEType(contentType); + + if (format == null) { + buildResponse(resp, HTTP_BADREQUEST, + MIME_TEXT_PLAIN, + "Content-Type not recognized as RDF: " + + contentType); + + return; + } + + final RDFParserFactory rdfParserFactory = RDFParserRegistry + .getInstance().get(format); + + if (rdfParserFactory == null) { + buildResponse(resp, HTTP_INTERNALERROR, + MIME_TEXT_PLAIN, + "Parser not found: Content-Type=" + + contentType); + + return; + } + + final RDFParser rdfParser = rdfParserFactory + .getParser(); + + rdfParser.setValueFactory(conn.getTripleStore() + .getValueFactory()); + + rdfParser.setVerifyData(true); + + rdfParser.setStopAtFirstError(true); + + rdfParser + .setDatatypeHandling(RDFParser.DatatypeHandling.IGNORE); + + rdfParser.setRDFHandler(new AddStatementHandler(conn + .getSailConnection(), nmodified)); + + /* + * Run the parser, which will cause statements to be + * inserted. + */ + + rdfParser.parse(hconn.getInputStream(), url + .toExternalForm()/* baseURL */); + + } finally { + + if (hconn instanceof HttpURLConnection) { + /* + * Disconnect, but only after we have loaded all the + * URLs. Disconnect is optional for java.net. It is a + * hint that you will not be accessing more resources on + * the connected host. By disconnecting only after all + * resources have been loaded we are basically assuming + * that people are more likely to load from a single + * host. + */ + ((HttpURLConnection) hconn).disconnect(); + } + + } + + } // next URI. + + // Commit the mutation. + conn.commit(); + + final long elapsed = System.currentTimeMillis(); + + reportModifiedCount(resp, nmodified.get(), elapsed); + + } finally { + + if (conn != null) + conn.close(); + + } + + } catch (Exception ex) { + + // Will be rendered as an INTERNAL_ERROR. + throw new RuntimeException(ex); + + } + + } + + /** + * Helper class adds statements to the sail as they are visited by a parser. + */ + private static class AddStatementHandler extends RDFHandlerBase { + + private final BigdataSailConnection conn; + private final AtomicLong nmodified; + + public AddStatementHandler(final BigdataSailConnection conn, + final AtomicLong nmodified) { + this.conn = conn; + this.nmodified = nmodified; + } + + public void handleStatement(Statement stmt) throws RDFHandlerException { + + try { + + conn.addStatement(// + stmt.getSubject(), // + stmt.getPredicate(), // + stmt.getObject(), // + (Resource[]) (stmt.getContext() == null ? new Resource[] { } + : new Resource[] { stmt.getContext() })// + ); + + } catch (SailException e) { + + throw new RDFHandlerException(e); + + } + + nmodified.incrementAndGet(); + + } + + } + +} Property changes on: branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/InsertServlet.java ___________________________________________________________________ Added: svn:keywords + Id Date Revision Author HeadURL Modified: branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/RESTServlet.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/RESTServlet.java 2011-04-15 14:02:24 UTC (rev 4402) +++ branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/RESTServlet.java 2011-04-15 16:24:17 UTC (rev 4403) @@ -26,6 +26,7 @@ * The delegates to which we dispatch the various requests. */ private QueryServlet m_queryServlet; + private InsertServlet m_insertServlet; private DeleteServlet m_deleteServlet; private UpdateServlet m_updateServlet; @@ -42,10 +43,12 @@ super.init(); m_queryServlet = new QueryServlet(); + m_insertServlet = new InsertServlet(); m_updateServlet = new UpdateServlet(); m_deleteServlet = new DeleteServlet(); m_queryServlet.init(getServletConfig()); + m_insertServlet.init(getServletConfig()); m_updateServlet.init(getServletConfig()); m_deleteServlet.init(getServletConfig()); @@ -62,6 +65,11 @@ m_queryServlet = null; } + if (m_insertServlet != null) { + m_insertServlet.destroy(); + m_insertServlet = null; + } + if (m_updateServlet != null) { m_updateServlet.destroy(); m_updateServlet = null; @@ -87,34 +95,45 @@ } - /** - * A query can be submitted with a POST if a query parameter is provided. - * - * Otherwise delegate to the UpdateServlet - */ + /** + * A query can be submitted with a POST if a query parameter is provided. + * Otherwise delegate to the {@link InsertServlet} or {@link DeleteServlet} + * as appropriate. + */ @Override protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws IOException { if (req.getParameter("delete") != null) { + // DELETE via POST w/ Body. m_deleteServlet.doPost(req, resp); } else if (req.getParameter("query") != null) { - - m_queryServlet.doGet(req, resp); + + // QUERY via POST + m_queryServlet.doPost(req, resp); + + } else if(req.getParameter("uri") != null) { + + // INSERT via w/ URIs + m_insertServlet.doPost(req, resp); } else { - - m_updateServlet.doPut(req, resp); + + // INSERT via POST w/ Body + m_insertServlet.doPost(req, resp); } } - - /** - * A PUT request always delegates to the UpdateServlet - */ + + /** + * A PUT request always delegates to the {@link UpdateServlet}. + * <p> + * Note: The semantics of PUT are "DELETE+INSERT" for the API. PUT is not + * support for just "INSERT". Use POST instead for that purpose. + */ @Override protected void doPut(final HttpServletRequest req, final HttpServletResponse resp) throws IOException { @@ -124,10 +143,7 @@ } /** - * A DELETE request will delete statements indicated by a provided namespace - * URI and an optional query parameter. - * - * Delegate to the DeleteServlet. + * Delegate to the {@link DeleteServlet}. */ @Override protected void doDelete(final HttpServletRequest req, Modified: branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/UpdateServlet.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/UpdateServlet.java 2011-04-15 14:02:24 UTC (rev 4402) +++ branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/webapp/UpdateServlet.java 2011-04-15 16:24:17 UTC (rev 4403) @@ -1,413 +1,35 @@ package com.bigdata.rdf.sail.webapp; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.Arrays; -import java.util.Vector; -import java.util.concurrent.atomic.AtomicLong; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; -import org.openrdf.model.Resource; -import org.openrdf.model.Statement; -import org.openrdf.rio.RDFFormat; -import org.openrdf.rio.RDFHandlerException; -import org.openrdf.rio.RDFParser; -import org.openrdf.rio.RDFParserFactory; -import org.openrdf.rio.RDFParserRegistry; -import org.openrdf.rio.helpers.RDFHandlerBase; -import org.openrdf.sail.SailException; -import com.bigdata.rdf.sail.BigdataSailRepositoryConnection; -import com.bigdata.rdf.sail.BigdataSail.BigdataSailConnection; - /** - * Handler for update (POST + * Handler for UPDATE operations (PUT). * * @author martyncutcher + * + * FIXME The UPDATE API is not finished yet. It will provide + * DELETE+INSERT semantics. */ public class UpdateServlet extends BigdataRDFServlet { - + /** * */ private static final long serialVersionUID = 1L; - - static private final transient Logger log = Logger.getLogger(UpdateServlet.class); + static private final transient Logger log = Logger + .getLogger(UpdateServlet.class); + public UpdateServlet() { - + } - /** - * <p> - * Perform an HTTP-POST, which corresponds to the basic CRUD operation - * "create" according to the generic interaction semantics of HTTP REST. The - * operation will be executed against the target namespace per the URI. - * </p> - * - * <pre> - * POST [/namespace/NAMESPACE] - * ... - * Content-Type: - * ... - * - * BODY - * </pre> - * <p> - * Where <code>BODY</code> is the new RDF content using the representation - * indicated by the <code>Content-Type</code>. - * </p> - * <p> - * -OR- - * </p> - * - * <pre> - * POST [/namespace/NAMESPACE] ?uri=URL - * </pre> - * <p> - * Where <code>URI</code> identifies a resource whose RDF content will be - * inserted into the database. The <code>uri</code> query parameter may - * occur multiple times. All identified resources will be loaded within a - * single native transaction. Bigdata provides snapshot isolation so you can - * continue to execute queries against the last commit point while this - * operation is executed. - * </p> - */ @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) { - try { - if (req.getParameter("uri") != null) { - doPostWithURIs(req, resp); - return; - } else { - doPostWithBody(req, resp); - return; - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Override - protected void doPut(HttpServletRequest req, HttpServletResponse resp) { - try { - doPostWithBody(req, resp); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) { - try { - buildResponse(resp, HTTP_METHOD_NOT_ALLOWED, MIME_TEXT_PLAIN, - "GET method not valid for update"); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - /** - * POST with request body containing statements to be inserted. - * - * @param req - * The request. - * - * @return The response. - * - * @throws Exception - */ - private void doPostWithBody(final HttpServletRequest req, - final HttpServletResponse resp) throws Exception { - - final long begin = System.currentTimeMillis(); - - final String baseURI = "";// @todo baseURI query parameter? - - final String namespace = getNamespace(req.getRequestURI()); - - final String contentType = req.getContentType(); - - if (log.isInfoEnabled()) - log.info("Request body: " + contentType); - - final RDFFormat format = RDFFormat.forMIMEType(contentType); - - if (format == null) { - - buildResponse(resp, HTTP_BADREQUEST, MIME_TEXT_PLAIN, - "Content-Type not recognized as RDF: " + contentType); - - return; - - } - - if (log.isInfoEnabled()) - log.info("RDFFormat=" + format); - - final RDFParserFactory rdfParserFactory = RDFParserRegistry - .getInstance().get(format); - - if (rdfParserFactory == null) { - - buildResponse(resp, HTTP_INTERNALERROR, MIME_TEXT_PLAIN, - "Parser factory not found: Content-Type=" - + contentType + ", format=" + format); - - return; - - } - - try { - - final AtomicLong nmodified = new AtomicLong(0L); - - BigdataSailRepositoryConnection conn = null; - try { - - conn = getBigdataRDFContext() - .getUnisolatedConnection(namespace); - - /* - * There is a request body, so let's try and parse it. - */ - - final RDFParser rdfParser = rdfParserFactory.getParser(); - - rdfParser.setValueFactory(conn.getTripleStore() - .getValueFactory()); - - rdfParser.setVerifyData(true); - - rdfParser.setStopAtFirstError(true); - - rdfParser - .setDatatypeHandling(RDFParser.DatatypeHandling.IGNORE); - - rdfParser.setRDFHandler(new AddStatementHandler(conn - .getSailConnection(), nmodified)); - - /* - * Run the parser, which will cause statements to be inserted. - */ - rdfParser.parse(req.getInputStream(), baseURI); - - // Commit the mutation. - conn.commit(); - - final long elapsed = System.currentTimeMillis() - begin; - - reportModifiedCount(resp, nmodified.get(), elapsed); - - return; - - } finally { - - if (conn != null) - conn.close(); - - } - - } catch (Exception ex) { - - // Will be rendered as an INTERNAL_ERROR. - throw new RuntimeException(ex); - - } - + protected void doPut(HttpServletRequest req, HttpServletResponse resp) { + throw new UnsupportedOperationException(); } - /** - * POST with URIs of resources to be inserted (loads the referenced - * resources). - * - * @param req - * The request. - * - * @return The response. - * - * @throws Exception - */ - private void doPostWithURIs(final HttpServletRequest req, - final HttpServletResponse resp) throws Exception { - - final long begin = System.currentTimeMillis(); - - final String namespace = getNamespace(req.getRequestURI()); - - final String contentType = req.getContentType(); - - final String[] uris = req.getParameterValues("uri"); - - if (uris == null) - throw new UnsupportedOperationException(); - - if (uris.length == 0) { - - reportModifiedCount(resp, 0L/* nmodified */, System - .currentTimeMillis() - - begin); - - return; - - } - - if (log.isInfoEnabled()) - log.info("URIs: " + Arrays.toString(uris)); - - // Before we do anything, make sure we have valid URLs. - final Vector<URL> urls = new Vector<URL>(uris.length); - - for (String uri : uris) { - - urls.add(new URL(uri)); - - } - - try { - - final AtomicLong nmodified = new AtomicLong(0L); - - BigdataSailRepositoryConnection conn = null; - try { - - conn = getBigdataRDFContext().getUnisolatedConnection( - namespace); - - for (URL url : urls) { - - HttpURLConnection hconn = null; - try { - - hconn = (HttpURLConnection) url.openConnection(); - hconn.setRequestMethod("GET"); - hconn.setReadTimeout(0);// no timeout? http param? - - /* - * There is a request body, so let's try and parse it. - */ - - final RDFFormat format = RDFFormat - .forMIMEType(contentType); - - if (format == null) { - buildResponse(resp, HTTP_BADREQUEST, - MIME_TEXT_PLAIN, - "Content-Type not recognized as RDF: " - + contentType); - - return; - } - - final RDFParserFactory rdfParserFactory = RDFParserRegistry - .getInstance().get(format); - - if (rdfParserFactory == null) { - buildResponse(resp, HTTP_INTERNALERROR, - MIME_TEXT_PLAIN, - "Parser not found: Content-Type=" - + contentType); - - return; - } - - final RDFParser rdfParser = rdfParserFactory - .getParser(); - - rdfParser.setValueFactory(conn.getTripleStore() - .getValueFactory()); - - rdfParser.setVerifyData(true); - - rdfParser.setStopAtFirstError(true); - - rdfParser - .setDatatypeHandling(RDFParser.DatatypeHandling.IGNORE); - - rdfParser.setRDFHandler(new AddStatementHandler(conn - .getSailConnection(), nmodified)); - - /* - * Run the parser, which will cause statements to be - * inserted. - */ - - rdfParser.parse(req.getInputStream(), url - .toExternalForm()/* baseURL */); - - } finally { - - if (hconn != null) - hconn.disconnect(); - - } // next URI. - - } - - // Commit the mutation. - conn.commit(); - - final long elapsed = System.currentTimeMillis(); - - reportModifiedCount(resp, nmodified.get(), elapsed); - - } finally { - - if (conn != null) - conn.close(); - - } - - } catch (Exception ex) { - - // Will be rendered as an INTERNAL_ERROR. - throw new RuntimeException(ex); - - } - - } - - /** - * Helper class adds statements to the sail as they are visited by a parser. - */ - private static class AddStatementHandler extends RDFHandlerBase { - - private final BigdataSailConnection conn; - private final AtomicLong nmodified; - - public AddStatementHandler(final BigdataSailConnection conn, - final AtomicLong nmodified) { - this.conn = conn; - this.nmodified = nmodified; - } - - public void handleStatement(Statement stmt) throws RDFHandlerException { - - try { - - conn.addStatement(// - stmt.getSubject(), // - stmt.getPredicate(), // - stmt.getObject(), // - (Resource[]) (stmt.getContext() == null ? new Resource[] { } - : new Resource[] { stmt.getContext() })// - ); - - } catch (SailException e) { - - throw new RDFHandlerException(e); - - } - - nmodified.incrementAndGet(); - - } - - } - - } Modified: branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/TestNanoSparqlServer.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/TestNanoSparqlServer.java 2011-04-15 14:02:24 UTC (rev 4402) +++ branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/webapp/TestNanoSparqlServer.java 2011-04-15 16:24:17 UTC (rev 4403) @@ -16,6 +16,9 @@ import java.util.Properties; import java.util.concurrent.atomic.AtomicLong; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + import junit.framework.TestCase2; import org.eclipse.jetty.server.Server; @@ -50,6 +53,8 @@ import org.openrdf.rio.RDFWriterFactory; import org.openrdf.rio.RDFWriterRegistry; import org.openrdf.rio.helpers.StatementCollector; +import org.xml.sax.Attributes; +import org.xml.sax.ext.DefaultHandler2; import com.bigdata.journal.BufferMode; import com.bigdata.journal.ITx; @@ -78,10 +83,13 @@ * writer, but not a parser) before we can test queries which CONNEG for a * JSON result set. * + * @todo Add tests for TRIPLES mode (the tests are running against a quads mode + * KB instance). + * * @todo Add tests for SIDS mode interchange of RDF XML. * - * @todo The methods which return a mutation count should verify the returned - * XML document. + * @todo Tests which verify the correct rejection of illegal or ill-formed + * requests. * * @todo Test suite for reading from a historical commit point. * @@ -95,7 +103,10 @@ private Server m_fixture; private String m_serviceURL; - final private static String requestPath = ""; + /** + * The request path for the REST API under test. + */ + final private static String requestPath = "/"; protected void setUp() throws Exception { @@ -105,24 +116,24 @@ m_jnl = new Journal(properties); - // Create the kb instance. - new LocalTripleStore(m_jnl, namespace, ITx.UNISOLATED, properties).create(); + // Create the kb instance. + new LocalTripleStore(m_jnl, namespace, ITx.UNISOLATED, properties) + .create(); -// /* -// * Service will not hold a read lock. -// * -// * Queries will read from the last commit point by default and will use -// * a read-only tx to have snapshot isolation for that query. -// */ -// config.timestamp = ITx.READ_COMMITTED; + // /* + // * Service will not hold a read lock. + // * + // * Queries will read from the last commit point by default and will + // use + // * a read-only tx to have snapshot isolation for that query. + // */ + // config.timestamp = ITx.READ_COMMITTED; final Map<String, String> initParams = new LinkedHashMap<String, String>(); { - - initParams.put( - ConfigParams.NAMESPACE, - namespace); - + + initParams.put(ConfigParams.NAMESPACE, namespace); + } // Start server for that kb instance. m_fixture = NanoSparqlServer @@ -130,7 +141,6 @@ m_fixture.start(); -// final int port = m_fixture.getPort(); final int port = m_fixture.getConnectors()[0].getLocalPort(); // log.info("Getting host address"); @@ -238,17 +248,17 @@ */ private static class QueryOptions { - /** The default timeout (ms). */ - private static final int DEFAULT_TIMEOUT = 2000; - /** The URL of the SPARQL endpoint. */ public String serviceURL = null; /** The HTTP method (GET, POST, etc). */ public String method = "GET"; - /** The SPARQL query. */ + /** + * The SPARQL query (this is a short hand for setting the + * <code>query</code> URL query parameter). + */ public String queryStr = null; - /** TODO DG and NG protocol params: The default graph URI (optional). */ - public String defaultGraphUri = null; + /** Request parameters to be formatted as URL query parameters. */ + public Map<String,String[]> requestParams; /** The accept header. */ public String acceptHeader = // BigdataRDFServlet.MIME_SPARQL_RESULTS_XML + ";q=1" + // @@ -281,26 +291,65 @@ * * @param opts * The query request. + * @param requestPath + * The request path, including the leading "/". * * @return The connection. */ protected HttpURLConnection doSparqlQuery(final QueryOptions opts, - final String servlet) throws Exception { + final String requestPath) throws Exception { - // Fully formed and encoded URL. - final String urlString = opts.serviceURL - + "/" - + servlet - + "?query=" - + URLEncoder.encode(opts.queryStr, "UTF-8") - + (opts.defaultGraphUri == null ? "" - : ("&default-graph-uri=" + URLEncoder.encode( - opts.defaultGraphUri, "UTF-8"))); + /* + * Generate the fully formed and encoded URL. + */ + final StringBuilder urlString = new StringBuilder(opts.serviceURL); + + urlString.append(requestPath); + + if (opts.queryStr != null) { + + if (opts.requestParams == null) { + + opts.requestParams = new LinkedHashMap<String, String[]>(); + + } + + opts.requestParams.put("query", new String[] { opts.queryStr }); + + } + + if (opts.requestParams != null) { + /* + * Add any URL query parameters. + */ + boolean first = true; + for (Map.Entry<String, String[]> e : opts.requestParams.entrySet()) { + urlString.append(first ? "?" : "&"); + first = false; + final String name = e.getKey(); + final String[] vals = e.getValue(); + if (vals == null) { + urlString.append(URLEncoder.encode(name, "UTF-8")); + } else { + for (String val : vals) { + urlString.append(URLEncoder.encode(name, "UTF-8")); + urlString.append("="); + urlString.append(URLEncoder.encode(val, "UTF-8")); + } + } + } // next Map.Entry +// + "?query=" +// + URLEncoder.encode(opts.queryStr, "UTF-8") +// + (opts.defaultGraphUri == null ? "" +// : ("&default-graph-uri=" + URLEncoder.encode( +// opts.defaultGraphUri, "UTF-8"))); + } + HttpURLConnection conn = null; try { - conn = doConnect(urlString, opts.method); + conn = doConnect(urlString.toString(), opts.method); conn.setReadTimeout(opts.timeout); @@ -521,7 +570,83 @@ } - /** + /** + * Class representing the result of a mutation operation against the REST + * API. + * + * TODO Refactor into the non-test code base? + */ + private static class MutationResult { + + /** The mutation count. */ + public final long mutationCount; + + /** The elapsed time for the operation. */ + public final long elapsedMillis; + + public MutationResult(final long mutationCount, final long elapsedMillis) { + this.mutationCount = mutationCount; + this.elapsedMillis = elapsedMillis; + } + + } + + protected MutationResult getMutationResult(final HttpURLConnection conn) throws Exception { + + try { + + final String contentType = conn.getContentType(); + + if (!contentType.startsWith(BigdataRDFServlet.MIME_APPLICATION_XML)) { + + fail("Expecting Content-Type of " + + BigdataRDFServlet.MIME_APPLICATION_XML + ", not " + + contentType); + + } + + final SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); + + final AtomicLong mutationCount = new AtomicLong(); + final AtomicLong elapsedMillis = new AtomicLong(); + + /* + * For example: <data modified="5" milliseconds="112"/> + */ + parser.parse(conn.getInputStream(), new DefaultHandler2(){ + + public void startElement(final String uri, + final String localName, final String qName, + final Attributes attributes) { + + if (!"data".equals(qName)) + fail("Expecting: 'data', but have: uri=" + uri + + ", localName=" + localName + ", qName=" + + qName); + + mutationCount.set(Long.valueOf(attributes + .getValue("modified"))); + + elapsedMillis.set(Long.valueOf(attributes + .getValue("milliseconds"))); + + } + + }); + + // done. + return new MutationResult(mutationCount.get(), elapsedMillis.get()); + + } finally { + + // terminate the http connection. + conn.disconnect(); + + } + + } + + /** * Issue a "status" request against the service. */ public void test_STATUS() throws Exception { @@ -572,6 +697,61 @@ } /** + * Generates some statements and serializes them using the specified + * {@link RDFFormat}. + * + * @param ntriples + * The #of statements to generate. + * @param format + * The format. + * + * @return the serialized statements. + */ + private byte[] genNTRIPLES(final int ntriples, final RDFFormat format) + throws RDFHandlerException { + + final Graph g = new GraphImpl(); + + final ValueFactory f = new ValueFactoryImpl(); + + final URI s = f.createURI("http://www.bigdata.org/b"); + + final URI rdfType = f + .createURI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); + + for (int i = 0; i < ntriples; i++) { + + final URI o = f.createURI("http://www.bigdata.org/c#" + i); + + g.add(s, rdfType, o); + + } + + final RDFWriterFactory writerFactory = RDFWriterRegistry.getInstance() + .get(format); + + if (writerFactory == null) + fail("RDFWriterFactory not found: format=" + format); + + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + final RDFWriter writer = writerFactory.getWriter(baos); + + writer.startRDF(); + + for (Statement stmt : g) { + + writer.handleStatement(stmt); + + } + + writer.endRDF(); + + return baos.toByteArray(); + + } + + /** * "ASK" query using GET with an empty KB. */ public void test_GET_ASK() throws Exception { @@ -661,80 +841,104 @@ } - public void test_POST_UPDATE_withBody_RDFXML() throws Exception { + public void test_POST_INSERT_withBody_RDFXML() throws Exception { - do_UPDATE_withBody("POST", 23, requestPath, RDFFormat.RDFXML); + doInsertWithBodyTest("POST", 23, requestPath, RDFFormat.RDFXML); } - public void test_POST_UPDATE_withBody_NTRIPLES() throws Exception { + public void test_POST_INSERT_withBody_NTRIPLES() throws Exception { - do_UPDATE_withBody("POST", 23, requestPath, RDFFormat.NTRIPLES); + doInsertWithBodyTest("POST", 23, requestPath, RDFFormat.NTRIPLES); } - public void test_POST_UPDATE_withBody_N3() throws Exception { + public void test_POST_INSERT_withBody_N3() throws Exception { - do_UPDATE_withBody("POST", 23, requestPath, RDFFormat.N3); + doInsertWithBodyTest("POST", 23, requestPath, RDFFormat.N3); } - public void test_POST_UPDATE_withBody_TURTLE() throws Exception { + public void test_POST_INSERT_withBody_TURTLE() throws Exception { - do_UPDATE_withBody("POST", 23, requestPath, RDFFormat.TURTLE); + doInsertWithBodyTest("POST", 23, requestPath, RDFFormat.TURTLE); } // Note: quads interchange - public void test_POST_UPDATE_withBody_TRIG() throws Exception { + public void test_POST_INSERT_withBody_TRIG() throws Exception { - do_UPDATE_withBody("POST", 23, requestPath, RDFFormat.TRIG); + doInsertWithBodyTest("POST", 23, requestPath, RDFFormat.TRIG); } // Note: quads interchange - public void test_POST_UPDATE_withBody_TRIX() throws Exception { + public void test_POST_INSERT_withBody_TRIX() throws Exception { - do_UPDATE_withBody("POST", 23, requestPath, RDFFormat.TRIX); + doInsertWithBodyTest("POST", 23, requestPath, RDFFormat.TRIX); } - public void test_PUT_UPDATE_withBody_RDFXML() throws Exception { + /** + * Test ability to load data from a URI. + */ + public void test_POST_INSERT_LOAD_FROM_URIs() throws Exception { - do_UPDATE_withBody("PUT", 23, requestPath, RDFFormat.RDFXML); + // Verify nothing in the KB. + { + final String queryStr = "ASK where {?s ?p ?o}"; - } + final QueryOptions opts = new QueryOptions(); + opts.serviceURL = m_serviceURL; + opts.queryStr = queryStr; + opts.method = "GET"; - public void test_PUT_UPDATE_withBody_NTRIPLES() throws Exception { + opts.acceptHeader = BooleanQueryResultFormat.SPARQL + .getDefaultMIMEType(); + assertEquals(false, askResults(doSparqlQuery(opts, requestPath))); + } - do_UPDATE_withBody("PUT", 23, requestPath, RDFFormat.NTRIPLES); + // #of statements in that RDF file. + final long expectedStatementCount = 4; + + // Load the resource into the KB. + { + final QueryOptions opts = new QueryOptions(); + opts.serviceURL = m_serviceURL; + opts.method = "POST"; + opts.requestParams = new LinkedHashMap<String, String[]>(); + opts.requestParams + .put( + "uri", + new String[] { "file:bigdata-rdf/src/test/com/bigdata/rdf/rio/small.rdf" }); - } + final MutationResult result = getMutationResult(doSparqlQuery(opts, + requestPath)); - public void test_PUT_UPDATE_withBody_N3() throws Exception { + assertEquals(expectedStatementCount, result.mutationCount); - do_UPDATE_withBody("PUT", 23, requestPath, RDFFormat.N3); + } - } + /* + * Verify KB has the loaded data. + */ + { + final String queryStr = "SELECT * where {?s ?p ?o}"; - public void test_PUT_UPDATE_withBody_TURTLE() throws Exception { + final QueryOptions opts = new QueryOptions(); + opts.serviceURL = m_serviceURL; + opts.queryStr = queryStr; + opts.method = "GET"; - do_UPDATE_withBody("PUT", 23, requestPath, RDFFormat.TURTLE); + opts.acceptHeader = BooleanQueryResultFormat.SPARQL + .getDefaultMIMEType(); - } + assertEquals(expectedStatementCount, countResults(doSparqlQuery( + opts, requestPath))); + } - public void test_PUT_UPDATE_withBody_TRIG() throws Exception { - - do_UPDATE_withBody("PUT", 23, requestPath, RDFFormat.TRIG); - } - public void test_PUT_UPDATE_withBody_TRIX() throws Exception { - - do_UPDATE_withBody("PUT", 23, requestPath, RDFFormat.TRIX); - - } - /** * Select everything in the kb using a POST. */ @@ -747,11 +951,11 @@ opts.queryStr = queryStr; opts.method = "POST"; - do_UPDATE_withBody("POST", 23, requestPath, RDFFormat.NTRIPLES); + doInsertWithBodyTest("POST", 23, requestPath, RDFFormat.NTRIPLES); assertEquals(23, countResults(doSparqlQuery(opts, requestPath))); - do_DELETE_with_Query(requestPath, "construct {?s ?p ?o} where {?s ?p ?o}"); + doDeleteWit... [truncated message content] |