http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/DataValidator.java
----------------------------------------------------------------------
diff --git 
a/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/DataValidator.java
 
b/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/DataValidator.java
new file mode 100644
index 0000000..6105562
--- /dev/null
+++ 
b/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/DataValidator.java
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki.validation;
+
+import static org.apache.jena.riot.SysRIOT.fmtMessage ;
+
+import java.io.IOException ;
+import java.io.PrintStream ;
+import java.io.Reader ;
+import java.io.StringReader ;
+
+import javax.servlet.ServletOutputStream ;
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.atlas.io.IO ;
+import org.apache.jena.atlas.lib.Sink ;
+import org.apache.jena.fuseki.FusekiLib ;
+import org.apache.jena.riot.Lang ;
+import org.apache.jena.riot.RDFLanguages ;
+import org.apache.jena.riot.RiotException ;
+import org.apache.jena.riot.RiotReader ;
+import org.apache.jena.riot.lang.LangRIOT ;
+import org.apache.jena.riot.system.ErrorHandler ;
+import org.apache.jena.riot.system.RiotLib ;
+import org.apache.jena.riot.system.StreamRDF ;
+import org.apache.jena.riot.system.StreamRDFLib ;
+import org.apache.jena.riot.tokens.Tokenizer ;
+import org.apache.jena.riot.tokens.TokenizerFactory ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.sparql.core.Quad ;
+import com.hp.hpl.jena.sparql.serializer.SerializationContext ;
+import com.hp.hpl.jena.sparql.util.FmtUtils ;
+
+public class DataValidator extends ValidatorBase
+{
+    public DataValidator() 
+    { }
+  
+    static final String paramLineNumbers      = "linenumbers" ;
+    static final String paramFormat           = "outputFormat" ;
+    static final String paramIndirection      = "url" ;
+    static final String paramData             = "data" ;
+    static final String paramSyntax           = "languageSyntax" ;
+    //static final String paramSyntaxExtended   = "extendedSyntax" ;
+    
+    @Override
+    protected void execute(HttpServletRequest httpRequest, HttpServletResponse 
httpResponse)
+    {
+        try {
+//            if ( log.isInfoEnabled() )
+//                log.info("data validation request") ;
+            
+            Tokenizer tokenizer = createTokenizer(httpRequest, httpResponse) ;
+            if ( tokenizer == null )
+                return ;
+            
+            String syntax = FusekiLib.safeParameter(httpRequest, paramSyntax) ;
+            if ( syntax == null || syntax.equals("") )
+                syntax = RDFLanguages.NQUADS.getName() ;
+
+            Lang language = RDFLanguages.shortnameToLang(syntax) ;
+            if ( language == null )
+            {
+                httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, 
"Unknown syntax: "+syntax) ;
+                return ;
+            }
+
+            ServletOutputStream outStream = httpResponse.getOutputStream() ;
+            ErrorHandlerMsg errorHandler = new ErrorHandlerMsg(outStream) ;
+            
+            PrintStream stdout = System.out ;
+            PrintStream stderr = System.err ;
+            System.setOut(new PrintStream(outStream)) ;
+            System.setErr(new PrintStream(outStream)) ;
+
+            // Headers
+            setHeaders(httpResponse) ;
+
+            outStream.println("<html>") ;
+            printHead(outStream, "Jena Data Validator Report") ;
+            outStream.println("<body>") ;
+            
+            outStream.println("<h1>RIOT Parser Report</h1>") ;
+            outStream.println("<p>Line and column numbers refer to original 
input</p>") ;
+            outStream.println("<p>&nbsp;</p>") ;
+            try {
+                LangRIOT parser = setupParser(tokenizer, language, 
errorHandler, outStream) ;
+                startFixed(outStream) ;
+                RiotException exception = null ;
+                try {
+                    parser.parse() ;
+                    System.out.flush() ;
+                    System.err.flush() ;
+                } catch (RiotException ex) { exception = ex ; }
+            } finally 
+            {
+                finishFixed(outStream) ;
+                System.out.flush() ;
+                System.err.flush() ;
+                System.setOut(stdout) ;
+                System.setErr(stdout) ;
+            }
+            
+            outStream.println("</body>") ;
+            outStream.println("</html>") ;
+        } catch (Exception ex)
+        {
+            serviceLog.warn("Exception in validationRequest",ex) ;
+        }
+    }
+    
+    static final long LIMIT = 50000 ;
+    
+    
+    private LangRIOT setupParser(Tokenizer tokenizer, Lang language, 
ErrorHandler errorHandler, final ServletOutputStream outStream)
+    {
+        Sink<Quad> sink = new Sink<Quad>()
+        {
+            SerializationContext sCxt = new SerializationContext() ;
+            @Override
+            public void send(Quad quad)
+            {
+                // Clean up!
+                StringBuilder sb = new StringBuilder() ;
+
+                sb.append(formatNode(quad.getSubject())) ;
+                sb.append("  ") ;
+                sb.append(formatNode(quad.getPredicate())) ;
+                sb.append("  ") ;
+                sb.append(formatNode(quad.getObject())) ;
+                
+                if ( ! quad.isTriple() )
+                {
+                    sb.append("  ") ;
+                    sb.append(formatNode(quad.getGraph())) ;
+                }
+
+                String $ = htmlQuote(sb.toString()) ;
+                try { 
+                    outStream.print($) ;
+                    outStream.println(" .") ;
+                } catch (IOException ex) { IO.exception(ex) ; }
+            }
+            @Override
+            public void close() {}
+            @Override
+            public void flush() {}
+            String formatNode(Node n) { return FmtUtils.stringForNode(n, sCxt) 
; }
+        } ;
+
+        StreamRDF dest = StreamRDFLib.sinkQuads(sink) ;
+        @SuppressWarnings("deprecation")
+        LangRIOT parser = RiotReader.createParser(tokenizer, language, null, 
dest) ;
+        // Don't resolve IRIs.  Do checking.
+        parser.setProfile(RiotLib.profile(null, false, true, errorHandler)) ;
+        return parser ;
+    }
+
+    // Error handler that records messages
+    private static class ErrorHandlerMsg implements ErrorHandler
+    {
+        private ServletOutputStream out ;
+
+        ErrorHandlerMsg(ServletOutputStream out) { this.out = out ; }
+        
+        @Override
+        public void warning(String message, long line, long col)
+        { output(message, line, col, "Warning", "warning") ; }
+    
+        // Attempt to continue.
+        @Override
+        public void error(String message, long line, long col)
+        { output(message, line, col, "Error", "error") ; }
+    
+        @Override
+        public void fatal(String message, long line, long col)
+        { output(message, line, col, "Fatal", "error") ; throw new 
RiotException(fmtMessage(message, line, col)) ; }
+        
+        private void output(String message, long line, long col, String 
typeName, String className)
+        {
+            try {
+                String str = fmtMessage(message, line, col) ;
+                //String str = typeName+": "+message ;
+                str = htmlQuote(str) ;
+                out.print("<div class=\""+className+"\">") ;
+                out.print(str) ;
+                out.print("</div>") ;
+            } catch (IOException ex) { IO.exception(ex) ; }
+        }
+    }
+    
+    private Tokenizer createTokenizer(HttpServletRequest httpRequest, 
HttpServletResponse httpResponse) throws Exception
+    {
+        Reader reader = null ;  
+        String[] args = httpRequest.getParameterValues(paramData) ;
+        if ( args == null || args.length == 0 )
+        {
+            // Not a form?
+            reader = httpRequest.getReader() ;
+        }
+        else if ( args.length > 1 )
+        {
+            httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, "Too 
many parameters for '"+paramData+"='") ;
+            return null ;
+        }
+        else
+        {
+            reader = new StringReader(args[0]) ;
+        }
+        
+        if ( reader == null )
+        {
+            httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, "Can't 
find data to validate") ;
+            return null ;
+        }
+        
+        return TokenizerFactory.makeTokenizer(reader) ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/IRIValidator.java
----------------------------------------------------------------------
diff --git 
a/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/IRIValidator.java 
b/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/IRIValidator.java
new file mode 100644
index 0000000..2972b49
--- /dev/null
+++ 
b/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/IRIValidator.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki.validation;
+
+import java.io.IOException ;
+import java.io.PrintStream ;
+import java.util.Iterator ;
+
+import javax.servlet.ServletOutputStream ;
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.iri.IRI ;
+import org.apache.jena.iri.IRIFactory ;
+import org.apache.jena.iri.Violation ;
+import org.apache.jena.riot.system.IRIResolver ;
+
+public class IRIValidator extends ValidatorBase
+{
+    public IRIValidator() 
+    { }
+  
+    static final String paramIRI      = "iri" ;
+    //static IRIFactory iriFactory = IRIFactory.iriImplementation() ;
+    static IRIFactory iriFactory = IRIResolver.iriFactory ;
+    
+    @Override
+    protected void execute(HttpServletRequest httpRequest, HttpServletResponse 
httpResponse)
+    {
+        try {
+            String[] args = httpRequest.getParameterValues(paramIRI) ;
+            ServletOutputStream outStream = httpResponse.getOutputStream() ;
+            PrintStream stdout = System.out ;
+            PrintStream stderr = System.err ;
+            System.setOut(new PrintStream(outStream)) ;
+            System.setErr(new PrintStream(outStream)) ;
+
+            setHeaders(httpResponse) ;
+
+            outStream.println("<html>") ;
+            printHead(outStream, "Jena IRI Validator Report") ;
+            outStream.println("<body>") ;
+
+            outStream.println("<h1>IRI Report</h1>") ;
+
+            startFixed(outStream) ;
+
+            try {
+                boolean first = true ;
+                for ( String iriStr : args )
+                {
+                    if ( ! first )
+                        System.out.println() ;
+                    first = false ;
+
+                    IRI iri = iriFactory.create(iriStr) ;
+                    System.out.println(iriStr + " ==> "+iri) ;
+                    if ( iri.isRelative() )
+                        System.out.println("Relative IRI: "+iriStr) ;
+
+                    Iterator<Violation> vIter = iri.violations(true) ;
+                    for ( ; vIter.hasNext() ; )
+                    {
+                        String str = vIter.next().getShortMessage() ;
+                        str = htmlQuote(str) ;
+                        
+                        System.out.println(str) ;
+                    }
+                }
+            } finally 
+            {
+                finishFixed(outStream) ;
+                System.out.flush() ;
+                System.err.flush() ;
+                System.setOut(stdout) ;
+                System.setErr(stdout) ;
+            }
+
+            outStream.println("</body>") ;
+            outStream.println("</html>") ;
+        } catch (IOException ex) {}
+    } 
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/QueryValidator.java
----------------------------------------------------------------------
diff --git 
a/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/QueryValidator.java
 
b/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/QueryValidator.java
new file mode 100644
index 0000000..75ad901
--- /dev/null
+++ 
b/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/QueryValidator.java
@@ -0,0 +1,269 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki.validation;
+
+import java.io.IOException ;
+
+import javax.servlet.ServletOutputStream ;
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.atlas.io.IndentedLineBuffer ;
+import org.apache.jena.atlas.io.IndentedWriter ;
+
+import com.hp.hpl.jena.query.Query ;
+import com.hp.hpl.jena.query.QueryFactory ;
+import com.hp.hpl.jena.query.Syntax ;
+import com.hp.hpl.jena.sparql.ARQException ;
+import com.hp.hpl.jena.sparql.algebra.Algebra ;
+import com.hp.hpl.jena.sparql.algebra.Op ;
+import com.hp.hpl.jena.sparql.serializer.SerializationContext ;
+
+public class QueryValidator extends ValidatorBase 
+{
+    public QueryValidator() 
+    { }
+
+    static final String paramLineNumbers      = "linenumbers" ;
+    static final String paramFormat           = "outputFormat" ;
+    static final String paramQuery            = "query" ;
+    static final String paramSyntax           = "languageSyntax" ;
+    //static final String paramSyntaxExtended   = "extendedSyntax" ;
+    
+    @Override
+    protected void execute(HttpServletRequest httpRequest, HttpServletResponse 
httpResponse)
+    {
+        try {
+//            if ( log.isInfoEnabled() )
+//                log.info("validation request") ;
+            
+            String[] args = httpRequest.getParameterValues(paramQuery) ;
+            
+            if ( args == null || args.length == 0 )
+            {
+                httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, "No 
query parameter to validator") ;
+                return ;
+            }
+            
+            if ( args.length > 1 )
+            {
+                httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, 
"Too many query parameters") ;
+                return ;
+            }
+
+            final String queryString = 
httpRequest.getParameter(paramQuery).replaceAll("(\r|\n| )*$", "") ;
+//            queryString = queryString.replace("\r\n", "\n") ;
+//            queryString.replaceAll("(\r|\n| )*$", "") ;
+            
+            String querySyntax = httpRequest.getParameter(paramSyntax) ;
+            if ( querySyntax == null || querySyntax.equals("") )
+                querySyntax = "SPARQL" ;
+
+            Syntax language = Syntax.lookup(querySyntax) ;
+            if ( language == null )
+            {
+                httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, 
"Unknown syntax: "+querySyntax) ;
+                return ;
+            }
+            
+            String lineNumbersArg = httpRequest.getParameter(paramLineNumbers) 
; 
+
+            String a[] = httpRequest.getParameterValues(paramFormat) ;
+            
+            boolean outputSPARQL = false ;
+            boolean outputPrefix = false ;
+            boolean outputAlgebra = false ;
+            boolean outputQuads = false ;
+            boolean outputOptimized = false ;
+            boolean outputOptimizedQuads = false ;
+            
+            if ( a != null )
+            {
+                for ( String anA : a )
+                {
+                    if ( anA.equals( "sparql" ) )
+                    {
+                        outputSPARQL = true;
+                    }
+                    if ( anA.equals( "prefix" ) )
+                    {
+                        outputPrefix = true;
+                    }
+                    if ( anA.equals( "algebra" ) )
+                    {
+                        outputAlgebra = true;
+                    }
+                    if ( anA.equals( "quads" ) )
+                    {
+                        outputQuads = true;
+                    }
+                    if ( anA.equals( "opt" ) )
+                    {
+                        outputOptimized = true;
+                    }
+                    if ( anA.equals( "optquads" ) )
+                    {
+                        outputOptimizedQuads = true;
+                    }
+                }
+            }
+            
+//            if ( ! outputSPARQL && ! outputPrefix )
+//                outputSPARQL = true ;
+            
+            boolean lineNumbers = true ;
+            
+            if ( lineNumbersArg != null )
+                lineNumbers = lineNumbersArg.equalsIgnoreCase("true") || 
lineNumbersArg.equalsIgnoreCase("yes") ;
+            
+            // Headers
+            setHeaders(httpResponse) ;
+            
+            ServletOutputStream outStream = httpResponse.getOutputStream() ;
+
+            outStream.println("<html>") ;
+            
+            printHead(outStream, "SPARQL Query Validation Report") ;
+            
+            outStream.println("<body>") ;
+            outStream.println("<h1>SPARQL Query Validator</h1>") ;
+            // Print query as received
+            {
+                outStream.println("<p>Input:</p>") ;
+                // Not Java's finest hour.
+                Content c = new Content(){
+                    @Override
+                    public void print(IndentedWriter out)
+                    { out.print(queryString) ; }
+                } ;
+                output(outStream, c, lineNumbers) ;
+            }
+            
+            // Attempt to parse it.
+            Query query = null ;
+            try {
+                query = QueryFactory.create(queryString, 
"http://example/base/";, language) ;
+            } catch (ARQException ex)
+            {
+                // Over generous exception (should be QueryException)
+                // but this makes the code robust.
+                outStream.println("<p>Syntax error:</p>") ;
+                startFixed(outStream) ;
+                outStream.println(ex.getMessage()) ;
+                finishFixed(outStream) ;
+            }
+            catch (RuntimeException ex)
+            { 
+                outStream.println("<p>Internal error:</p>") ;
+                startFixed(outStream) ;
+                outStream.println(ex.getMessage()) ;
+                finishFixed(outStream) ;
+            }
+            
+            if ( query != null )
+            {
+                if ( outputSPARQL )
+                    outputSyntax(outStream, query, lineNumbers) ;
+                
+                if ( outputAlgebra )
+                    outputAlgebra(outStream, query, lineNumbers) ;
+                
+                if ( outputQuads )
+                    outputAlgebraQuads(outStream, query, lineNumbers) ;
+                
+                if ( outputOptimized )
+                    outputAlgebraOpt(outStream, query, lineNumbers) ;
+
+                if ( outputOptimizedQuads )
+                    outputAlgebraOptQuads(outStream, query, lineNumbers) ;
+            }
+            
+            outStream.println("</body>") ;
+            outStream.println("</html>") ;
+            
+        } catch (Exception ex)
+        {
+            serviceLog.warn("Exception in doGet",ex) ;
+        }
+    }
+    
+    interface Content { void print(IndentedWriter out) ; }
+    
+    private void outputSyntax(ServletOutputStream outStream, final Query 
query, boolean lineNumbers) throws IOException
+    {
+        outStream.println("<p>Formatted, parsed query:</p>") ;
+        Content c = new Content(){
+            @Override
+            public void print(IndentedWriter out)
+            { query.serialize(out) ; }
+        } ;
+        output(outStream, c, lineNumbers) ;
+    }
+    
+    private void outputAlgebra(ServletOutputStream outStream, final Query 
query, boolean lineNumbers) throws IOException
+    {
+        outStream.println("<p>Algebra structure:</p>") ;
+        final Op op = Algebra.compile(query) ;   // No optimization
+        output(outStream, query, op, lineNumbers) ;
+    }
+        
+    private void outputAlgebraOpt(ServletOutputStream outStream, final Query 
query, boolean lineNumbers) throws IOException
+    {
+        outStream.println("<p>Alebgra, with general triple 
optimizations:</p>") ;
+        final Op op = Algebra.optimize(Algebra.compile(query)) ;
+        output(outStream, query, op, lineNumbers) ;
+    }
+        
+    private void outputAlgebraQuads(ServletOutputStream outStream, final Query 
query, boolean lineNumbers) throws IOException
+    {
+        outStream.println("<p>Quad structure:</p>") ;
+        final Op op = Algebra.toQuadForm(Algebra.compile(query)) ;
+        output(outStream, query, op, lineNumbers) ;
+    }
+
+    private void outputAlgebraOptQuads(ServletOutputStream outStream, final 
Query query, boolean lineNumbers) throws IOException
+    {
+        outStream.println("<p>Alebgra, with general quads optimizations:</p>") 
;
+        final Op op = 
Algebra.optimize(Algebra.toQuadForm(Algebra.compile(query))) ;
+        output(outStream, query, op, lineNumbers) ;
+    }
+    
+    private void output(ServletOutputStream outStream, Query query, final Op 
op, boolean lineNumbers) throws IOException
+    {
+        final SerializationContext sCxt = new SerializationContext(query) ;
+        Content c = new Content(){
+            @Override
+            public void print(IndentedWriter out)
+            {  op.output(out, sCxt) ; }
+        } ;
+        output(outStream, c , lineNumbers) ;
+    }
+
+    private void output(ServletOutputStream outStream, Content content, 
boolean lineNumbers) throws IOException
+    {
+        startFixed(outStream) ;
+        IndentedLineBuffer out = new IndentedLineBuffer(lineNumbers) ; 
+        content.print(out) ;
+        out.flush() ;  
+        String x = htmlQuote(out.asString()) ;
+        byte b[] = x.getBytes("UTF-8") ;
+        outStream.write(b) ;
+        finishFixed(outStream) ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/UpdateValidator.java
----------------------------------------------------------------------
diff --git 
a/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/UpdateValidator.java
 
b/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/UpdateValidator.java
new file mode 100644
index 0000000..dd63de8
--- /dev/null
+++ 
b/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/UpdateValidator.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki.validation;
+
+import java.io.IOException ;
+
+import javax.servlet.ServletOutputStream ;
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.atlas.io.IndentedLineBuffer ;
+import org.apache.jena.atlas.io.IndentedWriter ;
+
+import com.hp.hpl.jena.query.Syntax ;
+import com.hp.hpl.jena.sparql.ARQException ;
+import com.hp.hpl.jena.update.UpdateFactory ;
+import com.hp.hpl.jena.update.UpdateRequest ;
+
+public class UpdateValidator extends ValidatorBase
+{
+    public UpdateValidator() 
+    { }
+    
+    static final String paramLineNumbers      = "linenumbers" ;
+    static final String paramFormat           = "outputFormat" ;
+    static final String paramUpdate            = "update" ;
+    static final String paramSyntax           = "languageSyntax" ;
+    //static final String paramSyntaxExtended   = "extendedSyntax" ;
+    
+    @Override
+    protected void execute(HttpServletRequest httpRequest, HttpServletResponse 
httpResponse)
+    {
+        try {
+//            if ( log.isInfoEnabled() )
+//                log.info("validation request") ;
+            
+            String[] args = httpRequest.getParameterValues(paramUpdate) ;
+            
+            if ( args == null || args.length == 0 )
+            {
+                httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, "No 
update parameter to validator") ;
+                return ;
+            }
+            
+            if ( args.length > 1 )
+            {
+                httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, 
"Too many update parameters") ;
+                return ;
+            }
+
+            final String updateString = 
httpRequest.getParameter(paramUpdate).replaceAll("(\r|\n| )*$", "") ;
+            
+            String updateSyntax = httpRequest.getParameter(paramSyntax) ;
+            if ( updateSyntax == null || updateSyntax.equals("") )
+                updateSyntax = "SPARQL" ;
+
+            Syntax language = Syntax.lookup(updateSyntax) ;
+            if ( language == null )
+            {
+                httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, 
"Unknown syntax: "+updateSyntax) ;
+                return ;
+            }
+            
+            String lineNumbersArg = httpRequest.getParameter(paramLineNumbers) 
; 
+            String a[] = httpRequest.getParameterValues(paramFormat) ;
+            
+            // Currently default.
+            boolean outputSPARQL = true ;
+            boolean lineNumbers = true ;
+            
+            if ( lineNumbersArg != null )
+                lineNumbers = lineNumbersArg.equalsIgnoreCase("true") || 
lineNumbersArg.equalsIgnoreCase("yes") ;
+            
+            // Headers
+            setHeaders(httpResponse) ;
+
+            ServletOutputStream outStream = httpResponse.getOutputStream() ;
+
+            outStream.println("<html>") ;
+            
+            printHead(outStream, "SPARQL Update Validation Report") ;
+            
+            outStream.println("<body>") ;
+            outStream.println("<h1>SPARQL Update Validator</h1>") ;
+            
+            // Print as received
+            {
+                outStream.println("<p>Input:</p>") ;
+                // Not Java's finest hour.
+                Content c = new Content(){
+                    @Override
+                    public void print(IndentedWriter out)
+                    { out.print(updateString) ; }
+                } ;
+                output(outStream, c, lineNumbers) ;
+            }
+            
+            // Attempt to parse it.
+            UpdateRequest request= null ;
+            try {
+                request = UpdateFactory.create(updateString, 
"http://example/base/";, language) ;
+            } catch (ARQException ex)
+            {
+                // Over generous exception (should be QueryException)
+                // but this makes the code robust.
+                outStream.println("<p>Syntax error:</p>") ;
+                startFixed(outStream) ;
+                outStream.println(ex.getMessage()) ;
+                finishFixed(outStream) ;
+            }
+            catch (RuntimeException ex)
+            { 
+                outStream.println("<p>Internal error:</p>") ;
+                startFixed(outStream) ;
+                outStream.println(ex.getMessage()) ;
+                finishFixed(outStream) ;
+            }
+            
+            // Because we pass into anon inner classes
+            final UpdateRequest updateRequest = request ;
+            
+            // OK?  Pretty print
+            if ( updateRequest != null && outputSPARQL )
+            {
+                outStream.println("<p>Formatted, parsed update request:</p>") ;
+                Content c = new Content(){
+                    @Override
+                    public void print(IndentedWriter out)
+                    {
+                        updateRequest.output(out) ;
+                    }
+                        
+                } ;
+                output(outStream, c, lineNumbers) ;
+            }
+            outStream.println("</body>") ;
+            outStream.println("</html>") ;
+            
+        } catch (Exception ex)
+        {
+            serviceLog.warn("Exception in doGet",ex) ;
+        }
+    }
+
+    interface Content { void print(IndentedWriter out) ; }
+    
+    private void output(ServletOutputStream outStream, Content content, 
boolean lineNumbers) throws IOException
+    {
+        startFixed(outStream) ;
+        IndentedLineBuffer out = new IndentedLineBuffer(lineNumbers) ; 
+        content.print(out) ;
+        out.flush() ;  
+        String x = htmlQuote(out.asString()) ;
+        byte b[] = x.getBytes("UTF-8") ;
+        outStream.write(b) ;
+        finishFixed(outStream) ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/ValidatorBase.java
----------------------------------------------------------------------
diff --git 
a/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/ValidatorBase.java
 
b/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/ValidatorBase.java
new file mode 100644
index 0000000..61820f4
--- /dev/null
+++ 
b/jena-fuseki/src/main/java/org/apache/jena/fuseki/validation/ValidatorBase.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki.validation;
+
+import java.io.IOException ;
+
+import javax.servlet.ServletConfig ;
+import javax.servlet.ServletException ;
+import javax.servlet.ServletOutputStream ;
+import javax.servlet.http.HttpServlet ;
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.fuseki.Fuseki ;
+import org.apache.jena.fuseki.servlets.ServletBase ;
+import org.slf4j.Logger ;
+
+public abstract class ValidatorBase extends HttpServlet 
+{
+    protected static Logger serviceLog = Fuseki.requestLog ;
+
+    public static final String cssFile          = "/fuseki.css" ;
+    public static final String respService      = "X-Service" ;
+
+    
+    @Override
+    public void init() throws ServletException
+    { super.init() ; }
+
+    @Override
+    public void init(ServletConfig config) throws ServletException
+    { super.init(config) ; }
+    
+    @Override
+    public void destroy()
+    { }
+    
+    @Override
+    public void doGet(HttpServletRequest httpRequest, HttpServletResponse 
httpResponse)
+    { execute(httpRequest, httpResponse) ; }
+
+    @Override
+    public void doPost(HttpServletRequest httpRequest, HttpServletResponse 
httpResponse)
+    { execute(httpRequest, httpResponse) ; }
+    
+    protected abstract void execute(HttpServletRequest httpRequest, 
HttpServletResponse httpResponse) ;
+
+    protected static void setHeaders(HttpServletResponse httpResponse)
+    {
+        ServletBase.setCommonHeaders(httpResponse) ; 
+        httpResponse.setCharacterEncoding("UTF-8") ;
+        httpResponse.setContentType("text/html") ;
+        httpResponse.setHeader(respService, "Fuseki/ARQ SPARQL Query 
Validator: http://jena.apache.org/";) ;
+    }
+    
+    protected static String htmlQuote(String str)
+    {
+        StringBuilder sBuff = new StringBuilder() ;
+        for ( int i = 0 ; i < str.length() ; i++ )
+        {
+            char ch = str.charAt(i) ;
+            switch (ch)
+            {
+                case '<': sBuff.append("&lt;") ; break ;
+                case '>': sBuff.append("&gt;") ; break ;
+                case '&': sBuff.append("&amp;") ; break ;
+                default: 
+                    // Work around Eclipe bug with StringBuffer.append(char)
+                    //try { sBuff.append(ch) ; } catch (Exception ex) {}
+                    sBuff.append(ch) ;
+                    break ;  
+            }
+        }
+        return sBuff.toString() ; 
+    }
+
+    protected static void startFixed(ServletOutputStream outStream) throws 
IOException
+    {
+        outStream.println("<pre class=\"box\">") ;
+    }
+
+    protected static void columns(String prefix, ServletOutputStream 
outStream) throws IOException
+    {
+        outStream.print(prefix) ;
+        outStream.println("         1         2         3         4         5  
       6         7") ;
+        outStream.print(prefix) ;
+        
outStream.println("12345678901234567890123456789012345678901234567890123456789012345678901234567890")
 ;
+    }
+    
+    protected static void finishFixed(ServletOutputStream outStream) throws 
IOException
+    {
+        outStream.println("</pre>") ;
+    }
+    
+    protected static void printHead(ServletOutputStream outStream, String 
title) throws IOException
+    {
+        outStream.println("<head>") ;
+        outStream.println(" <title>"+title+"</title>") ;
+        outStream.println("   <meta http-equiv=\"Content-Type\" 
content=\"text/html; charset=utf-8\">") ;
+        outStream.println("   <link rel=\"stylesheet\" type=\"text/css\" 
href=\""+cssFile+"\" />") ;
+        //outStream.println() ;
+        outStream.println("</head>") ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/resources/META-INF/DEPENDENCIES
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/main/resources/META-INF/DEPENDENCIES 
b/jena-fuseki/src/main/resources/META-INF/DEPENDENCIES
new file mode 100644
index 0000000..910b788
--- /dev/null
+++ b/jena-fuseki/src/main/resources/META-INF/DEPENDENCIES
@@ -0,0 +1,24 @@
+This file lists the dependences for Apache Jena Fuseki.
+  Version numbers are given in the POM file for a particular distribution. 
+
+Apache Projects:   Apache Software License
+  Apache Jena, including the Jena IRI library
+  Apache Xerces-J
+  Apache log4j
+  Apache HttpComponents (HTTP Client)
+  Apache Commons Codec
+  Apache Common FileUpload
+
+ICU4J : http://icu-project.org/
+   IBM X License (to version ICU4J 3.4.4)
+
+SLF4J : http://www.slf4j.org/
+  Copyright (c) 2004-2008 QOS.ch
+  MIT License
+
+JUnit : http://junit.org/
+  Common Public License - v 1.0
+
+Jetty: http://www.eclipse.org/jetty/
+  Apache License 2.0 
+  (also avilable under Eclipse Public License 1.0)

http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/resources/META-INF/LICENSE
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/main/resources/META-INF/LICENSE 
b/jena-fuseki/src/main/resources/META-INF/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/jena-fuseki/src/main/resources/META-INF/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/resources/META-INF/NOTICE
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/main/resources/META-INF/NOTICE 
b/jena-fuseki/src/main/resources/META-INF/NOTICE
new file mode 100644
index 0000000..9e0e009
--- /dev/null
+++ b/jena-fuseki/src/main/resources/META-INF/NOTICE
@@ -0,0 +1,16 @@
+Apache Jena - module Fuseki
+Copyright 2011, 2012, 2013, 2014 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+Portions of this software were originally based on the following:
+  - Copyright 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development 
Company, LP
+  - Copyright 2010, 2011 Epimorphics Ltd.
+  - Copyright 2010, 2011 Talis Systems Ltd.
+These have been licensed to the Apache Software Foundation under a software 
grant.
+
+- - - - - - - - - - - - - - - - - - - - - - - 
+
+Portions of this software include software from  Mort Bay Consulting Pty. Ltd.
+ - Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.

http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/resources/org/apache/jena/fuseki/fuseki-properties.xml
----------------------------------------------------------------------
diff --git 
a/jena-fuseki/src/main/resources/org/apache/jena/fuseki/fuseki-properties.xml 
b/jena-fuseki/src/main/resources/org/apache/jena/fuseki/fuseki-properties.xml
new file mode 100644
index 0000000..34082eb
--- /dev/null
+++ 
b/jena-fuseki/src/main/resources/org/apache/jena/fuseki/fuseki-properties.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd";>
+<!-- Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0"; 
-->
+<properties version="1.0">
+  <comment>Fuseki System Properties</comment>
+  <entry key="org.apache.jena.fuseki.version">${project.version}</entry>
+  <entry key="org.apache.jena.fuseki.build.datetime">${build.time.xsd}</entry>
+</properties>

http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/test/java/org/apache/jena/fuseki/ServerTest.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/test/java/org/apache/jena/fuseki/ServerTest.java 
b/jena-fuseki/src/test/java/org/apache/jena/fuseki/ServerTest.java
new file mode 100644
index 0000000..7a4f6dc
--- /dev/null
+++ b/jena-fuseki/src/test/java/org/apache/jena/fuseki/ServerTest.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki;
+
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.NodeFactory ;
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.rdf.model.ModelFactory ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.DatasetGraphFactory ;
+import com.hp.hpl.jena.sparql.modify.request.Target ;
+import com.hp.hpl.jena.sparql.modify.request.UpdateDrop ;
+import com.hp.hpl.jena.sparql.sse.SSE ;
+import com.hp.hpl.jena.update.Update ;
+import com.hp.hpl.jena.update.UpdateExecutionFactory ;
+import com.hp.hpl.jena.update.UpdateProcessor ;
+
+/** Manage a server for testing.
+ * Example for one server per test suite: 
+ * <pre>
+    \@BeforeClass public static void beforeClass() { ServerTest.allocServer() 
; }
+    \@AfterClass  public static void afterClass()  { ServerTest.freeServer() ; 
}
+    \@Before      public void beforeTest()         { ServerTest.resetServer() 
; }
+    </pre>
+ */
+public class ServerTest
+{
+    // Abstraction that runs a SPARQL server for tests.
+    
+    public static final int port             = 3535 ;
+    public static final String urlRoot       = "http://localhost:"+port+"/"; ;
+    public static final String datasetPath   = "/dataset" ;
+    public static final String serviceUpdate = 
"http://localhost:"+port+datasetPath+"/update"; ; 
+    public static final String serviceQuery  = 
"http://localhost:"+port+datasetPath+"/query"; ; 
+    public static final String serviceREST   = 
"http://localhost:"+port+datasetPath+"/data"; ; // ??????
+    
+    public static final String gn1       = "http://graph/1"; ;
+    public static final String gn2       = "http://graph/2"; ;
+    public static final String gn99      = "http://graph/99"; ;
+    
+    public static final Node n1          = 
NodeFactory.createURI("http://graph/1";) ;
+    public static final Node n2          = 
NodeFactory.createURI("http://graph/2";) ;
+    public static final Node n99         = 
NodeFactory.createURI("http://graph/99";) ;
+    
+    public static final Graph graph1     = SSE.parseGraph("(base 
<http://example/> (graph (<x> <p> 1)))") ;
+    public static final Graph graph2     = SSE.parseGraph("(base 
<http://example/> (graph (<x> <p> 2)))") ;
+    
+    public static final Model model1     = 
ModelFactory.createModelForGraph(graph1) ;
+    public static final Model model2     = 
ModelFactory.createModelForGraph(graph2) ;
+    
+    private static EmbeddedFusekiServer server = null ;
+    
+    // reference count of start/stop server
+    private static int countServer = 0 ; 
+    
+    // This will cause there to be one server over all tests.
+    // Must be after initialization of counters 
+    //static { allocServer() ; }
+
+    static public void allocServer()
+    {
+        if ( countServer == 0 )
+            setupServer() ;
+        countServer++ ;
+    }
+    
+    static public void freeServer() 
+    {
+        if ( countServer >= 0 ) {
+            countServer -- ;
+            if ( countServer == 0 )
+                teardownServer() ;
+        }
+    }
+    
+    protected static void setupServer()
+    {
+        DatasetGraph dsg = DatasetGraphFactory.createMem() ;
+        server = EmbeddedFusekiServer.create(port, dsg, datasetPath) ;
+        server.start() ;
+    }
+    
+    protected static void teardownServer() {
+        if ( server != null )
+            server.stop() ;
+        server = null ;
+    }
+    public static void resetServer()
+    {
+        Update clearRequest = new UpdateDrop(Target.ALL) ;
+        UpdateProcessor proc = 
UpdateExecutionFactory.createRemote(clearRequest, ServerTest.serviceUpdate) ;
+        proc.execute() ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java 
b/jena-fuseki/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java
new file mode 100644
index 0000000..693217f
--- /dev/null
+++ b/jena-fuseki/src/test/java/org/apache/jena/fuseki/TS_Fuseki.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki;
+
+import org.apache.http.client.HttpClient ;
+import org.apache.jena.atlas.logging.LogCtl ;
+import org.apache.jena.fuseki.http.TestDatasetAccessorHTTP ;
+import org.apache.jena.fuseki.http.TestDatasetGraphAccessorHTTP ;
+import org.apache.jena.fuseki.http.TestHttpOp ;
+import org.apache.jena.riot.web.HttpOp ;
+import org.junit.AfterClass ;
+import org.junit.BeforeClass ;
+import org.junit.runner.RunWith ;
+import org.junit.runners.Suite ;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses( {
+    TestHttpOp.class
+    , TestSPARQLProtocol.class
+    , TestDatasetGraphAccessorHTTP.class
+    , TestDatasetAccessorHTTP.class
+    , TestQuery.class
+    , TestAuth.class
+})
+public class TS_Fuseki extends ServerTest
+{
+    // Use HttpOp caching of connections during testing to stop
+    // swamping  kernel socket management (seems to be most
+    // acute on Java 1.6)
+    
+    static HttpClient defaultHttpClient = HttpOp.getDefaultHttpClient() ;
+    // Used for all tests except auth tests.
+    static HttpClient globalCachingClient = HttpOp.createCachingHttpClient() ;
+    
+    @BeforeClass public static void beforeClassAbstract1() {
+        HttpOp.setDefaultHttpClient(globalCachingClient) ;
+    }
+    
+    @AfterClass public static void afterClassAbstract1() {
+        HttpOp.setDefaultHttpClient(defaultHttpClient) ;
+    }
+    
+    @BeforeClass static public void beforeClass() { 
LogCtl.disable(Fuseki.requestLogName) ; }
+    @AfterClass static public void afterClass()   { 
LogCtl.setInfo(Fuseki.requestLogName) ;}
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestAuth.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestAuth.java 
b/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestAuth.java
new file mode 100644
index 0000000..3324a92
--- /dev/null
+++ b/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestAuth.java
@@ -0,0 +1,420 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki;
+
+import java.io.File ;
+import java.io.FileWriter ;
+import java.io.IOException ;
+import java.net.URI ;
+import java.net.URISyntaxException ;
+import java.util.HashMap ;
+import java.util.Map ;
+
+import org.apache.jena.atlas.logging.LogCtl ;
+import org.apache.jena.atlas.web.HttpException ;
+import org.apache.jena.atlas.web.auth.PreemptiveBasicAuthenticator ;
+import org.apache.jena.atlas.web.auth.ScopedAuthenticator ;
+import org.apache.jena.atlas.web.auth.ServiceAuthenticator ;
+import org.apache.jena.atlas.web.auth.SimpleAuthenticator ;
+import org.apache.jena.fuseki.server.FusekiConfig ;
+import org.apache.jena.fuseki.server.SPARQLServer ;
+import org.apache.jena.fuseki.server.ServerConfig ;
+import org.junit.AfterClass ;
+import org.junit.Assert ;
+import org.junit.BeforeClass ;
+import org.junit.Test ;
+
+import com.hp.hpl.jena.query.ARQ ;
+import com.hp.hpl.jena.query.DatasetAccessor ;
+import com.hp.hpl.jena.query.DatasetAccessorFactory ;
+import com.hp.hpl.jena.query.QueryExecutionFactory ;
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.DatasetGraphFactory ;
+import com.hp.hpl.jena.sparql.engine.http.QueryEngineHTTP ;
+import com.hp.hpl.jena.sparql.engine.http.QueryExceptionHTTP ;
+import com.hp.hpl.jena.sparql.engine.http.Service ;
+import com.hp.hpl.jena.sparql.modify.UpdateProcessRemoteBase ;
+import com.hp.hpl.jena.sparql.util.Context ;
+import com.hp.hpl.jena.update.UpdateExecutionFactory ;
+import com.hp.hpl.jena.update.UpdateFactory ;
+import com.hp.hpl.jena.update.UpdateRequest ;
+
+/**
+ * Tests Fuseki operation with authentication enabled
+ */
+public class TestAuth extends ServerTest {
+
+    private static File realmFile;
+    private static SPARQLServer server;
+
+    /**
+     * Sets up the authentication for tests
+     * @throws IOException
+     */
+    @BeforeClass
+    public static void setup() throws IOException {
+        realmFile = File.createTempFile("realm", ".properties");
+
+        try(FileWriter writer = new FileWriter(realmFile)) {
+            writer.write("allowed: password, fuseki\n");
+            writer.write("forbidden: password, other");
+        }
+
+        LogCtl.logLevel(Fuseki.serverLog.getName(), 
org.apache.log4j.Level.WARN, java.util.logging.Level.WARNING);
+        LogCtl.logLevel(Fuseki.requestLog.getName(), 
org.apache.log4j.Level.WARN, java.util.logging.Level.WARNING);
+        LogCtl.logLevel("org.eclipse.jetty", org.apache.log4j.Level.WARN, 
java.util.logging.Level.WARNING);
+
+        DatasetGraph dsg = DatasetGraphFactory.createMem();
+        // This must agree with ServerTest
+        ServerConfig conf = FusekiConfig.defaultConfiguration(datasetPath, 
dsg, true, true);
+        conf.port = ServerTest.port;
+        conf.pagesPort = ServerTest.port;
+        conf.authConfigFile = realmFile.getAbsolutePath();
+
+        server = new SPARQLServer(conf);
+        server.start();
+    }
+
+    /**
+     * Tears down authentication test setup
+     */
+    @AfterClass
+    public static void teardown() {
+        server.stop();
+
+        realmFile.delete();
+    }
+
+    @Test(expected = QueryExceptionHTTP.class)
+    public void query_with_auth_01() {
+        QueryEngineHTTP qe = (QueryEngineHTTP) 
QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+        // No auth credentials should result in an error
+        qe.execAsk();
+    }
+
+    @Test(expected = QueryExceptionHTTP.class)
+    public void query_with_auth_02() {
+        QueryEngineHTTP qe = (QueryEngineHTTP) 
QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+        // Auth credentials for valid user with bad password
+        qe.setBasicAuthentication("allowed", "incorrect".toCharArray());
+        qe.execAsk();
+    }
+
+    @Test
+    public void query_with_auth_03() {
+        QueryEngineHTTP qe = (QueryEngineHTTP) 
QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+        // Auth credentials for valid user with correct password
+        qe.setBasicAuthentication("allowed", "password".toCharArray());
+        Assert.assertTrue(qe.execAsk());
+    }
+
+    @Test(expected = QueryExceptionHTTP.class)
+    public void query_with_auth_04() {
+        QueryEngineHTTP qe = (QueryEngineHTTP) 
QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+        // Auth credentials for valid user with correct password BUT not in
+        // correct role
+        qe.setBasicAuthentication("forbidden", "password".toCharArray());
+        qe.execAsk();
+    }
+
+    @Test
+    public void query_with_auth_05() {
+        // Uses auth and enables compression
+        QueryEngineHTTP qe = (QueryEngineHTTP) 
QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+        qe.setAllowDeflate(true);
+        qe.setAllowGZip(true);
+
+        // Auth credentials for valid user with correct password
+        qe.setBasicAuthentication("allowed", "password".toCharArray());
+        Assert.assertTrue(qe.execAsk());
+    }
+
+    @Test(expected = QueryExceptionHTTP.class)
+    public void query_with_auth_06() {
+        // Uses auth and enables compression
+        QueryEngineHTTP qe = (QueryEngineHTTP) 
QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+        qe.setAllowDeflate(true);
+        qe.setAllowGZip(true);
+
+        // Auth credentials for valid user with bad password
+        qe.setBasicAuthentication("allowed", "incorrect".toCharArray());
+        qe.execAsk();
+    }
+
+    @Test(expected = QueryExceptionHTTP.class)
+    public void query_with_auth_07() throws URISyntaxException {
+        QueryEngineHTTP qe = (QueryEngineHTTP) 
QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+        // Auth credentials for valid user with correct password but scoped to
+        // wrong URI
+        ScopedAuthenticator authenticator = new ScopedAuthenticator(new 
URI("http://example";), "allowed",
+                "password".toCharArray());
+        qe.setAuthenticator(authenticator);
+        qe.execAsk();
+    }
+
+    @Test
+    public void query_with_auth_08() throws URISyntaxException {
+        QueryEngineHTTP qe = (QueryEngineHTTP) 
QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+        // Auth credentials for valid user with correct password and scoped to
+        // correct URI
+        ScopedAuthenticator authenticator = new ScopedAuthenticator(new 
URI(serviceQuery), "allowed", "password".toCharArray());
+        qe.setAuthenticator(authenticator);
+        Assert.assertTrue(qe.execAsk());
+    }
+
+    @Test
+    public void query_with_auth_09() throws URISyntaxException {
+        QueryEngineHTTP qe = (QueryEngineHTTP) 
QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+        // Auth credentials for valid user with correct password using
+        // pre-emptive auth
+        ScopedAuthenticator authenticator = new ScopedAuthenticator(new 
URI(serviceQuery), "allowed", "password".toCharArray());
+        qe.setAuthenticator(new PreemptiveBasicAuthenticator(authenticator));
+        Assert.assertTrue(qe.execAsk());
+    }
+
+    @Test
+    public void query_with_auth_10() {
+        Context ctx = ARQ.getContext();
+        try {
+            QueryEngineHTTP qe = (QueryEngineHTTP) 
QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+            // Auth credentials for valid user with correct password and scoped
+            // to correct URI
+            // Provided via Service Context and its associated authenticator
+            Map<String, Context> serviceContext = new HashMap<String, 
Context>();
+            Context authContext = new Context();
+            authContext.put(Service.queryAuthUser, "allowed");
+            authContext.put(Service.queryAuthPwd, "password");
+            serviceContext.put(serviceQuery, authContext);
+            ctx.put(Service.serviceContext, serviceContext);
+
+            qe.setAuthenticator(new ServiceAuthenticator());
+            Assert.assertTrue(qe.execAsk());
+        } finally {
+            ctx.remove(Service.serviceContext);
+        }
+    }
+    
+    @Test
+    public void query_with_auth_11() {
+        Context ctx = ARQ.getContext();
+        try {
+            QueryEngineHTTP qe = (QueryEngineHTTP) 
QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+            // Auth credentials for valid user with correct password and scoped
+            // to base URI of the actual service URL
+            // Provided via Service Context and its associated authenticator
+            Map<String, Context> serviceContext = new HashMap<String, 
Context>();
+            Context authContext = new Context();
+            authContext.put(Service.queryAuthUser, "allowed");
+            authContext.put(Service.queryAuthPwd, "password");
+            serviceContext.put(urlRoot, authContext);
+            ctx.put(Service.serviceContext, serviceContext);
+
+            qe.setAuthenticator(new ServiceAuthenticator());
+            Assert.assertTrue(qe.execAsk());
+        } finally {
+            ctx.remove(Service.serviceContext);
+        }
+    }
+    
+    @Test
+    public void query_with_auth_12() {
+        ARQ.getContext().remove(Service.serviceContext);
+
+        QueryEngineHTTP qe = (QueryEngineHTTP) 
QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+        // Auth credentials for valid user with correct password
+        // Use service authenticator with fallback credentials.
+        qe.setAuthenticator(new ServiceAuthenticator("allowed", 
"password".toCharArray()));
+        Assert.assertTrue(qe.execAsk());
+     }
+    
+    @Test
+    public void query_with_auth_13() throws URISyntaxException {
+        QueryEngineHTTP qe = (QueryEngineHTTP) 
QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+        // Auth credentials for valid user with correct password and scoped to
+        // base URI of the actual service URL
+        ScopedAuthenticator authenticator = new ScopedAuthenticator(new 
URI(urlRoot), "allowed", "password".toCharArray());
+        qe.setAuthenticator(authenticator);
+        Assert.assertTrue(qe.execAsk());
+    }
+    
+    @Test
+    public void query_with_auth_14() throws URISyntaxException {
+        QueryEngineHTTP qe = (QueryEngineHTTP) 
QueryExecutionFactory.sparqlService(serviceQuery, "ASK { }");
+
+        // Auth credentials for valid user with correct password and scoped to
+        // base URI of the actual service URL
+        ScopedAuthenticator authenticator = new ScopedAuthenticator(new 
URI("http://localhost:"; + port), "allowed", "password".toCharArray());
+        qe.setAuthenticator(authenticator);
+        Assert.assertTrue(qe.execAsk());
+    }
+
+    @Test(expected = HttpException.class)
+    public void update_with_auth_01() {
+        UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH 
<http://graph>");
+        UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) 
UpdateExecutionFactory.createRemote(updates, serviceUpdate);
+        // No auth credentials should result in an error
+        ue.execute();
+    }
+
+    @Test(expected = HttpException.class)
+    public void update_with_auth_02() {
+        UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH 
<http://graph>");
+        UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) 
UpdateExecutionFactory.createRemote(updates, serviceUpdate);
+        // Auth credentials for valid user with bad password
+        ue.setAuthentication("allowed", "incorrect".toCharArray());
+        ue.execute();
+    }
+
+    @Test
+    public void update_with_auth_03() {
+        UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH 
<http://graph>");
+        UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) 
UpdateExecutionFactory.createRemote(updates, serviceUpdate);
+        // Auth credentials for valid user with correct password
+        ue.setAuthentication("allowed", "password".toCharArray());
+        ue.execute();
+    }
+
+    @Test(expected = HttpException.class)
+    public void update_with_auth_04() {
+        UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH 
<http://graph>");
+        UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) 
UpdateExecutionFactory.createRemote(updates, serviceUpdate);
+        // Auth credentials for valid user with correct password BUT not in
+        // correct role
+        ue.setAuthentication("forbidden", "password".toCharArray());
+        ue.execute();
+    }
+
+    @Test(expected = HttpException.class)
+    public void update_with_auth_05() {
+        UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH 
<http://graph>");
+        UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) 
UpdateExecutionFactory.createRemoteForm(updates, serviceUpdate);
+        // No auth credentials should result in an error
+        ue.execute();
+    }
+
+    @Test(expected = HttpException.class)
+    public void update_with_auth_06() {
+        UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH 
<http://graph>");
+        UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) 
UpdateExecutionFactory.createRemoteForm(updates, serviceUpdate);
+        // Auth credentials for valid user with bad password
+        ue.setAuthentication("allowed", "incorrect".toCharArray());
+        ue.execute();
+    }
+
+    @Test
+    public void update_with_auth_07() {
+        UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH 
<http://graph>");
+        UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) 
UpdateExecutionFactory.createRemoteForm(updates, serviceUpdate);
+        // Auth credentials for valid user with correct password
+        ue.setAuthentication("allowed", "password".toCharArray());
+        ue.execute();
+    }
+
+    @Test(expected = HttpException.class)
+    public void update_with_auth_08() {
+        UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH 
<http://graph>");
+        UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) 
UpdateExecutionFactory.createRemoteForm(updates, serviceUpdate);
+        // Auth credentials for valid user with correct password BUT not in
+        // correct role
+        ue.setAuthentication("forbidden", "password".toCharArray());
+        ue.execute();
+    }
+
+    @Test(expected = HttpException.class)
+    public void update_with_auth_09() throws URISyntaxException {
+        UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH 
<http://graph>");
+        UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) 
UpdateExecutionFactory.createRemote(updates, serviceUpdate);
+
+        // Auth credentials for valid user with correct password but scoped to
+        // wrong URI
+        ScopedAuthenticator authenticator = new ScopedAuthenticator(new 
URI("http://example";), "allowed",
+                "password".toCharArray());
+        ue.setAuthenticator(authenticator);
+        ue.execute();
+    }
+
+    @Test
+    public void update_with_auth_10() throws URISyntaxException {
+        UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH 
<http://graph>");
+        UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) 
UpdateExecutionFactory.createRemote(updates, serviceUpdate);
+
+        // Auth credentials for valid user with correct password scoped to
+        // correct URI
+        ScopedAuthenticator authenticator = new ScopedAuthenticator(new 
URI(serviceUpdate), "allowed", "password".toCharArray());
+        ue.setAuthenticator(authenticator);
+        ue.execute();
+    }
+
+    @Test
+    public void update_with_auth_11() throws URISyntaxException {
+        UpdateRequest updates = UpdateFactory.create("CREATE SILENT GRAPH 
<http://graph>");
+        UpdateProcessRemoteBase ue = (UpdateProcessRemoteBase) 
UpdateExecutionFactory.createRemote(updates, serviceUpdate);
+
+        // Auth credentials for valid user with correct password scoped to
+        // correct URI
+        // Also using pre-emptive auth
+        ScopedAuthenticator authenticator = new ScopedAuthenticator(new 
URI(serviceUpdate), "allowed", "password".toCharArray());
+        ue.setAuthenticator(new PreemptiveBasicAuthenticator(authenticator));
+        ue.execute();
+    }
+    
+    @Test(expected = HttpException.class)
+    public void graphstore_with_auth_01() {       
+        // No auth credentials
+        DatasetAccessor accessor = 
DatasetAccessorFactory.createHTTP(serviceREST);
+        accessor.getModel();
+    }
+    
+    @Test(expected = HttpException.class)
+    public void graphstore_with_auth_02() {
+        // Incorrect auth credentials
+        DatasetAccessor accessor = 
DatasetAccessorFactory.createHTTP(serviceREST, new 
SimpleAuthenticator("allowed", "incorrect".toCharArray()));
+        accessor.getModel();
+    }
+    
+    @Test
+    public void graphstore_with_auth_03() {
+        // Correct auth credentials
+        DatasetAccessor accessor = 
DatasetAccessorFactory.createHTTP(serviceREST, new 
SimpleAuthenticator("allowed", "password".toCharArray()));
+        Model m = accessor.getModel();
+        Assert.assertTrue(m.isEmpty());
+    }
+    
+    @Test(expected = HttpException.class)
+    public void graphstore_with_auth_04() throws URISyntaxException {
+        // Correct auth credentials scoped to wrong URI
+        DatasetAccessor accessor = 
DatasetAccessorFactory.createHTTP(serviceREST, new ScopedAuthenticator(new 
URI("http://example.org/";), "allowed", "password".toCharArray()));
+        accessor.getModel();
+    }
+    
+    @Test
+    public void graphstore_with_auth_05() throws URISyntaxException {
+        // Correct auth credentials scoped to correct URI
+        DatasetAccessor accessor = 
DatasetAccessorFactory.createHTTP(serviceREST, new ScopedAuthenticator(new 
URI(serviceREST), "allowed", "password".toCharArray()));
+        accessor.getModel();
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestQuery.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestQuery.java 
b/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestQuery.java
new file mode 100644
index 0000000..5748dc4
--- /dev/null
+++ b/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestQuery.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki;
+
+import java.io.IOException ;
+import java.net.HttpURLConnection ;
+import java.net.URL ;
+
+import static org.apache.jena.fuseki.ServerTest.* ;
+
+import org.junit.AfterClass ;
+import org.junit.Assert ;
+import org.junit.BeforeClass ;
+import org.junit.Test ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import com.hp.hpl.jena.query.* ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.engine.binding.Binding ;
+import com.hp.hpl.jena.sparql.resultset.ResultSetCompare ;
+import com.hp.hpl.jena.sparql.sse.Item ;
+import com.hp.hpl.jena.sparql.sse.SSE ;
+import com.hp.hpl.jena.sparql.sse.builders.BuilderResultSet ;
+import com.hp.hpl.jena.sparql.util.Convert ;
+
+public class TestQuery extends BaseTest 
+{
+    protected static ResultSet rs1 = null ; 
+    static {
+        Item item = SSE.parseItem("(resultset (?s ?p ?o) (row (?s <x>)(?p 
<p>)(?o 1)))") ;
+        rs1 = BuilderResultSet.build(item) ;
+    }
+    
+    // DRY - test protocol?
+    @BeforeClass public static void beforeClass()
+    {
+        ServerTest.allocServer() ;
+        ServerTest.resetServer() ;
+        DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ;
+        du.putModel(model1) ;
+        du.putModel(gn1, model2) ;
+    }
+    
+    @AfterClass public static void afterClass()
+    {
+        DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ;
+        du.deleteDefault() ;
+        ServerTest.freeServer() ;
+    }
+    
+    @Test public void query_01()
+    {
+        execQuery("SELECT * {?s ?p ?o}", 1) ;
+    }
+    
+    @Test public void query_recursive_01()
+    {
+        String query = "SELECT * WHERE { SERVICE <" + serviceQuery + "> { ?s 
?p ?o . BIND(?o AS ?x) } }";
+        try(QueryExecution qExec = 
QueryExecutionFactory.sparqlService(serviceQuery, query)) {
+            ResultSet rs = qExec.execSelect();
+            
+            Var x = Var.alloc("x");
+            while (rs.hasNext()) {
+                Binding b = rs.nextBinding();
+                Assert.assertNotNull(b.get(x));
+            }
+        }
+    }
+    
+    @Test public void query_with_params_01()
+    {
+        String query = "ASK { }";
+        try(QueryExecution qExec = 
QueryExecutionFactory.sparqlService(serviceQuery + "?output=json", query)) {
+            boolean result = qExec.execAsk();
+            Assert.assertTrue(result);
+        }
+    }
+    
+    @Test public void request_id_header_01() throws IOException
+    {
+        String qs = Convert.encWWWForm("ASK{}") ;
+        URL u = new URL(serviceQuery+"?query="+qs);
+        HttpURLConnection conn = (HttpURLConnection) u.openConnection();
+        Assert.assertTrue(conn.getHeaderField("Fuseki-Request-ID") != null);
+    }
+
+    private void execQuery(String queryString, int exceptedRowCount)
+    {
+        QueryExecution qExec = 
QueryExecutionFactory.sparqlService(serviceQuery, queryString) ;
+        ResultSet rs = qExec.execSelect() ;
+        int x = ResultSetFormatter.consume(rs) ;
+        assertEquals(exceptedRowCount, x) ;
+    }
+    
+    private void execQuery(String queryString, ResultSet expectedResultSet)
+    {
+        QueryExecution qExec = 
QueryExecutionFactory.sparqlService(serviceQuery, queryString) ;
+        ResultSet rs = qExec.execSelect() ;
+        boolean b = ResultSetCompare.equalsByTerm(rs, expectedResultSet) ;
+        assertTrue("Result sets different", b) ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestSPARQLProtocol.java
----------------------------------------------------------------------
diff --git 
a/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestSPARQLProtocol.java 
b/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestSPARQLProtocol.java
new file mode 100644
index 0000000..3b86e17
--- /dev/null
+++ b/jena-fuseki/src/test/java/org/apache/jena/fuseki/TestSPARQLProtocol.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki;
+
+import static org.apache.jena.fuseki.ServerTest.* ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.riot.WebContent ;
+import org.junit.AfterClass ;
+import org.junit.BeforeClass ;
+import org.junit.Test ;
+
+import com.hp.hpl.jena.query.* ;
+import com.hp.hpl.jena.sparql.engine.http.QueryEngineHTTP ;
+import com.hp.hpl.jena.sparql.util.Convert ;
+import com.hp.hpl.jena.update.UpdateExecutionFactory ;
+import com.hp.hpl.jena.update.UpdateFactory ;
+import com.hp.hpl.jena.update.UpdateProcessor ;
+import com.hp.hpl.jena.update.UpdateRequest ;
+// Generally poke the server using Jena APIs
+// SPARQL Query
+// SPARQL Update
+//   GSP is done in TestDatasetAccessorHTTP
+
+public class TestSPARQLProtocol extends BaseTest
+{
+    @BeforeClass public static void beforeClass()
+    {
+        ServerTest.allocServer() ;
+        ServerTest.resetServer() ;
+        // Load some data.
+        DatasetAccessor du = DatasetAccessorFactory.createHTTP(serviceREST) ;
+        du.putModel(model1) ;
+        du.putModel(gn1, model2) ;
+    }
+    
+    @AfterClass public static void afterClass()
+    {
+        ServerTest.resetServer() ;
+        ServerTest.freeServer() ;
+    }
+    
+    static String query(String base, String queryString)
+    {
+        return base+"?query="+Convert.encWWWForm(queryString) ;
+    }
+    
+    @Test public void query_01()
+    {
+        Query query = QueryFactory.create("SELECT * { ?s ?p ?o }") ;
+        QueryExecution qexec = 
QueryExecutionFactory.sparqlService(serviceQuery, query) ;
+        ResultSet rs = qexec.execSelect() ;
+        int x = ResultSetFormatter.consume(rs) ;
+        assertTrue( x != 0 ) ;
+    }
+
+    @Test public void query_02()
+    {
+        Query query = QueryFactory.create("SELECT * { ?s ?p ?o }") ;
+        QueryEngineHTTP engine = 
QueryExecutionFactory.createServiceRequest(serviceQuery, query) ;
+        engine.setSelectContentType(WebContent.contentTypeResultsJSON) ;
+        ResultSet rs = engine.execSelect() ;
+        int x = ResultSetFormatter.consume(rs) ;
+        assertTrue( x != 0 ) ;
+    }
+
+    @Test public void update_01()
+    {
+        UpdateRequest update = UpdateFactory.create("INSERT DATA {}") ;
+        UpdateProcessor proc = UpdateExecutionFactory.createRemote(update, 
serviceUpdate) ;
+        proc.execute() ;
+    }
+    
+    @Test public void update_02()
+    {
+        UpdateRequest update = UpdateFactory.create("INSERT DATA {}") ;
+        UpdateProcessor proc = UpdateExecutionFactory.createRemoteForm(update, 
serviceUpdate) ;
+        proc.execute() ;
+    }
+}

Reply via email to