You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2018/09/21 10:16:08 UTC
[57/70] [abbrv] jena git commit: JENA-1597: Modules jena-fuseki-main
and jena-fuseki-server
http://git-wip-us.apache.org/repos/asf/jena/blob/7e6d03af/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestFusekiCustomOperation.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestFusekiCustomOperation.java b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestFusekiCustomOperation.java
deleted file mode 100644
index 17eaff6..0000000
--- a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestFusekiCustomOperation.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * 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.embedded;
-
-import static org.junit.Assert.*;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.jena.atlas.io.IO;
-import org.apache.jena.atlas.web.HttpException;
-import org.apache.jena.atlas.web.TypedInputStream;
-import org.apache.jena.fuseki.FusekiConfigException;
-import org.apache.jena.fuseki.FusekiLib;
-import org.apache.jena.fuseki.build.FusekiBuilder;
-import org.apache.jena.fuseki.server.DataService;
-import org.apache.jena.fuseki.server.Operation;
-import org.apache.jena.fuseki.servlets.ActionService;
-import org.apache.jena.query.QueryExecution;
-import org.apache.jena.rdfconnection.RDFConnection;
-import org.apache.jena.rdfconnection.RDFConnectionFactory;
-import org.apache.jena.riot.web.HttpOp;
-import org.apache.jena.sparql.core.DatasetGraph;
-import org.apache.jena.sparql.core.DatasetGraphFactory;
-import org.junit.Test;
-
-/** Test for adding a new operation */
-public class TestFusekiCustomOperation {
- private static final Operation newOp = Operation.register("Special", "Custom operation");
- private static final String contentType = "application/special";
- private static final String endpointName = "special";
-
- private final ActionService customHandler = new CustomService();
- private final int port = FusekiLib.choosePort();
- private final String url = "http://localhost:"+port;
-
- @Test
- public void cfg_dataservice() {
- // Create a DataService and add the endpoint -> operation association.
- // This still needs the server to have the operation registered.
- DatasetGraph dsg = DatasetGraphFactory.createTxnMem();
- DataService dataService = new DataService(dsg);
- FusekiBuilder.populateStdServices(dataService, true);
- FusekiBuilder.addServiceEP(dataService, newOp, endpointName);
-
- FusekiServer server =
- FusekiServer.create()
- .port(port)
- .registerOperation(newOp, contentType, customHandler)
- .add("/ds", dataService)
- .build();
- testServer(server, true, true);
- }
-
- @Test
- public void cfg_builder_CT() {
- FusekiServer server =
- FusekiServer.create()
- .port(port)
- .registerOperation(newOp, contentType, customHandler)
- .add("/ds", DatasetGraphFactory.createTxnMem(), true)
- .addOperation("/ds", endpointName, newOp)
- .build();
- testServer(server, true, true);
- }
-
- @Test
- public void cfg_builder_noCT() {
- FusekiServer server =
- FusekiServer.create()
- .port(port)
- .registerOperation(newOp, null, customHandler)
- .add("/ds", DatasetGraphFactory.createTxnMem(), true)
- .addOperation("/ds", endpointName, newOp)
- .build();
- testServer(server, true, false);
- }
-
- @Test(expected=FusekiConfigException.class)
- public void cfg_bad_01() {
- FusekiServer.create()
- .port(port)
- .registerOperation(newOp, null, customHandler)
- .addOperation("/UNKNOWN", endpointName, newOp);
- //.build();
- }
-
- @Test(expected=FusekiConfigException.class)
- public void cfg_bad_02() {
- FusekiServer.create()
- .port(port)
- //.registerOperation(newOp, null, customHandler)
- .add("/ds", DatasetGraphFactory.createTxnMem(), true)
- // Unregistered.
- .addOperation("/ds", endpointName, newOp);
- //.build();
- }
-
- public void cfg_bad_ct_not_enabkled_here() {
- FusekiServer server = FusekiServer.create()
- .port(port)
- .registerOperation(newOp, "app/special", customHandler)
- .add("/ds", DatasetGraphFactory.createTxnMem(), true)
- // Unregistered.
- .addOperation("/ds", endpointName, newOp)
- .build();
- testServer(server, false, false);
- }
-
-
- private void testServer(FusekiServer server, boolean withEndpoint, boolean withContentType) {
- try {
- server.start();
- // Try query (no extension required)
- try(RDFConnection rconn = RDFConnectionFactory.connect(url+"/ds")) {
- try(QueryExecution qExec = rconn.query("ASK {}")) {
- qExec.execAsk();
- }
- }
-
- if ( withEndpoint ) {
- // Service endpoint name : GET
- String s1 = HttpOp.execHttpGetString(url+"/ds/"+endpointName);
-
- // Service endpoint name : POST
- try ( TypedInputStream stream = HttpOp.execHttpPostStream(url+"/ds/"+endpointName, "ignored", "", "text/plain") ) {
- String x = IOUtils.toString(stream, StandardCharsets.UTF_8);
- assertNotNull(x);
- } catch (IOException ex) {
- IO.exception(ex);
- }
- } else {
- // No endpoint so we expect a 404.
- try {
- // Service endpoint name : GET
- HttpOp.execHttpGet(url+"/ds/"+endpointName);
- fail("Expected to fail HTTP GET");
- } catch (HttpException ex) {
- assertEquals(404, ex.getResponseCode());
- }
- }
-
- if ( withContentType ) {
- // Content-type
- try ( TypedInputStream stream = HttpOp.execHttpPostStream(url+"/ds", contentType, "", "text/plain") ) {
- String x = IOUtils.toString(stream, StandardCharsets.UTF_8);
- assertNotNull(x);
- } catch (IOException ex) {
- IO.exception(ex);
- }
- } else {
- // No Content-Type
- try ( TypedInputStream stream = HttpOp.execHttpPostStream(url+"/ds", contentType, "", "text/plain") ) {
- fail("Expected to fail HTTP POST using Content-Type");
- } catch (HttpException ex) {}
-
- // Service endpoint name. DELETE -> fails 405
- try {
- HttpOp.execHttpDelete(url+"/ds/"+endpointName);
- throw new IllegalStateException("DELETE succeeded");
- } catch (HttpException ex) {
- assertEquals(405, ex.getResponseCode());
- }
- }
- } finally {
- server.stop();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/7e6d03af/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestFusekiTestAuth.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestFusekiTestAuth.java b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestFusekiTestAuth.java
deleted file mode 100644
index 4c575b4..0000000
--- a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestFusekiTestAuth.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.embedded;
-
-import static org.apache.jena.fuseki.embedded.FusekiTestAuth.assertAuthHttpException;
-
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.Credentials;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.HttpClient;
-import org.apache.http.impl.client.BasicCredentialsProvider;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.jena.atlas.logging.LogCtl;
-import org.apache.jena.atlas.web.HttpException;
-import org.apache.jena.atlas.web.TypedInputStream;
-import org.apache.jena.fuseki.Fuseki;
-import org.apache.jena.riot.web.HttpOp;
-import org.eclipse.jetty.security.SecurityHandler;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-public class TestFusekiTestAuth {
-
- static {
- LogCtl.setLevel(Fuseki.serverLogName, "WARN");
- LogCtl.setLevel(Fuseki.actionLogName, "WARN");
- LogCtl.setLevel(Fuseki.requestLogName, "WARN");
- LogCtl.setLevel(Fuseki.adminLogName, "WARN");
- LogCtl.setLevel("org.eclipse.jetty", "WARN");
- }
-
- private static String USER = "user1234";
- private static String PASSWORD = "password1234";
-
- @BeforeClass
- public static void ctlBeforeClass() {
- SecurityHandler sh = FusekiTestAuth.makeSimpleSecurityHandler("/*", USER, PASSWORD);
- FusekiTestAuth.setupServer(false, sh);
- }
-
- @AfterClass
- public static void ctlAfterClass() {
- FusekiTestAuth.teardownServer();
- HttpOp.setDefaultHttpClient(HttpOp.createPoolingHttpClient());
- }
-
- @Test(expected=HttpException.class)
- public void testServer_auth_no_auth() {
- // No Auth
- try ( TypedInputStream in = HttpOp.execHttpGet(FusekiTestAuth.urlDataset(), "*/*") ) {}
- catch (HttpException ex) { throw assertAuthHttpException(ex); }
- }
-
- @Test public void testServer_auth() {
- BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
- Credentials credentials = new UsernamePasswordCredentials(USER, PASSWORD);
- credsProvider.setCredentials(AuthScope.ANY, credentials);
- HttpClient client = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
- try ( TypedInputStream in = HttpOp.execHttpGet(FusekiTestAuth.urlDataset(), "*/*", client, null) ) {}
- }
-
- @Test(expected=HttpException.class)
- public void testServer_auth_bad_user() {
- BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
- Credentials credentials = new UsernamePasswordCredentials("USERUSER", PASSWORD);
- credsProvider.setCredentials(AuthScope.ANY, credentials);
- HttpClient client = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
- try ( TypedInputStream in = HttpOp.execHttpGet(FusekiTestAuth.urlDataset(), "*/*", client, null) ) {}
- catch (HttpException ex) { throw assertAuthHttpException(ex); }
- }
-
- @Test(expected=HttpException.class)
- public void testServer_auth_bad_password() {
- BasicCredentialsProvider credsProv = new BasicCredentialsProvider();
- credsProv.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(USER, "WRONG"));
- HttpClient client = HttpClients.custom().setDefaultCredentialsProvider(credsProv).build();
-
- try ( TypedInputStream in = HttpOp.execHttpGet(FusekiTestAuth.urlDataset(), "*/*", client, null) ) {}
- catch (HttpException ex) { throw assertAuthHttpException(ex); }
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/7e6d03af/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestFusekiTestServer.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestFusekiTestServer.java b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestFusekiTestServer.java
deleted file mode 100644
index 9bbe2a8..0000000
--- a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestFusekiTestServer.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.embedded;
-
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.HttpClient;
-import org.apache.http.impl.client.BasicCredentialsProvider;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.jena.atlas.web.HttpException;
-import org.apache.jena.atlas.web.TypedInputStream;
-import org.apache.jena.riot.web.HttpOp;
-import org.apache.jena.web.HttpSC;
-import org.junit.*;
-
-public class TestFusekiTestServer {
-
-// @BeforeClass static public void beforeSuiteClass() { ServerCtl.ctlBeforeTestSuite(); }
-// @AfterClass static public void afterSuiteClass() { ServerCtl.ctlAfterTestSuite(); }
-
- // This is file is the "suite".
-
- @BeforeClass public static void ctlBeforeClass() { FusekiTestServer.ctlBeforeTestSuite(); FusekiTestServer.ctlBeforeClass(); }
- @AfterClass public static void ctlAfterClass() { FusekiTestServer.ctlAfterClass(); FusekiTestServer.ctlAfterTestSuite(); }
- @Before public void ctlBeforeTest() { FusekiTestServer.ctlBeforeTest(); }
- @After public void ctlAfterTest() { FusekiTestServer.ctlAfterTest(); }
-
- @Test public void testServer_1() {
- HttpOp.execHttpGetString(FusekiTestServer.urlDataset());
- }
-
- @Test public void testServer_2() {
- BasicCredentialsProvider credsProv = new BasicCredentialsProvider();
- credsProv.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("USER", "PASSWORD"));
- HttpClient client = HttpClients.custom().setDefaultCredentialsProvider(credsProv).build();
-
- // No auth set - should work.
- try ( TypedInputStream in = HttpOp.execHttpGet(FusekiTestServer.urlDataset(), "*/*") ) {}
- catch (HttpException ex) {
- Assert.assertTrue(ex.getResponseCode() == HttpSC.FORBIDDEN_403 || ex.getResponseCode() == HttpSC.UNAUTHORIZED_401 );
- throw ex;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/7e6d03af/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestMultipleEmbedded.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestMultipleEmbedded.java b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestMultipleEmbedded.java
deleted file mode 100644
index 7871490..0000000
--- a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/TestMultipleEmbedded.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * 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.embedded;
-
-import static org.apache.jena.fuseki.embedded.TestEmbeddedFuseki.dataset ;
-import static org.apache.jena.fuseki.embedded.TestEmbeddedFuseki.query ;
-import static org.junit.Assert.assertEquals ;
-import static org.junit.Assert.assertTrue ;
-
-import java.io.OutputStream ;
-
-import org.apache.http.HttpEntity ;
-import org.apache.http.entity.ContentProducer ;
-import org.apache.http.entity.EntityTemplate ;
-import org.apache.jena.atlas.web.ContentType ;
-import org.apache.jena.fuseki.FusekiException ;
-import org.apache.jena.fuseki.FusekiLib;
-import org.apache.jena.graph.Graph ;
-import org.apache.jena.query.ResultSet ;
-import org.apache.jena.query.ResultSetFormatter ;
-import org.apache.jena.riot.RDFDataMgr ;
-import org.apache.jena.riot.RDFFormat ;
-import org.apache.jena.sparql.core.DatasetGraph ;
-import org.apache.jena.sparql.core.Quad ;
-import org.apache.jena.sparql.sse.SSE ;
-import org.apache.jena.system.Txn ;
-import org.junit.Test ;
-
-public class TestMultipleEmbedded {
-
- static Quad q1 = SSE.parseQuad("(_ :s :p 1)") ;
- static Quad q2 = SSE.parseQuad("(_ :s :p 2)") ;
-
- // Two servers, same port -> bad.
- @Test(expected=FusekiException.class)
- public void multiple_01() {
- DatasetGraph dsg = dataset() ;
-
- int port = FusekiLib.choosePort() ;
- FusekiServer server1 = FusekiServer.create().port(port).add("/ds1", dsg).build() ;
- // Same port - Bad.
- FusekiServer server2 = FusekiServer.create().port(port).add("/ds2", dsg).build() ;
-
- server1.start();
-
- try {
- server2.start();
- } catch (FusekiException ex) {
- assertTrue(ex.getCause() instanceof java.net.BindException ) ;
- throw ex ;
- } finally {
- try { server1.stop() ; } catch (Exception ex) {}
- try { server2.stop() ; } catch (Exception ex) {}
- }
- }
-
- // Two servers, different ports -> good.
- @Test
- public void multiple_02() {
- DatasetGraph dsg = dataset() ;
- int port1 = FusekiLib.choosePort() ;
- FusekiServer server1 = FusekiServer.create().port(port1).add("/ds1", dsg).build() ;
-
- // Different port - good
- int port2 = FusekiLib.choosePort() ;
- FusekiServer server2 = FusekiServer.create().port(port2).add("/ds2", dsg).build() ;
-
- try {
- server1.start();
- server2.start();
- } finally {
- try { server1.stop() ; } catch (Exception ex) {}
- try { server2.stop() ; } catch (Exception ex) {}
- }
- }
-
- // Two servers, two datasets.
- @Test
- public void multiple_03() {
- DatasetGraph dsg1 = dataset() ;
- DatasetGraph dsg2 = dataset() ;
- // Same name.
- int port1 = FusekiLib.choosePort() ;
- FusekiServer server1 = FusekiServer.create().port(port1).add("/ds", dsg1).build().start() ;
- Txn.executeWrite(dsg1, ()->dsg1.add(q1));
-
- int port2 = FusekiLib.choosePort() ;
- FusekiServer server2 = FusekiServer.create().port(port2).add("/ds", dsg2).build().start() ;
- Txn.executeWrite(dsg2, ()->dsg2.add(q2));
-
- query("http://localhost:"+port1+"/ds/", "SELECT * {?s ?p 1}", qExec->{
- ResultSet rs = qExec.execSelect() ;
- int x = ResultSetFormatter.consume(rs) ;
- assertEquals(1, x) ;
- }) ;
- query("http://localhost:"+port2+"/ds/", "SELECT * {?s ?p 1}", qExec->{
- ResultSet rs = qExec.execSelect() ;
- int x = ResultSetFormatter.consume(rs) ;
- assertEquals(0, x) ;
- }) ;
- server1.stop();
- // server2 still running
- query("http://localhost:"+port2+"/ds/", "SELECT * {?s ?p 2}", qExec->{
- ResultSet rs = qExec.execSelect() ;
- int x = ResultSetFormatter.consume(rs) ;
- assertEquals(1, x) ;
- }) ;
- server2.stop();
- }
-
- // Two servers, one dataset under two names.
- @Test
- public void multiple_04() {
- DatasetGraph dsg = dataset() ;
-
- int port1 = FusekiLib.choosePort() ;
- FusekiServer server1 = FusekiServer.create().port(port1).add("/ds1", dsg).build().start() ;
- Txn.executeWrite(dsg, ()->dsg.add(q1));
-
- int port2 = FusekiLib.choosePort() ;
- FusekiServer server2 = FusekiServer.create().port(port2).add("/ds2", dsg).build().start() ;
- Txn.executeWrite(dsg, ()->dsg.add(q2));
-
- query("http://localhost:"+port1+"/ds1", "SELECT * {?s ?p ?o}", qExec->{
- ResultSet rs = qExec.execSelect() ;
- int x = ResultSetFormatter.consume(rs) ;
- assertEquals(2, x) ;
- }) ;
- query("http://localhost:"+port2+"/ds2", "SELECT * {?s ?p ?o}", qExec->{
- ResultSet rs = qExec.execSelect() ;
- int x = ResultSetFormatter.consume(rs) ;
- assertEquals(2, x) ;
- }) ;
-
- server1.stop();
- server2.stop();
- }
-
- /** Create an HttpEntity for the graph */
- protected static HttpEntity graphToHttpEntity(final Graph graph) {
- final RDFFormat syntax = RDFFormat.TURTLE_BLOCKS ;
- ContentProducer producer = new ContentProducer() {
- @Override
- public void writeTo(OutputStream out) {
- RDFDataMgr.write(out, graph, syntax) ;
- }
- } ;
- EntityTemplate entity = new EntityTemplate(producer) ;
- ContentType ct = syntax.getLang().getContentType() ;
- entity.setContentType(ct.getContentType()) ;
- return entity ;
- }
-}
-
http://git-wip-us.apache.org/repos/asf/jena/blob/7e6d03af/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/ExtendFuseki_AddService_1.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/ExtendFuseki_AddService_1.java b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/ExtendFuseki_AddService_1.java
deleted file mode 100644
index e4f8e3d..0000000
--- a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/ExtendFuseki_AddService_1.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * 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.embedded.examples;
-
-import java.io.IOException;
-
-import org.apache.jena.atlas.io.IO;
-import org.apache.jena.atlas.logging.LogCtl;
-import org.apache.jena.atlas.web.HttpException;
-import org.apache.jena.atlas.web.TypedInputStream;
-import org.apache.jena.fuseki.FusekiLib;
-import org.apache.jena.fuseki.embedded.FusekiServer;
-import org.apache.jena.fuseki.server.Operation;
-import org.apache.jena.fuseki.servlets.ActionService;
-import org.apache.jena.riot.web.HttpOp;
-import org.apache.jena.sparql.core.DatasetGraphFactory;
-import org.apache.jena.util.FileUtils;
-import org.apache.jena.web.HttpSC;
-
-/**
- * This example show adding a custom operation to Fuseki.
- * <p>
- * There are two ways operations are routed: for a datset {@code /dataset}:
- * <ol>
- * <li>By endpoint name: {@code /dataset/endpoint}</li>
- * <li>By content type, when a POST is made on the {@code /dataset}.</li>
- * </ol>
- * The first is the usual way; the second is not a common pattern.
- * <p>
- * The second way is in addition to the endpoint; an endpoint is always required to
- * enabled routing by {@code Content-Type}.
- * <p>
- * The process for adding an operation is:
- * <ul>
- * <li>Register the operation with the server, with its implmementation.</li>
- * <li>Add the operation to a datasets.</li>
- * </ul>
- * <pre>
- * // Register operation.
- * Operation myOperation = Operation.register("Special", "Custom operation");
- * // An implementation to call
- * ActionService customHandler = new SpecialService();
- * // Builder pattern ...
- * FusekiServer server =
- * FusekiServer.create().port (1122)
- * // Register the operation with the server, together with implementation.
- * .registerOperation(myOperation, customHandler)
- * // Add a dataset
- * .add("/dataset", DatasetGraphFactory.createTxnMem(), true)
- * // Add operation by endpoint
- * .addOperation("/dataset", "endpoint", myOperation)
- * .build();
- * </pre>
- * @see SpecialService
- */
-
-public class ExtendFuseki_AddService_1 {
- static { LogCtl.setLog4j(); }
-
- // Endpoint dispatch only.
-
- // Choose free port for the example
- // Normally, this is fixed and published, and fixed in URLs.
- // To make the example portable, we ask the OS for a free port.
- static int PORT = FusekiLib.choosePort();
-
- // The server
- static String SERVER_URL = "http://localhost:"+PORT+"/";
-
- static String DATASET = "dataset";
-
- public static void main(String ...args) {
- // Create a new operation: operations are really just names (symbols). The code to
- // run is found by looking up the operation in a per-server table that gives the server-specific
- // implementation as an ActionService.
-
- Operation myOperation = Operation.register("Special", "Custom operation");
-
- // Service endpoint name.
- // This can be different for different datasets even in the same server.
- // c.f. {@code fuseki:serviceQuery}
-
- String endpointName = "special";
-
- // The handled for the new operation.
-
- ActionService customHandler = new SpecialService();
-
- FusekiServer server =
- FusekiServer.create().port(PORT)
- .verbose(true)
-
- // Register the new operation, and it's handler, but no Content-Type
- .registerOperation(myOperation, customHandler)
-
- // Add a dataset with the normal, default naming services
- // (/sparql, /query, /update, /upload, /data, /get)
- .add(DATASET, DatasetGraphFactory.createTxnMem(), true)
-
- // Add the custom service, mapping from endpoint to operation for a specific dataset.
- .addOperation(DATASET, endpointName, myOperation)
-
- // And build the server.
- .build();
-
- // Start the server. This does not block this thread.
- server.start();
-
- // Try some operations on the server using the service URL.
- String customOperationURL = SERVER_URL + DATASET + "/" + endpointName;
-
- try {
-
- // Service endpoint name : GET
- String s1 = HttpOp.execHttpGetString(customOperationURL);
- System.out.print(s1);
- if ( s1 == null )
- System.out.println();
-
- // Service endpoint name : POST
- try ( TypedInputStream stream = HttpOp.execHttpPostStream(customOperationURL, null, "text/plain") ) {
- String s2 = FileUtils.readWholeFileAsUTF8(stream);
- System.out.print(s2);
- if ( s2 == null )
- System.out.println();
- } catch (IOException ex) { IO.exception(ex); }
-
- // Service endpoint name. DELETE -> fails 405
- try {
- HttpOp.execHttpDelete(customOperationURL);
- throw new IllegalStateException("DELETE succeeded");
- } catch (HttpException ex) {
- if ( ex.getResponseCode() != HttpSC.METHOD_NOT_ALLOWED_405 )
- System.err.println("Unexpected HTTP Response Code: "+ex.getMessage());
- else
- System.out.println("DELETE rejected correctly: "+ex.getMessage());
- }
- } finally {
- server.stop();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/7e6d03af/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/ExtendFuseki_AddService_2.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/ExtendFuseki_AddService_2.java b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/ExtendFuseki_AddService_2.java
deleted file mode 100644
index 7c97132..0000000
--- a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/ExtendFuseki_AddService_2.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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.embedded.examples;
-
-import org.apache.jena.atlas.logging.LogCtl;
-import org.apache.jena.fuseki.FusekiLib;
-import org.apache.jena.fuseki.build.FusekiBuilder;
-import org.apache.jena.fuseki.embedded.FusekiServer;
-import org.apache.jena.fuseki.server.DataService;
-import org.apache.jena.fuseki.server.Operation;
-import org.apache.jena.fuseki.servlets.ActionService;
-import org.apache.jena.query.Query;
-import org.apache.jena.query.QueryExecution;
-import org.apache.jena.query.QueryExecutionFactory;
-import org.apache.jena.query.QueryFactory;
-import org.apache.jena.riot.web.HttpOp;
-import org.apache.jena.sparql.core.DatasetGraph;
-import org.apache.jena.sparql.core.DatasetGraphFactory;
-import org.apache.jena.sparql.engine.http.QueryExceptionHTTP;
-import org.apache.jena.web.HttpSC;
-
-/**
- * Create custom endpoint names, dispatch by {@code Content-Type}.
- * See also {@link ExtendFuseki_AddService_1} for more details.
- */
-
-public class ExtendFuseki_AddService_2 {
- static { LogCtl.setLog4j(); }
-
- // Endpoint dispatch only.
- static int PORT = FusekiLib.choosePort();
-
- // The server
- static String SERVER_URL = "http://localhost:"+PORT+"/";
-
- static String DATASET = "dataset";
-
- public static void main(String ...args) {
- // Register a new operation
-
- Operation myOperation = Operation.register("Special", "Custom operation");
-
- // Service endpoint names.
-
- String queryEndpoint = "q";
- String customEndpoint = "x";
-
- // Make a DataService with custom named for endpoints.
- // In this example, "q" for SPARQL query and "x" for our custom extension and no others.
- DatasetGraph dsg = DatasetGraphFactory.createTxnMem();
- DataService dataService = new DataService(dsg);
- // This would add the usual defaults.
- //FusekiBuilder.populateStdServices(dataService, true);
- FusekiBuilder.addServiceEP(dataService, myOperation, customEndpoint);
- FusekiBuilder.addServiceEP(dataService, Operation.Query, queryEndpoint);
-
- // The handled for the new operation.
- ActionService customHandler = new SpecialService();
-
- FusekiServer server =
- FusekiServer.create().port(PORT)
- .verbose(true)
- // Register the new operation, and it's handler
- .registerOperation(myOperation, customHandler)
-
- // The DataService.
- .add(DATASET, dataService)
-
- // And build the server.
- .build();
-
- server.start();
-
- // Try some operations on the server using the service URL.
- String customOperationURL = SERVER_URL + DATASET + "/" + customEndpoint;
- String queryOperationURL = SERVER_URL + DATASET + "/" + queryEndpoint;
-
- Query query = QueryFactory.create("ASK{}");
-
-
- try {
-
- // Try custom name - OK
- try ( QueryExecution qExec = QueryExecutionFactory.sparqlService(queryOperationURL, query) ) {
- qExec.execAsk();
- }
-
- // Try default name - 404
- try ( QueryExecution qExec = QueryExecutionFactory.sparqlService(SERVER_URL + DATASET + "/sparql", query) ) {
- qExec.execAsk();
- throw new RuntimeException("Didn't fail");
- } catch (QueryExceptionHTTP ex) {
- if ( ex.getResponseCode() != HttpSC.NOT_FOUND_404 ) {
- throw new RuntimeException("Not a 404", ex);
- }
- }
-
- // Service endpoint name : GET
- String s1 = HttpOp.execHttpGetString(customOperationURL);
- if ( s1 == null )
- throw new RuntimeException("Failed: "+customOperationURL);
-
- } finally {
- server.stop();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/7e6d03af/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/ExtendFuseki_AddService_3.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/ExtendFuseki_AddService_3.java b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/ExtendFuseki_AddService_3.java
deleted file mode 100644
index ce663a8..0000000
--- a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/ExtendFuseki_AddService_3.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.embedded.examples;
-
-import java.io.IOException;
-
-import org.apache.jena.atlas.io.IO;
-import org.apache.jena.atlas.logging.LogCtl;
-import org.apache.jena.atlas.web.TypedInputStream;
-import org.apache.jena.fuseki.FusekiLib;
-import org.apache.jena.fuseki.embedded.FusekiServer;
-import org.apache.jena.fuseki.server.Operation;
-import org.apache.jena.fuseki.servlets.ActionService;
-import org.apache.jena.riot.web.HttpOp;
-import org.apache.jena.sparql.core.DatasetGraphFactory;
-import org.apache.jena.util.FileUtils;
-
-/**
- * This example show adding a custom operation to Fuseki, with dispatch by {@code Content-Type}.
- * <p>
- * See {@link ExtendFuseki_AddService_1} fior a geenral description of the routing process.
- * @see SpecialService
- */
-
-public class ExtendFuseki_AddService_3 {
- static { LogCtl.setLog4j(); }
-
- static int PORT = FusekiLib.choosePort();
-
- // The server
- static String SERVER_URL = "http://localhost:"+PORT+"/";
-
- static String DATASET = "dataset";
-
- public static void main(String ...args) {
- // Create a new operation: operations are really just names (symbols). The code to
- // run is found by looking up the operation in a per-server table that gives the server-specific
- // implementation as an ActionService.
-
- Operation myOperation = Operation.register("Special", "Custom operation");
-
- // Service endpoint name.
- // This can be different for different datasets even in the same server.
- // c.f. {@code fuseki:serviceQuery}
-
- String endpointName = "special";
- String contentType = "application/special";
-
- // The handled for the new operation.
-
- ActionService customHandler = new SpecialService();
-
- FusekiServer server =
- FusekiServer.create().port(PORT)
- .verbose(true)
-
- // Register the new operation, with content type and handler
- .registerOperation(myOperation, contentType, customHandler)
-
- // Add a dataset with the normal, default naming services
- // (/sparql, /query, /update, /upload, /data, /get)
- .add(DATASET, DatasetGraphFactory.createTxnMem(), true)
-
- // Add the custom service, mapping from endpoint to operation for a specific dataset.
- // Required when when routing via Content-Type.
- .addOperation(DATASET, endpointName, myOperation)
-
- // And build the server.
- .build();
-
- // Start the server. This does not block this thread.
- server.start();
-
- // Try some operations on the server using the service URL.
- String datasetURL = SERVER_URL + DATASET;
- //String customOperationURL = SERVER_URL + DATASET + "/" + endpointName;
-
- try {
-
- // Dataset endpoint name : POST, with Content-type.
- try ( TypedInputStream stream = HttpOp.execHttpPostStream(datasetURL, contentType, "", "text/plain") ) {
- String s2 = FileUtils.readWholeFileAsUTF8(stream);
- System.out.print(s2);
- if ( s2 == null )
- System.out.println();
- } catch (IOException ex) { IO.exception(ex); }
- } finally {
- server.stop();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/7e6d03af/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/SpecialService.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/SpecialService.java b/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/SpecialService.java
deleted file mode 100644
index 239e6d7..0000000
--- a/jena-fuseki2/jena-fuseki-embedded/src/test/java/org/apache/jena/fuseki/embedded/examples/SpecialService.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.embedded.examples;
-
-import java.io.IOException;
-
-import org.apache.jena.atlas.logging.LogCtl;
-import org.apache.jena.fuseki.servlets.ActionREST;
-import org.apache.jena.fuseki.servlets.HttpAction;
-import org.apache.jena.fuseki.servlets.ServletOps;
-import org.apache.jena.riot.WebContent;
-import org.apache.jena.web.HttpSC;
-
-public class SpecialService extends ActionREST {
- static { LogCtl.setLog4j(); }
-
- @Override
- protected void doGet(HttpAction action) {
- action.response.setStatus(HttpSC.OK_200);
- try {
- action.response.setContentType(WebContent.contentTypeTextPlain);
- action.response.getOutputStream().println(" ** Hello world (GET) **");
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- protected void doHead(HttpAction action) {
- action.response.setStatus(HttpSC.OK_200);
- action.response.setContentType(WebContent.contentTypeTextPlain);
- }
-
- @Override
- protected void doPost(HttpAction action) {
- action.response.setStatus(HttpSC.OK_200);
- try {
- action.response.setContentType(WebContent.contentTypeTextPlain);
- action.response.getOutputStream().println(" ** Hello world (POST) **");
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- protected void doPatch(HttpAction action) { notSupported(action); }
-
- @Override
- protected void doDelete(HttpAction action) { notSupported(action); }
-
- @Override
- protected void doPut(HttpAction action) { notSupported(action); }
-
- @Override
- protected void doOptions(HttpAction action) { notSupported(action); }
-
- @Override
- protected void validate(HttpAction action) { }
-
- private void notSupported(HttpAction action) {
- ServletOps.errorMethodNotAllowed(action.getMethod()+" "+action.getActionURI());
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/7e6d03af/jena-fuseki2/jena-fuseki-embedded/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/src/test/resources/log4j.properties b/jena-fuseki2/jena-fuseki-embedded/src/test/resources/log4j.properties
deleted file mode 100644
index e84e60e..0000000
--- a/jena-fuseki2/jena-fuseki-embedded/src/test/resources/log4j.properties
+++ /dev/null
@@ -1,40 +0,0 @@
-# Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
-
-# Plain output to stdout
-log4j.appender.jena.plainstdout=org.apache.log4j.ConsoleAppender
-log4j.appender.jena.plainstdout.target=System.out
-log4j.appender.jena.plainstdout.layout=org.apache.log4j.PatternLayout
-log4j.appender.jena.plainstdout.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] %-10c{1} %-5p %m%n
-## %d{ISO8601} -- includes "ss,sss"
-## log4j.appender.jena.plainstdout.layout.ConversionPattern=[%d{ISO8601}] %-10c{1} %-5p %m%n
-
-# Unadorned, for the NCSA requests log.
-log4j.appender.fuseki.plain=org.apache.log4j.ConsoleAppender
-log4j.appender.fuseki.plain.target=System.out
-log4j.appender.fuseki.plain.layout=org.apache.log4j.PatternLayout
-log4j.appender.fuseki.plain.layout.ConversionPattern=%m%n
-
-log4j.rootLogger=INFO, jena.plainstdout
-log4j.logger.org.apache.jena=WARN
-log4j.logger.org.apache.jena.fuseki=INFO
-
-# Others
-log4j.logger.org.eclipse.jetty=WARN
-log4j.logger.org.apache.shiro=WARN
-
-# Fuseki System logs.
-log4j.logger.org.apache.jena.fuseki.Server=INFO
-log4j.logger.org.apache.jena.fuseki.Fuseki=INFO
-log4j.logger.org.apache.jena.fuseki.Admin=INFO
-log4j.logger.org.apache.jena.fuseki.Validate=INFO
-log4j.logger.org.apache.jena.fuseki.Config=INFO
-
-# NCSA Request log.
-log4j.additivity.org.apache.jena.fuseki.Request=false
-log4j.logger.org.apache.jena.fuseki.Request=OFF, fuseki.plain
-
-# TDB
-log4j.logger.org.apache.jena.tdb.loader=INFO
-## Parser output
-log4j.additivity.org.apache.jena.riot=false
-log4j.logger.org.apache.jena.riot=INFO, jena.plainstdout
http://git-wip-us.apache.org/repos/asf/jena/blob/7e6d03af/jena-fuseki2/jena-fuseki-embedded/testing/FusekiEmbedded/config.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/testing/FusekiEmbedded/config.ttl b/jena-fuseki2/jena-fuseki-embedded/testing/FusekiEmbedded/config.ttl
deleted file mode 100644
index 5a7f84a..0000000
--- a/jena-fuseki2/jena-fuseki-embedded/testing/FusekiEmbedded/config.ttl
+++ /dev/null
@@ -1,18 +0,0 @@
-@prefix : <#> .
-@prefix fuseki: <http://jena.apache.org/fuseki#> .
-@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix ja: <http://jena.hpl.hp.com/2005/11/Assembler#> .
-@prefix tdb: <http://jena.hpl.hp.com/2008/tdb#> .
-
-<#serviceInMemory> rdf:type fuseki:Service;
- rdfs:label "test";
- fuseki:name "FuTest";
- fuseki:serviceQuery "query";
- fuseki:serviceUpdate "update";
- fuseki:serviceUpload "upload" ;
- fuseki:dataset <#dataset> ;
-.
-
-<#dataset> rdf:type ja:RDFDataset;
-.
http://git-wip-us.apache.org/repos/asf/jena/blob/7e6d03af/jena-fuseki2/jena-fuseki-embedded/testing/FusekiEmbedded/test.txt
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-embedded/testing/FusekiEmbedded/test.txt b/jena-fuseki2/jena-fuseki-embedded/testing/FusekiEmbedded/test.txt
deleted file mode 100644
index 1a98ff9..0000000
--- a/jena-fuseki2/jena-fuseki-embedded/testing/FusekiEmbedded/test.txt
+++ /dev/null
@@ -1 +0,0 @@
-Test data.
http://git-wip-us.apache.org/repos/asf/jena/blob/7e6d03af/jena-fuseki2/jena-fuseki-main/pom.xml
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/pom.xml b/jena-fuseki2/jena-fuseki-main/pom.xml
new file mode 100644
index 0000000..25f3d5e
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-main/pom.xml
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <name>Apache Jena - Fuseki Server</name>
+ <artifactId>jena-fuseki-main</artifactId>
+
+ <parent>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-fuseki</artifactId>
+ <version>3.9.0-SNAPSHOT</version>
+ </parent>
+
+ <packaging>jar</packaging>
+
+ <properties>
+ <automatic.module.name>org.apache.jena.jena-fuseki-main</automatic.module.name>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-fuseki-core</artifactId>
+ <version>3.9.0-SNAPSHOT</version>
+
+ <exclusions>
+
+ <!-- Parts of Jena not needed but picked up via jena-fuseki-core.
+ The application can put back any of these if it wants to use
+ them, e.g. a text-indexed dataset, providing the version is compatible.
+ -->
+
+ <exclusion>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-text</artifactId>
+ </exclusion>
+
+ <!-- Jena uses SLF4J as its API. Exclude any logging bindings picked up via Jena.
+ For example, jena-fuseki-core has logging output and so some logging provider.
+ For embedded use, it is the enclosing application that chooses the kind of
+ logging system.
+ -->
+ <!--
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ </exclusion>
+ -->
+ </exclusions>
+
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-cmds</artifactId>
+ <version>3.9.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <optional>true</optional>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifestEntries>
+ <Automatic-Module-Name>${automatic.module.name}</Automatic-Module-Name>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar-no-fork</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>attach-sources-test</id>
+ <goals>
+ <goal>test-jar-no-fork</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>**/TS_*.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+
+ </plugins>
+
+ </build>
+
+</project>
http://git-wip-us.apache.org/repos/asf/jena/blob/7e6d03af/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
new file mode 100644
index 0000000..cd9b9e0
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
@@ -0,0 +1,597 @@
+/*
+ * 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.main;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import javax.servlet.Filter;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServlet;
+
+import org.apache.jena.atlas.lib.Pair;
+import org.apache.jena.fuseki.Fuseki;
+import org.apache.jena.fuseki.FusekiConfigException;
+import org.apache.jena.fuseki.FusekiException;
+import org.apache.jena.fuseki.build.FusekiBuilder;
+import org.apache.jena.fuseki.build.FusekiConfig;
+import org.apache.jena.fuseki.ctl.ActionPing;
+import org.apache.jena.fuseki.ctl.ActionStats;
+import org.apache.jena.fuseki.jetty.FusekiErrorHandler1;
+import org.apache.jena.fuseki.jetty.JettyLib;
+import org.apache.jena.fuseki.server.DataAccessPoint;
+import org.apache.jena.fuseki.server.DataAccessPointRegistry;
+import org.apache.jena.fuseki.server.DataService;
+import org.apache.jena.fuseki.server.FusekiVocab;
+import org.apache.jena.fuseki.server.Operation;
+import org.apache.jena.fuseki.servlets.ActionService;
+import org.apache.jena.fuseki.servlets.FusekiFilter;
+import org.apache.jena.fuseki.servlets.ServiceDispatchRegistry;
+import org.apache.jena.query.Dataset;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.assembler.AssemblerUtils;
+import org.apache.jena.sparql.util.graph.GraphUtils;
+import org.eclipse.jetty.security.SecurityHandler;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.servlet.DefaultServlet;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+
+/**
+ * Embedded Fuseki server. This is a Fuseki server running with a pre-configured set of
+ * datasets and services. There is no admin UI and no security.
+ * <p>
+ * To create a embedded sever, use {@link FusekiServer} ({@link #make} is a
+ * packaging of a call to {@link FusekiServer} for the case of one dataset,
+ * responding to localhost only).
+ * <p>
+ * The application should call {@link #start()} to actually start the server
+ * (it will run in the background : see {@link #join}).
+ * <p>Example:
+ * <pre>
+ * DatasetGraph dsg = ...;
+ * FusekiServer server = FusekiServer.create()
+ * .port(1234)
+ * .add("/ds", dsg)
+ * .build();
+ * server.start();
+ * </pre>
+ * Compact form (use the builder pattern above to get more flexibility):
+ * <pre>
+ * FusekiServer.make(1234, "/ds", dsg).start();
+ * </pre>
+ *
+ */
+public class FusekiServer {
+ /** Construct a Fuseki server for one dataset.
+ * It only responds to localhost.
+ * The returned server has not been started.
+ */
+ static public FusekiServer make(int port, String name, DatasetGraph dsg) {
+ return create()
+ .port(port)
+ .loopback(true)
+ .add(name, dsg)
+ .build();
+ }
+
+ /** Return a builder, with the default choices of actions available. */
+ public static Builder create() {
+ return new Builder();
+ }
+
+ /**
+ * Return a builder, with a custom set of operation-action mappings. An endpoint must
+ * still be created for the server to be able to provide the action. An endpoint
+ * dispatches to an operation, and an operation maps to an implementation. This is a
+ * specialised operation - normal use is the operation {@link #create()}.
+ */
+ public static Builder create(ServiceDispatchRegistry serviceDispatchRegistry) {
+ return new Builder(serviceDispatchRegistry);
+ }
+
+ public final Server server;
+ private int port;
+
+ private FusekiServer(int port, Server server) {
+ this.server = server;
+ // This should be the same.
+ //this.port = ((ServerConnector)server.getConnectors()[0]).getPort();
+ this.port = port;
+ }
+
+ /**
+ * Return the port begin used.
+ * This will be the give port, which defaults to 3330, or
+ * the one actually allocated if the port was 0 ("choose a free port").
+ */
+ public int getPort() {
+ return port;
+ }
+
+ /** Get the underlying Jetty server which has also been set up. */
+ public Server getJettyServer() {
+ return server;
+ }
+
+ /** Get the {@link ServletContext}.
+ * Adding new servlets is possible with care.
+ */
+ public ServletContext getServletContext() {
+ return ((ServletContextHandler)server.getHandler()).getServletContext();
+ }
+
+ /** Get the {@link DataAccessPointRegistry}.
+ * This method is intended for inspecting the registry.
+ */
+ public DataAccessPointRegistry getDataAccessPointRegistry() {
+ return DataAccessPointRegistry.get(getServletContext());
+ }
+
+ /** Get the {@link DataAccessPointRegistry}.
+ * This method is intended for inspecting the registry.
+ */
+ public ServiceDispatchRegistry getServiceDispatchRegistry() {
+ return ServiceDispatchRegistry.get(getServletContext());
+ }
+
+ /** Start the server - the server continues to run after this call returns.
+ * To synchronise with the server stopping, call {@link #join}.
+ */
+ public FusekiServer start() {
+ try { server.start(); }
+ catch (Exception e) { throw new FusekiException(e); }
+ if ( port == 0 )
+ port = ((ServerConnector)server.getConnectors()[0]).getLocalPort();
+ Fuseki.serverLog.info("Start Fuseki (port="+port+")");
+ return this;
+ }
+
+ /** Stop the server. */
+ public void stop() {
+ Fuseki.serverLog.info("Stop Fuseki (port="+port+")");
+ try { server.stop(); }
+ catch (Exception e) { throw new FusekiException(e); }
+ }
+
+ /** Wait for the server to exit. This call is blocking. */
+ public void join() {
+ try { server.join(); }
+ catch (Exception e) { throw new FusekiException(e); }
+ }
+
+ /** FusekiServer.Builder */
+ public static class Builder {
+ private DataAccessPointRegistry dataAccessPoints = new DataAccessPointRegistry();
+ private final ServiceDispatchRegistry serviceDispatch;
+ // Default values.
+ private int serverPort = 3330;
+ private boolean networkLoopback = false;
+ private boolean verbose = false;
+ private boolean withStats = false;
+ private boolean withPing = false;
+ // Other servlets to add.
+ private List<Pair<String, HttpServlet>> servlets = new ArrayList<>();
+ private List<Pair<String, Filter>> filters = new ArrayList<>();
+
+ private String contextPath = "/";
+ private String staticContentDir = null;
+ private SecurityHandler securityHandler = null;
+ private Map<String, Object> servletAttr = new HashMap<>();
+
+ // Builder with standard operation-action mapping.
+ Builder() {
+ this.serviceDispatch = new ServiceDispatchRegistry(true);
+ }
+
+ // Builder with provided operation-action mapping.
+ Builder(ServiceDispatchRegistry serviceDispatch) {
+ // Isolate.
+ this.serviceDispatch = new ServiceDispatchRegistry(serviceDispatch);
+ }
+
+ /** Set the port to run on.
+ * @deprecated Use {@link #port}.
+ */
+ @Deprecated
+ public Builder setPort(int port) {
+ return port(port);
+ }
+
+ /** Set the port to run on. */
+ public Builder port(int port) {
+ if ( port < 0 )
+ throw new IllegalArgumentException("Illegal port="+port+" : Port must be greater than or equal to zero.");
+ this.serverPort = port;
+ return this;
+ }
+
+ /** Context path to Fuseki. If it's "/" then Fuseki URL look like
+ * "http://host:port/dataset/query" else "http://host:port/path/dataset/query"
+ * @deprecated Use {@link #contextPath}.
+ */
+ @Deprecated
+ public Builder setContextPath(String path) {
+ return contextPath(path);
+ }
+
+ /** Context path to Fuseki. If it's "/" then Fuseki URL look like
+ * "http://host:port/dataset/query" else "http://host:port/path/dataset/query"
+ */
+ public Builder contextPath(String path) {
+ requireNonNull(path, "path");
+ this.contextPath = path;
+ return this;
+ }
+
+ /** Restrict the server to only responding to the localhost interface.
+ * @deprecated Use {@link #networkLoopback}.
+ */
+ @Deprecated
+ public Builder setLoopback(boolean loopback) {
+ return loopback(loopback);
+ }
+
+ /** Restrict the server to only responding to the localhost interface. */
+ public Builder loopback(boolean loopback) {
+ this.networkLoopback = loopback;
+ return this;
+ }
+
+ /** Set the location (filing system directory) to serve static file from.
+ * @deprecated Use {@link #staticFileBase}.
+ */
+ @Deprecated
+ public Builder setStaticFileBase(String directory) {
+ return staticFileBase(directory);
+ }
+
+ /** Set the location (filing system directory) to serve static file from. */
+ public Builder staticFileBase(String directory) {
+ requireNonNull(directory, "directory");
+ this.staticContentDir = directory;
+ return this;
+ }
+
+ /** Set a Jetty SecurityHandler.
+ * <p>
+ * By default, the server runs with no security.
+ * @deprecated Use {@link #staticFileBase}.
+ */
+ @Deprecated
+ public Builder setSecurityHandler(SecurityHandler securityHandler) {
+ return securityHandler(securityHandler);
+ }
+
+ /** Set a Jetty SecurityHandler.
+ * <p>
+ * By default, the server runs with no security.
+ * This is more for using the basic server for testing.
+ * The full Fuseki server provides security with Apache Shiro
+ * and a defensive reverse proxy (e.g. Apache httpd) in front of the Jetty server
+ * can also be used, which provides a wide variety of proven security options.
+ */
+ public Builder securityHandler(SecurityHandler securityHandler) {
+ requireNonNull(securityHandler, "securityHandler");
+ this.securityHandler = securityHandler;
+ return this;
+ }
+
+ /** Set verbose logging
+ * @deprecated Use {@link #verbose(boolean)}.
+ */
+ @Deprecated
+ public Builder setVerbose(boolean verbose) {
+ return verbose(verbose);
+ }
+
+ /** Set verbose logging */
+ public Builder verbose(boolean verbose) {
+ this.verbose = verbose;
+ return this;
+ }
+
+ /** Add the "/$/stats" servlet that responds with stats about the server,
+ * including counts of all calls made.
+ */
+ public Builder enableStats(boolean withStats) {
+ this.withStats = withStats;
+ return this;
+ }
+
+ /** Add the "/$/ping" servlet that responds to HTTP very efficiently.
+ * This is useful for testing whether a server is alive, for example, from a load balancer.
+ */
+ public Builder enablePing(boolean withPing) {
+ this.withPing = withPing;
+ return this;
+ }
+
+ /**
+ * Add the dataset with given name and a default set of services including update.
+ * This is equivalent to {@code add(name, dataset, true)}.
+ */
+ public Builder add(String name, Dataset dataset) {
+ requireNonNull(name, "name");
+ requireNonNull(dataset, "dataset");
+ return add(name, dataset.asDatasetGraph());
+ }
+
+ /**
+ * Add the {@link DatasetGraph} with given name and a default set of services including update.
+ * This is equivalent to {@code add(name, dataset, true)}.
+ */
+ /** Add the dataset with given name and a default set of services including update */
+ public Builder add(String name, DatasetGraph dataset) {
+ requireNonNull(name, "name");
+ requireNonNull(dataset, "dataset");
+ return add(name, dataset, true);
+ }
+
+ /**
+ * Add the dataset with given name and a default set of services and enabling
+ * update if allowUpdate=true.
+ */
+ public Builder add(String name, Dataset dataset, boolean allowUpdate) {
+ requireNonNull(name, "name");
+ requireNonNull(dataset, "dataset");
+ return add(name, dataset.asDatasetGraph(), allowUpdate);
+ }
+
+ /**
+ * Add the dataset with given name and a default set of services and enabling
+ * update if allowUpdate=true.
+ */
+ public Builder add(String name, DatasetGraph dataset, boolean allowUpdate) {
+ requireNonNull(name, "name");
+ requireNonNull(dataset, "dataset");
+ DataService dSrv = FusekiBuilder.buildDataServiceStd(dataset, allowUpdate);
+ return add(name, dSrv);
+ }
+
+ /** Add a data service that includes dataset and service names.
+ * A {@link DataService} allows for choices of the various endpoint names.
+ */
+ public Builder add(String name, DataService dataService) {
+ requireNonNull(name, "name");
+ requireNonNull(dataService, "dataService");
+ return add$(name, dataService);
+ }
+
+ private Builder add$(String name, DataService dataService) {
+ name = DataAccessPoint.canonical(name);
+ if ( dataAccessPoints.isRegistered(name) )
+ throw new FusekiConfigException("Data service name already registered: "+name);
+ DataAccessPoint dap = new DataAccessPoint(name, dataService);
+ dataAccessPoints.register(dap);
+ return this;
+ }
+
+ /**
+ * Configure using a Fuseki services/datasets assembler file.
+ * <p>
+ * The application is responsible for ensuring a correct classpath. For example,
+ * including a dependency on {@code jena-text} if the configuration file includes
+ * a text index.
+ */
+ public Builder parseConfigFile(String filename) {
+ requireNonNull(filename, "filename");
+ Model model = AssemblerUtils.readAssemblerFile(filename);
+
+ // Process server context
+ Resource server = GraphUtils.getResourceByType(model, FusekiVocab.tServer);
+ if ( server != null )
+ AssemblerUtils.setContext(server, Fuseki.getContext()) ;
+
+ // Process services, whether via server ja:services or, if absent, by finding by type.
+ List<DataAccessPoint> x = FusekiConfig.servicesAndDatasets(model);
+ // Unbundle so that they accumulate.
+ x.forEach(dap->add(dap.getName(), dap.getDataService()));
+ return this;
+ }
+
+ /**
+ * Add the given servlet with the {@code pathSpec}. These servlets are added so
+ * that they are checked after the Fuseki filter for datasets and before the
+ * static content handler (which is the last servlet) used for
+ * {@link #setStaticFileBase(String)}.
+ */
+ public Builder addServlet(String pathSpec, HttpServlet servlet) {
+ requireNonNull(pathSpec, "pathSpec");
+ requireNonNull(servlet, "servlet");
+ servlets.add(Pair.create(pathSpec, servlet));
+ return this;
+ }
+
+ /**
+ * Add a servlet attribute. Pass a value of null to remove any existing binding.
+ */
+ public Builder addServletAttribute(String attrName, Object value) {
+ requireNonNull(attrName, "attrName");
+ if ( value != null )
+ servletAttr.put(attrName, value);
+ else
+ servletAttr.remove(attrName);
+ return this;
+ }
+
+ /**
+ * Add a filter with the pathSpec. Note that Fuseki dispatch uses a servlet filter
+ * which is the last in the filter chain.
+ */
+ public Builder addFilter(String pathSpec, Filter filter) {
+ requireNonNull(pathSpec, "pathSpec");
+ requireNonNull(filter, "filter");
+ filters.add(Pair.create(pathSpec, filter));
+ return this;
+ }
+
+ /**
+ * Add an operation and handler to the server. This does not enable it for any dataset.
+ * <p>
+ * To associate an operation with a dataset, call {@link #addOperation} after adding the dataset.
+ *
+ * @see #addOperation
+ */
+ public Builder registerOperation(Operation operation, ActionService handler) {
+ registerOperation(operation, null, handler);
+ return this;
+ }
+
+ /**
+ * Add an operation to the server, together with its triggering Content-Type (may be null) and servlet handler.
+ * <p>
+ * To associate an operation with a dataset, call {@link #addOperation} after adding the dataset.
+ *
+ * @see #addOperation
+ */
+ public Builder registerOperation(Operation operation, String contentType, ActionService handler) {
+ Objects.requireNonNull(operation, "operation");
+ if ( handler == null )
+ serviceDispatch.unregister(operation);
+ else
+ serviceDispatch.register(operation, contentType, handler);
+ return this;
+ }
+
+ /**
+ * Create an endpoint on the dataset.
+ * The operation must already be registered with the builder.
+ * @see #registerOperation(Operation, ActionService)
+ */
+ public Builder addOperation(String datasetName, String endpointName, Operation operation) {
+ Objects.requireNonNull(datasetName, "datasetName");
+ Objects.requireNonNull(endpointName, "endpointName");
+
+ String name = DataAccessPoint.canonical(datasetName);
+
+ if ( ! serviceDispatch.isRegistered(operation) )
+ throw new FusekiConfigException("Operation not registered: "+operation.getName());
+
+ if ( ! dataAccessPoints.isRegistered(name) )
+ throw new FusekiConfigException("Dataset not registered: "+datasetName);
+ DataAccessPoint dap = dataAccessPoints.get(name);
+ FusekiBuilder.addServiceEP(dap.getDataService(), operation, endpointName);
+ return this;
+ }
+
+ /**
+ * Build a server according to the current description.
+ */
+ public FusekiServer build() {
+ ServletContextHandler handler = buildFusekiContext();
+ // Use HandlerCollection for several ServletContextHandlers and thus several ServletContext.
+ Server server = jettyServer(serverPort, networkLoopback);
+ server.setHandler(handler);
+ return new FusekiServer(serverPort, server);
+ }
+
+ /** Build one configured Fuseki in one unit - same ServletContext, same dispatch ContextPath */
+ private ServletContextHandler buildFusekiContext() {
+ ServletContextHandler handler = buildServletContext(contextPath);
+ ServletContext cxt = handler.getServletContext();
+ Fuseki.setVerbose(cxt, verbose);
+ servletAttr.forEach((n,v)->cxt.setAttribute(n, v));
+ // Clone to isolate from any future changes.
+ ServiceDispatchRegistry.set(cxt, new ServiceDispatchRegistry(serviceDispatch));
+ DataAccessPointRegistry.set(cxt, new DataAccessPointRegistry(dataAccessPoints));
+ JettyLib.setMimeTypes(handler);
+ servletsAndFilters(handler);
+ // Start services.
+ DataAccessPointRegistry.get(cxt).forEach((name, dap)->dap.getDataService().goActive());
+ return handler;
+ }
+
+ /** Build a ServletContextHandler */
+ private ServletContextHandler buildServletContext(String contextPath) {
+ if ( contextPath == null || contextPath.isEmpty() )
+ contextPath = "/";
+ else if ( !contextPath.startsWith("/") )
+ contextPath = "/" + contextPath;
+ ServletContextHandler context = new ServletContextHandler();
+ context.setDisplayName(Fuseki.servletRequestLogName);
+ context.setErrorHandler(new FusekiErrorHandler1());
+ context.setContextPath(contextPath);
+ if ( securityHandler != null )
+ context.setSecurityHandler(securityHandler);
+ return context;
+ }
+
+ /** Add servlets and servlet filters, including the {@link FusekiFilter} */
+ private void servletsAndFilters(ServletContextHandler context) {
+ // Fuseki dataset services filter
+ // This goes as the filter at the end of any filter chaining.
+ FusekiFilter ff = new FusekiFilter();
+ addFilter(context, "/*", ff);
+
+ if ( withStats )
+ addServlet(context, "/$/stats", new ActionStats());
+ if ( withPing )
+ addServlet(context, "/$/ping", new ActionPing());
+
+ servlets.forEach(p->addServlet(context, p.getLeft(), p.getRight()));
+ filters.forEach (p-> addFilter(context, p.getLeft(), p.getRight()));
+
+ if ( staticContentDir != null ) {
+ DefaultServlet staticServlet = new DefaultServlet();
+ ServletHolder staticContent = new ServletHolder(staticServlet);
+ staticContent.setInitParameter("resourceBase", staticContentDir);
+ context.addServlet(staticContent, "/");
+ }
+ }
+
+ private static void addServlet(ServletContextHandler context, String pathspec, HttpServlet httpServlet) {
+ ServletHolder sh = new ServletHolder(httpServlet);
+ context.addServlet(sh, pathspec);
+ }
+
+ private void addFilter(ServletContextHandler context, String pathspec, Filter filter) {
+ FilterHolder h = new FilterHolder(filter);
+ context.addFilter(h, pathspec, null);
+ }
+
+ /** Jetty server with one connector/port. */
+ private static Server jettyServer(int port, boolean loopback) {
+ Server server = new Server();
+ HttpConnectionFactory f1 = new HttpConnectionFactory();
+ // Some people do try very large operations ... really, should use POST.
+ f1.getHttpConfiguration().setRequestHeaderSize(512 * 1024);
+ f1.getHttpConfiguration().setOutputBufferSize(1024 * 1024);
+ // Do not add "Server: Jetty(....) when not a development system.
+ if ( ! Fuseki.outputJettyServerHeader )
+ f1.getHttpConfiguration().setSendServerVersion(false);
+ ServerConnector connector = new ServerConnector(server, f1);
+ connector.setPort(port);
+ server.addConnector(connector);
+ if ( loopback )
+ connector.setHost("localhost");
+ return server;
+ }
+ }
+}