You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by rv...@apache.org on 2015/01/14 11:31:47 UTC
[45/93] [abbrv] [partial] jena git commit: Maven modules for Fuseki2
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/JsonDescription.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/JsonDescription.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/JsonDescription.java
new file mode 100644
index 0000000..f54ead2
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/JsonDescription.java
@@ -0,0 +1,73 @@
+/**
+ * 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.mgt;
+
+import java.util.List ;
+
+import org.apache.jena.atlas.json.JsonBuilder ;
+import org.apache.jena.fuseki.server.DataAccessPoint ;
+import org.apache.jena.fuseki.server.DataAccessPointRegistry ;
+import org.apache.jena.fuseki.server.Endpoint ;
+import org.apache.jena.fuseki.server.OperationName ;
+
+/** Create a description of a service */
+public class JsonDescription {
+
+ public static void arrayDatasets(JsonBuilder builder, DataAccessPointRegistry registry) {
+ builder.startArray() ;
+ for ( String ds : registry.keys() ) {
+ DataAccessPoint access = DataAccessPointRegistry.get().get(ds) ;
+ JsonDescription.describe(builder, access) ;
+ }
+ builder.finishArray() ;
+ }
+
+ public static void describe(JsonBuilder builder, DataAccessPoint access) {
+ builder.startObject() ;
+ builder.key(JsonConst.dsName).value(access.getName()) ;
+
+ builder.key(JsonConst.dsState).value(access.getDataService().isAcceptingRequests()) ;
+
+ builder.key(JsonConst.dsService) ;
+ builder.startArray() ;
+
+ for ( OperationName opName : access.getDataService().getOperations() ) {
+ List<Endpoint> endpoints = access.getDataService().getOperation(opName) ;
+ describe(builder, opName, endpoints) ;
+ }
+ builder.finishArray() ;
+ builder.finishObject() ;
+ }
+
+ private static void describe(JsonBuilder builder, OperationName opName, List<Endpoint> endpoints) {
+ builder.startObject() ;
+
+ builder.key(JsonConst.srvType).value(opName.name()) ;
+ builder.key(JsonConst.srvDescription).value(opName.getDescription()) ;
+
+ builder.key(JsonConst.srvEndpoints) ;
+ builder.startArray() ;
+ for ( Endpoint endpoint : endpoints )
+ builder.value(endpoint.getEndpoint()) ;
+ builder.finishArray() ;
+
+ builder.finishObject() ;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtConst.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtConst.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtConst.java
new file mode 100644
index 0000000..e398894
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtConst.java
@@ -0,0 +1,30 @@
+/**
+ * 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.mgt;
+
+/** Various contants used in the admin functions */
+public class MgtConst {
+ public static final String opDump = "dump" ;
+ public static final String opPing = "ping" ;
+
+ public static final String opStats = "stats" ;
+ public static final String opDatasets = "datasets" ;
+ public static final String opServer = "server" ;
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtJMX.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtJMX.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtJMX.java
new file mode 100644
index 0000000..f9023fe
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/MgtJMX.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.mgt ;
+
+
+public class MgtJMX
+{
+ public static void removeJMX() { }
+
+// public static void addJMX() {
+// DatasetRegistry registry = DatasetRegistry.get() ;
+// for (String ds : registry.keys()) {
+// DataAccessPoint dsRef = registry.get(ds) ;
+// addJMX(dsRef) ;
+// }
+// }
+//
+// private static void addJMX(DataAccessPoint dapt) {
+// String x = datasetNames ;
+// // if ( x.startsWith("/") )
+// // x = x.substring(1) ;
+// ARQMgt.register(Fuseki.PATH + ".dataset:name=" + x, dapt) ;
+// // For all endpoints
+// for (ServiceRef sRef : dapt.getServiceRefs()) {
+// ARQMgt.register(Fuseki.PATH + ".dataset:name=" + x + "/" + sRef.name, sRef) ;
+// }
+// }
+//
+// public static void removeJMX() {
+// DatasetRegistry registry = DatasetRegistry.get() ;
+// for (String ds : registry.keys()) {
+// DataAccessPoint ref = registry.get(ds) ;
+// removeJMX(ref) ;
+// }
+// }
+//
+// private static void removeJMX(DatasetRef dsRef) {
+// String x = dsRef.getName() ;
+// ARQMgt.unregister(Fuseki.PATH + ".dataset:name=" + x) ;
+// for (ServiceRef sRef : dsRef.getServiceRefs()) {
+// ARQMgt.unregister(Fuseki.PATH + ".dataset:name=" + x + "/" + sRef.name) ;
+// }
+// }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/DatasetGraphSwitchable.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/DatasetGraphSwitchable.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/DatasetGraphSwitchable.java
new file mode 100644
index 0000000..0e075f6
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/DatasetGraphSwitchable.java
@@ -0,0 +1,88 @@
+/**
+ * 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.migrate;
+
+import java.util.concurrent.atomic.AtomicReference ;
+
+import org.apache.jena.fuseki.FusekiException ;
+
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.DatasetGraphWrapper ;
+
+public class DatasetGraphSwitchable extends DatasetGraphWrapper {
+ // **** Associated query engine factory - QueryEngineFactoryWrapper
+ // which executes on the unwrapped DSG.
+
+ // *** Modify DatasetGraphWrapper to use a get().
+
+ // Time to have DatasetGraph.getQueryDataset
+ private final DatasetGraph dsg1 ;
+ private final DatasetGraph dsg2 ;
+ private final AtomicReference<DatasetGraph> current = new AtomicReference<DatasetGraph>() ;
+
+ // Change DatasetGraphWrapper to use protected get()
+
+ public DatasetGraphSwitchable(DatasetGraph dsg1, DatasetGraph dsg2) {
+ super(null) ;
+ if ( dsg1 == null )
+ // Personally I think IllegalArgumentException is more
+ // appropriate, with NPE for unexpected use of null
+ // but convention says ....
+ throw new NullPointerException("First argument is null") ;
+ if ( dsg2 == null )
+ throw new NullPointerException("Second argument is null") ;
+ this.dsg1 = dsg1 ;
+ this.dsg2 = dsg2 ;
+ set(dsg1) ;
+ }
+
+ private void set(DatasetGraph dsg) { current.set(dsg) ; }
+
+ /** Change to using the other dataset */
+ public void flip() {
+ // Don't worry about concurrent calls to flip()
+ // The outcome will be that one call wins (the actual second caller)
+ // and not corrupted data. Noet that get() is only called once per
+ // redirection.
+
+ // if dsg1 -- (expected, update)
+ if ( current.compareAndSet(dsg1, dsg2) )
+ return ;
+ // if dsg2
+ if ( current.compareAndSet(dsg2, dsg1) )
+ return ;
+ throw new FusekiException() ;
+ }
+
+ /** Current dataset of the switchable pair */
+ public final DatasetGraph getCurrent() { return get() ; }
+
+ /** Return dataset1 of the switchable pair */
+ public final DatasetGraph getDataset1() { return dsg1 ; }
+
+ /** Return dataset2 of the switchable pair */
+ public final DatasetGraph getDataset2() { return dsg2 ; }
+
+ /** Use dataset1 */
+ public final void useDataset1() { set(dsg1) ; }
+
+ /** Use dataset2 */
+ public final void useDataset2() { set(dsg2) ; }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/GraphLoadUtils.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/GraphLoadUtils.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/GraphLoadUtils.java
new file mode 100644
index 0000000..c5f92ae
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/GraphLoadUtils.java
@@ -0,0 +1,76 @@
+/*
+ * 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.migrate;
+
+import org.apache.jena.atlas.web.TypedInputStream ;
+import org.apache.jena.fuseki.Fuseki ;
+import org.apache.jena.riot.RDFDataMgr ;
+import org.apache.jena.riot.system.StreamRDF ;
+import org.apache.jena.riot.system.StreamRDFLib ;
+
+import com.hp.hpl.jena.graph.Factory ;
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.rdf.model.ModelFactory ;
+
+/** A packaging of code to do a controlled read of a graph or model */
+
+public class GraphLoadUtils
+{
+ // ---- Model level
+
+ public static Model readModel(String uri, int limit)
+ {
+ Graph g = Factory.createGraphMem() ;
+ readUtil(g, uri, limit) ;
+ return ModelFactory.createModelForGraph(g) ;
+ }
+
+ public static void loadModel(Model model, String uri, int limit)
+ {
+ Graph g = model.getGraph() ;
+ readUtil(g, uri, limit) ;
+ }
+
+ // ---- Graph level
+
+ public static Graph readGraph(String uri, int limit)
+ {
+ Graph g = Factory.createGraphMem() ;
+ readUtil(g, uri, limit) ;
+ return g ;
+ }
+
+ public static void loadGraph(Graph g, String uri, int limit)
+ {
+ readUtil(g, uri, limit) ;
+ }
+
+ // ** Worker.
+ private static void readUtil(Graph graph, String uri, int limit)
+ {
+ // We need to do this ourselves, not via riot, to use the webStreamManager
+ StreamRDF sink = StreamRDFLib.graph(graph) ;
+ sink = new StreamRDFLimited(sink, limit) ;
+
+ TypedInputStream input = Fuseki.webStreamManager.open(uri) ;
+ RDFDataMgr.parse(sink, input, uri) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/Registry.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/Registry.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/Registry.java
new file mode 100644
index 0000000..9e7f729
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/Registry.java
@@ -0,0 +1,39 @@
+/*
+ * 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.migrate;
+
+import java.util.Collection ;
+import java.util.Map ;
+import java.util.concurrent.ConcurrentHashMap ;
+
+public class Registry<K,T>
+{
+ protected Map<K, T> registry = new ConcurrentHashMap<>() ;
+
+ public Registry() {}
+
+ public void put(K key, T value) { registry.put(key, value) ; }
+ public T get(K key) { return registry.get(key) ; }
+ public boolean isRegistered(K key) { return registry.containsKey(key) ; }
+ public void remove(K key) { registry.remove(key) ; }
+ public Collection<K> keys() { return registry.keySet() ; }
+ //public Iterator<String> keys() { return registry.keySet().iterator() ; }
+ public int size() { return registry.size() ; }
+ public boolean isEmpty() { return registry.isEmpty() ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/StreamRDFLimited.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/StreamRDFLimited.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/StreamRDFLimited.java
new file mode 100644
index 0000000..bf9ebf3
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/migrate/StreamRDFLimited.java
@@ -0,0 +1,63 @@
+/*
+ * 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.migrate ;
+
+import org.apache.jena.riot.RiotException ;
+import org.apache.jena.riot.system.StreamRDF ;
+import org.apache.jena.riot.system.StreamRDFWrapper ;
+
+import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.sparql.core.Quad ;
+
+/**
+ * Limit triples/quads and stop passing through after a limit is reached.
+ */
+public class StreamRDFLimited extends StreamRDFWrapper {
+ private long count = 0 ;
+ private final long limit ;
+
+ public StreamRDFLimited(StreamRDF output, long limit) {
+ super(output) ;
+ this.limit = limit ;
+ }
+
+ @Override
+ public void triple(Triple triple) {
+ count++ ;
+ if ( count > limit )
+ throw new RiotException("Limit ("+limit+") reached") ;
+ super.triple(triple) ;
+ }
+
+ @Override
+ public void quad(Quad quad) {
+ count++ ;
+ if ( count > limit )
+ throw new RiotException("Limit ("+limit+") reached") ;
+ super.quad(quad) ;
+ }
+
+ public long getCount() {
+ return count ;
+ }
+
+ public long getLimit() {
+ return limit ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Counter.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Counter.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Counter.java
new file mode 100644
index 0000000..88d4d37
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Counter.java
@@ -0,0 +1,34 @@
+/**
+ * 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.server;
+
+import java.util.concurrent.atomic.AtomicLong ;
+
+/** A statistics counter */
+public class Counter
+{
+ private AtomicLong counter = new AtomicLong(0) ;
+
+ public Counter() {}
+
+ public void inc() { counter.incrementAndGet() ; }
+ public void dec() { counter.decrementAndGet() ; }
+ public long value() { return counter.get() ; }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/CounterMXBean.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/CounterMXBean.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/CounterMXBean.java
new file mode 100644
index 0000000..2de7658
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/CounterMXBean.java
@@ -0,0 +1,25 @@
+/**
+ * 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.server;
+
+public interface CounterMXBean
+{
+ long getValue() ;
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/CounterName.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/CounterName.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/CounterName.java
new file mode 100644
index 0000000..7a8d306
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/CounterName.java
@@ -0,0 +1,84 @@
+/**
+ * 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.server;
+
+/** Names for all counters */
+public enum CounterName {
+ // There are generic names - apply to all services and datasets - and
+ // also specific ones that relate only to a particular kind of service.
+
+ // Total request received
+ Requests("requests"),
+ // .. of which some and "good" and some are "bad".
+ // #"good" + #"bad" roughly equals #"requests"
+ // except that the total is incremented at the start, and the outcome at the end.
+ // There may also be short term consistency issues.
+ RequestsGood("requests.good"),
+ RequestsBad("requests.bad") ,
+
+ // SPARQL Protocol - query and update - together with upload.
+
+ // Query - standard and ...
+ QueryTimeouts("query.timeouts") ,
+ QueryExecErrors("query.execerrors") ,
+ QueryIOErrors("query.ioerrors") ,
+
+ // Update - standard and ...
+ UpdateExecErrors("update.execerrors"),
+
+ // Upload ... standard counters
+
+ // Graph Store Protocol. uses HTTP codes.
+
+ // For each HTTP method
+
+ HTTPget("http.get.requests") ,
+ HTTPgetGood("http.get.requests.good") ,
+ HTTPGetBad("http.get.requests.bad") ,
+
+ HTTPpost("http.post.requests") ,
+ HTTPpostGood("http.post.requests.good") ,
+ HTTPpostBad("http.post.requests.bad") ,
+
+ HTTPdelete("http.delete.requests") ,
+ HTTPdeleteGood("http.delete.requests.good") ,
+ HTTPdeleteBad("http.delete.requests.bad") ,
+
+ HTTPput("http.put.requests") ,
+ HTTPputGood("http.put.requests.good") ,
+ HTTPputBad("http.put.requests.bad") ,
+
+ HTTPhead("http.head.requests") ,
+ HTTPheadGood("http.head.requests.good") ,
+ HTTPheadBad("http.head.requests.bad") ,
+
+ HTTPpatch("http.patch.requests") ,
+ HTTPpatchGood("http.patch.requests.good") ,
+ HTTPpatchBad("http.patch.requests.bad") ,
+
+ HTTPoptions("http.options.requests") ,
+ HTTPoptionsGood("http.options.requests.good") ,
+ HTTPoptionsBad("http.options.requests.bad") ,
+
+ ;
+
+ public final String name ;
+ private CounterName(String name) { this.name = name ; }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/CounterSet.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/CounterSet.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/CounterSet.java
new file mode 100644
index 0000000..9b8231e
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/CounterSet.java
@@ -0,0 +1,70 @@
+/**
+ * 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.server ;
+
+import java.util.Collection ;
+import java.util.HashMap ;
+import java.util.Map ;
+
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+/** A collection of counters */
+public class CounterSet {
+ private static Logger log = LoggerFactory.getLogger(CounterSet.class) ;
+
+ private Map<CounterName, Counter> counters = new HashMap<>() ;
+
+ public CounterSet() {}
+
+ public Collection<CounterName> counters() {
+ return counters.keySet() ;
+ }
+
+ public void inc(CounterName c) {
+ get(c).inc() ;
+ }
+
+ public void dec(CounterName c) {
+ get(c).dec() ;
+ }
+
+ public long value(CounterName c) {
+ return get(c).value() ;
+ }
+
+ public void add(CounterName counterName) {
+ if ( counters.containsKey(counterName) ) {
+ log.warn("Duplicate counter in counter set: " + counterName) ;
+ return ;
+ }
+ counters.put(counterName, new Counter()) ;
+ }
+
+ public boolean contains(CounterName cn) {
+ return counters.containsKey(cn) ;
+ }
+
+ public Counter get(CounterName cn) {
+ Counter c = counters.get(cn) ;
+ if ( c == null )
+ log.warn("No counter in counter set: " + cn) ;
+ return c ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Counters.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Counters.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Counters.java
new file mode 100644
index 0000000..4e5ca4b
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Counters.java
@@ -0,0 +1,25 @@
+/**
+ * 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.server;
+
+/** Objects that have a counter set */
+public interface Counters {
+ public CounterSet getCounters() ;
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataAccessPoint.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataAccessPoint.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataAccessPoint.java
new file mode 100644
index 0000000..24275a8
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataAccessPoint.java
@@ -0,0 +1,75 @@
+/**
+ * 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.server;
+
+import java.util.concurrent.atomic.AtomicLong ;
+
+import org.apache.jena.fuseki.servlets.HttpAction ;
+
+
+/** A name in the URL space of the server */
+public class DataAccessPoint {
+ private final String name ;
+ private DataService dataService ;
+ private DataAccessPoint link ; // Symbolic link.
+ private AtomicLong requests = new AtomicLong(0) ;
+
+ public DataAccessPoint(String name) {
+ this.name = canonical(name) ;
+ this.dataService = null ;
+ }
+
+ public String getName() { return name ; }
+
+ public static String canonical(String datasetPath) {
+ if ( datasetPath == null )
+ return datasetPath ;
+ if ( datasetPath.equals("/") )
+ datasetPath = "" ;
+ else
+ if ( !datasetPath.startsWith("/") )
+ datasetPath = "/" + datasetPath ;
+ if ( datasetPath.endsWith("/") )
+ datasetPath = datasetPath.substring(0, datasetPath.length() - 1) ;
+ return datasetPath ;
+ }
+
+ public DataService getDataService() {
+ return dataService;
+ }
+
+ public void setDataService(DataService dataService) {
+ this.dataService = dataService;
+ }
+
+ public DataAccessPoint getLink() {
+ return link;
+ }
+
+ public void setLink(DataAccessPoint link) {
+ this.link = link;
+ }
+
+ public long requestCount() { return requests.get() ; }
+
+ public void startRequest(HttpAction httpAction) { requests.incrementAndGet() ; }
+
+ public void finishRequest(HttpAction httpAction) { requests.getAndDecrement() ; }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataAccessPointRegistry.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataAccessPointRegistry.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataAccessPointRegistry.java
new file mode 100644
index 0000000..19119a9
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataAccessPointRegistry.java
@@ -0,0 +1,37 @@
+/*
+ * 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.server;
+
+import org.apache.jena.fuseki.FusekiException ;
+import org.apache.jena.fuseki.migrate.Registry ;
+
+public class DataAccessPointRegistry extends Registry<String, DataAccessPoint>
+{
+ public static void register(String name, DataAccessPoint accessPt) {
+ if ( get().isRegistered(name) )
+ throw new FusekiException("Already registered: "+name) ;
+ get().put(name, accessPt);
+ }
+
+ private static DataAccessPointRegistry singleton = new DataAccessPointRegistry() ;
+
+ public static DataAccessPointRegistry get() { return singleton ; }
+
+ private DataAccessPointRegistry() {}
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataService.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataService.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataService.java
new file mode 100644
index 0000000..df9d2b3
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DataService.java
@@ -0,0 +1,199 @@
+/**
+ * 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.server;
+
+import static org.apache.jena.fuseki.server.DatasetStatus.CLOSING ;
+import static org.apache.jena.fuseki.server.DatasetStatus.UNINITIALIZED ;
+
+import java.util.* ;
+import java.util.concurrent.atomic.AtomicBoolean ;
+import java.util.concurrent.atomic.AtomicLong ;
+
+import org.apache.jena.atlas.lib.MultiMap ;
+import org.apache.jena.atlas.lib.MultiMapToList ;
+import org.apache.jena.fuseki.DEF ;
+import org.apache.jena.fuseki.Fuseki ;
+import org.apache.jena.fuseki.build.DataServiceDesc ;
+
+import com.hp.hpl.jena.query.ReadWrite ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.DatasetGraphFactory ;
+import com.hp.hpl.jena.sparql.core.DatasetGraphReadOnly ;
+import com.hp.hpl.jena.tdb.StoreConnection ;
+import com.hp.hpl.jena.tdb.transaction.DatasetGraphTransaction ;
+
+public class DataService { //implements DatasetMXBean {
+ // XXX Add a "null model assembler".
+
+ public static DataService serviceOnlyDataService() {
+ return dummy ;
+ }
+
+ public static DataService dummy = new DataService(null, null) ;
+ static {
+ dummy.dataset = new DatasetGraphReadOnly(DatasetGraphFactory.createMemFixed()) ;
+ dummy.addEndpoint(OperationName.Query, DEF.ServiceQuery) ;
+ dummy.addEndpoint(OperationName.Query, DEF.ServiceQueryAlt) ;
+ }
+
+ private final DataServiceDesc svcDesc ;
+ private DatasetGraph dataset = null ; // Only valid if active.
+
+ private MultiMapToList<OperationName, Endpoint> operations = MultiMap.createMapList() ;
+ private Map<String, Endpoint> endpoints = new HashMap<>() ;
+
+ private volatile DatasetStatus state = UNINITIALIZED ;
+
+ // DataService-level counters.
+ private final CounterSet counters = new CounterSet() ;
+ private final AtomicLong requestCounter = new AtomicLong(0) ;
+ private final AtomicBoolean offlineInProgress = new AtomicBoolean(false) ;
+ private final AtomicBoolean acceptingRequests = new AtomicBoolean(true) ;
+
+ public DataService(DataServiceDesc desc, DatasetGraph dataset) {
+ this.svcDesc = desc ;
+ this.dataset = dataset ;
+ counters.add(CounterName.Requests) ;
+ counters.add(CounterName.RequestsGood) ;
+ counters.add(CounterName.RequestsBad) ;
+ }
+
+ public DatasetGraph getDataset() {
+ return dataset ;
+ }
+
+ public void addEndpoint(OperationName operationName, String endpointName) {
+ Endpoint endpoint = new Endpoint(operationName, endpointName) ;
+ endpoints.put(endpointName, endpoint) ;
+ operations.put(operationName, endpoint);
+ }
+
+ public Endpoint getOperation(String endpointName) {
+ return endpoints.get(endpointName) ;
+ }
+
+ public List<Endpoint> getOperation(OperationName opName) {
+ List<Endpoint> x = operations.get(opName) ;
+ if ( x == null )
+ x = Collections.emptyList() ;
+ return x ;
+ }
+
+ /** Return the OperationNames available here.
+ * @see #getOperation(OperationName) to ge the endpoint list
+ */
+ public Collection<OperationName> getOperations() {
+ return operations.keys() ;
+ }
+
+ //@Override
+ public boolean allowUpdate() { return true ; }
+
+ public void goOffline() {
+ offlineInProgress.set(true) ;
+ acceptingRequests.set(false) ;
+ state = DatasetStatus.OFFLINE ;
+ }
+
+ public void goActive() {
+ offlineInProgress.set(false) ;
+ acceptingRequests.set(true) ;
+ state = DatasetStatus.ACTIVE ;
+ }
+
+ public boolean isAcceptingRequests() {
+ return acceptingRequests.get() ;
+ }
+
+ //@Override
+ public CounterSet getCounters() { return counters ; }
+
+ //@Override
+ public long getRequests() {
+ return counters.value(CounterName.Requests) ;
+ }
+
+ //@Override
+ public long getRequestsGood() {
+ return counters.value(CounterName.RequestsGood) ;
+ }
+ //@Override
+ public long getRequestsBad() {
+ return counters.value(CounterName.RequestsBad) ;
+ }
+
+ /** Counter of active read transactions */
+ public AtomicLong activeReadTxn = new AtomicLong(0) ;
+
+ /** Counter of active write transactions */
+ public AtomicLong activeWriteTxn = new AtomicLong(0) ;
+
+ /** Cumulative counter of read transactions */
+ public AtomicLong totalReadTxn = new AtomicLong(0) ;
+
+ /** Cumulative counter of writer transactions */
+ public AtomicLong totalWriteTxn = new AtomicLong(0) ;
+
+ public void startTxn(ReadWrite mode)
+ {
+ switch(mode)
+ {
+ case READ:
+ activeReadTxn.getAndIncrement() ;
+ totalReadTxn.getAndIncrement() ;
+ break ;
+ case WRITE:
+ activeWriteTxn.getAndIncrement() ;
+ totalWriteTxn.getAndIncrement() ;
+ break ;
+ }
+ }
+
+ public void finishTxn(ReadWrite mode)
+ {
+ switch(mode)
+ {
+ case READ:
+ activeReadTxn.decrementAndGet() ;
+ break ;
+ case WRITE:
+ activeWriteTxn.decrementAndGet() ;
+ break ;
+ }
+ checkShutdown() ;
+ }
+
+ private void checkShutdown() {
+ if ( state == CLOSING ) {
+ if ( activeReadTxn.get() == 0 && activeWriteTxn.get() == 0 )
+ shutdown() ;
+ }
+ }
+
+ private void shutdown() {
+ Fuseki.serverLog.info("Shutting down dataset") ;
+ dataset.close() ;
+ if ( dataset instanceof DatasetGraphTransaction ) {
+ DatasetGraphTransaction dsgtxn = (DatasetGraphTransaction)dataset ;
+ StoreConnection.release(dsgtxn.getLocation()) ;
+ }
+ dataset = null ;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DatasetMXBean.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DatasetMXBean.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DatasetMXBean.java
new file mode 100644
index 0000000..bf38229
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DatasetMXBean.java
@@ -0,0 +1,35 @@
+/**
+ * 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.server;
+
+public interface DatasetMXBean
+{
+ String getName() ;
+
+ long getRequests() ;
+ long getRequestsGood() ;
+ long getRequestsBad() ;
+
+// void enable() ;
+// void disable() ;
+// void setReadOnly() ;
+// boolean getReadOnly() ;
+
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DatasetStatus.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DatasetStatus.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DatasetStatus.java
new file mode 100644
index 0000000..524b050
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/DatasetStatus.java
@@ -0,0 +1,40 @@
+/**
+ * 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.server;
+
+import com.hp.hpl.jena.rdf.model.Resource ;
+
+public enum DatasetStatus {
+ UNINITIALIZED("Uninitialized"), ACTIVE("Active"), OFFLINE("Offline"), CLOSING("Closing"), CLOSED("Closed") ;
+ public final String name ;
+ DatasetStatus(String string) { name = string ; }
+
+ public static DatasetStatus status(Resource r) {
+ if ( FusekiVocab.stateActive.equals(r) )
+ return ACTIVE ;
+ if ( FusekiVocab.stateOffline.equals(r) )
+ return OFFLINE ;
+ if ( FusekiVocab.stateClosing.equals(r) )
+ return CLOSING ;
+ if ( FusekiVocab.stateClosed.equals(r) )
+ return CLOSED ;
+ return null ;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Endpoint.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Endpoint.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Endpoint.java
new file mode 100644
index 0000000..6de7062
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Endpoint.java
@@ -0,0 +1,68 @@
+/**
+ * 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.server;
+
+import org.apache.jena.atlas.lib.InternalErrorException ;
+
+public class Endpoint implements Counters {
+
+ public final OperationName opName ;
+ public final String endpointName ;
+ // Endpoint-level counters.
+ private final CounterSet counters = new CounterSet() ;
+
+ public Endpoint(OperationName opName, String endpointName) {
+ this.opName = opName ;
+ if ( opName == null )
+ throw new InternalErrorException("opName is null") ;
+ this.endpointName = endpointName ;
+ // Standard counters - there may be others
+ counters.add(CounterName.Requests) ;
+ counters.add(CounterName.RequestsGood) ;
+ counters.add(CounterName.RequestsBad) ;
+ }
+
+ @Override
+ public CounterSet getCounters() { return counters ; }
+
+ //@Override
+ public OperationName getOperationName() { return opName ; }
+
+ //@Override
+ public boolean isType(OperationName operationName) {
+ return opName.equals(operationName) ;
+ }
+
+ public String getEndpoint() { return endpointName ; }
+
+ //@Override
+ public long getRequests() {
+ return counters.value(CounterName.Requests) ;
+ }
+ //@Override
+ public long getRequestsGood() {
+ return counters.value(CounterName.RequestsGood) ;
+ }
+ //@Override
+ public long getRequestsBad() {
+ return counters.value(CounterName.RequestsBad) ;
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiEnv.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiEnv.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiEnv.java
new file mode 100644
index 0000000..a76be11
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiEnv.java
@@ -0,0 +1,114 @@
+/**
+ * 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.server;
+
+import java.nio.file.Path ;
+import java.nio.file.Paths ;
+
+/**
+ * Separate initialization for FUSEKI_HOME and FUSEKI_BASE so that
+ * Fusekilogging can use these values.
+ * This code must not touch Jena.
+ *
+ * @See FusekiServer
+ */
+public class FusekiEnv {
+ /** Root of the Fuseki installation for fixed files.
+ * This may be null (e.g. running inside a web application container) */
+ public static Path FUSEKI_HOME = null ;
+
+ /** Root of the varying files in this deployment. Often $FUSEKI_HOME/run.
+ * This is not null - it may be /etc/fuseki, which must be writable.
+ */
+ public static Path FUSEKI_BASE = null ;
+
+ static final boolean isWindows = determineIfWindows() ;
+
+ // Copied from SystemTDB to avoid dependency.
+ // This code must not touch Jena.
+ private static boolean determineIfWindows() {
+ String s = System.getProperty("os.name") ;
+ if ( s == null )
+ return false ;
+ return s.startsWith("Windows ") ;
+ }
+
+ /** Unused */
+ // public static final String DFT_FUSEKI_HOME = isWindows
+ // ? /*What's correct here?*/ "/usr/share/fuseki"
+ // : "/usr/share/fuseki" ;
+ static final String DFT_FUSEKI_BASE = isWindows ? /* What's correct here? */"/etc/fuseki" : "/etc/fuseki" ;
+
+ public static final String ENV_runArea = "run" ;
+
+ private static boolean initialized = false ;
+ private static final boolean LogInit = false ;
+
+ public static synchronized void setEnvironment() {
+ if ( initialized )
+ return ;
+ initialized = true ;
+ logInit("FusekiInitEnv") ;
+ logInit("Start: ENV_FUSEKI_HOME = %s : ENV_FUSEKI_BASE = %s", FUSEKI_HOME, FUSEKI_BASE) ;
+
+ if ( FUSEKI_HOME == null ) {
+ // Make absolute
+ String x1 = getenv("FUSEKI_HOME") ;
+ if ( x1 != null )
+ FUSEKI_HOME = Paths.get(x1) ;
+ }
+
+ if ( FUSEKI_BASE == null ) {
+ String x2 = getenv("FUSEKI_BASE") ;
+ if ( x2 != null )
+ FUSEKI_BASE = Paths.get(x2) ;
+ else {
+ if ( FUSEKI_HOME != null )
+ FUSEKI_BASE = FUSEKI_HOME.resolve(ENV_runArea) ;
+ else
+ // Neither FUSEKI_HOME nor FUSEKI_BASE set.
+ FUSEKI_BASE = Paths.get(DFT_FUSEKI_BASE) ;
+ }
+ }
+
+ if ( FUSEKI_HOME != null )
+ FUSEKI_HOME = FUSEKI_HOME.toAbsolutePath() ;
+
+ FUSEKI_BASE = FUSEKI_BASE.toAbsolutePath() ;
+
+ logInit("Finish: ENV_FUSEKI_HOME = %s : ENV_FUSEKI_BASE = %s", FUSEKI_HOME, FUSEKI_BASE) ;
+ }
+
+ private static void logInit(String fmt, Object ... args) {
+ if ( LogInit ) {
+ System.out.printf(fmt, args) ;
+ System.out.println() ;
+ }
+ }
+
+ /** Get environment variable value (maybe in system properties) */
+ public static String getenv(String name) {
+ String x = System.getenv(name) ;
+ if ( x == null )
+ x = System.getProperty(name) ;
+ return x ;
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServer.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServer.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServer.java
new file mode 100644
index 0000000..83d5523
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServer.java
@@ -0,0 +1,395 @@
+/**
+ * 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.server;
+
+import java.io.File ;
+import java.io.IOException ;
+import java.io.InputStream ;
+import java.io.StringReader ;
+import java.nio.file.Files ;
+import java.nio.file.Path ;
+import java.nio.file.StandardCopyOption ;
+import java.util.ArrayList ;
+import java.util.HashMap ;
+import java.util.List ;
+import java.util.Map ;
+
+import org.apache.jena.atlas.io.IO ;
+import org.apache.jena.atlas.lib.DS ;
+import org.apache.jena.atlas.lib.FileOps ;
+import org.apache.jena.atlas.lib.InternalErrorException ;
+import org.apache.jena.atlas.lib.Lib ;
+import org.apache.jena.fuseki.Fuseki ;
+import org.apache.jena.fuseki.FusekiConfigException ;
+import org.apache.jena.fuseki.build.Builder ;
+import org.apache.jena.fuseki.build.FusekiConfig ;
+import org.apache.jena.fuseki.build.Template ;
+import org.apache.jena.fuseki.build.TemplateFunctions ;
+import org.apache.jena.fuseki.servlets.ServletOps ;
+import org.apache.jena.riot.Lang ;
+import org.apache.jena.riot.RDFDataMgr ;
+import org.apache.jena.riot.RDFLanguages ;
+import arq.cmd.CmdException ;
+
+import com.hp.hpl.jena.rdf.model.* ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.tdb.sys.Names ;
+
+public class FusekiServer
+{
+ // Initialization of FUSEKI_HOME and FUSEKI_BASE is done in FusekiEnvInit
+ // so that the code is independent of any logging. FusekiLogging can use
+ // initialized values of FUSEKI_BASE while looking forlog4j configuration.
+
+ /** Root of the Fuseki installation for fixed files.
+ * This may be null (e.g. running inside a web application container) */
+ //public static Path FUSEKI_HOME = null ;
+
+ /** Root of the varying files in this deployment. Often $FUSEKI_HOME/run.
+ * This is not null - it may be /etc/fuseki, which must be writable.
+ */
+ //public static Path FUSEKI_BASE = null ;
+
+ // Relative names of directories in the FUSEKI_BASE area.
+ public static final String runArea = FusekiEnv.ENV_runArea ;
+ public static final String databasesLocationBase = "databases" ;
+ // Place to put Lucene text and spatial indexes.
+ //private static final String databaseIndexesDir = "indexes" ;
+
+ public static final String backupDirNameBase = "backups" ;
+ public static final String configDirNameBase = "configuration" ;
+ public static final String logsNameBase = "logs" ;
+ public static final String systemDatabaseNameBase = "system" ;
+ public static final String systemFileAreaBase = "system_files" ;
+ public static final String templatesNameBase = "templates" ;
+ // This name is in web.xml as well.
+ public static final String DFT_SHIRO_INI = "shiro.ini" ;
+ // In FUSEKI_BASE
+ public static final String DFT_CONFIG = "config.ttl" ;
+
+ /** Directory for TDB databases - this is known to the assembler templates */
+ public static Path dirDatabases = null ;
+
+ /** Directory for writing backups */
+ public static Path dirBackups = null ;
+
+ /** Directory for assembler files */
+ public static Path dirConfiguration = null ;
+
+ /** Directory for assembler files */
+ public static Path dirLogs = null ;
+
+ /** Directory for system database */
+ public static Path dirSystemDatabase = null ;
+
+ /** Directory for files uploaded (e.g upload assmbler descriptions); not data uploads. */
+ public static Path dirFileArea = null ;
+
+ /** Directory for assembler files */
+ public static Path dirTemplates = null ;
+
+ private static boolean initialized = false ;
+ public static boolean serverInitialized = false ;
+
+ /** For testing - reset the places which initialize once */
+ public synchronized static void reset() {
+ initialized = false ;
+ FusekiServer.initialized = false ;
+ }
+
+ public synchronized static void init() {
+ if ( initialized )
+ return ;
+ initialized = true ;
+ try {
+ FusekiEnv.setEnvironment() ;
+ Path FUSEKI_HOME = FusekiEnv.FUSEKI_HOME ;
+ Path FUSEKI_BASE = FusekiEnv.FUSEKI_BASE ;
+
+ Fuseki.init() ;
+ Fuseki.configLog.info("FUSEKI_HOME="+ ((FUSEKI_HOME==null) ? "unset" : FUSEKI_HOME.toString())) ;
+ Fuseki.configLog.info("FUSEKI_BASE="+FUSEKI_BASE.toString());
+
+ // ---- Check FUSEKI_HOME and FUSEKI_BASE
+ // If FUSEKI_HOME exists, it may be FUSEKI_BASE.
+
+ if ( FUSEKI_HOME != null ) {
+ if ( ! Files.isDirectory(FUSEKI_HOME) )
+ throw new FusekiConfigException("FUSEKI_HOME is not a directory: "+FUSEKI_HOME) ;
+ if ( ! Files.isReadable(FUSEKI_HOME) )
+ throw new FusekiConfigException("FUSEKI_HOME is not readable: "+FUSEKI_HOME) ;
+ }
+
+ if ( Files.exists(FUSEKI_BASE) ) {
+ if ( ! Files.isDirectory(FUSEKI_BASE) )
+ throw new FusekiConfigException("FUSEKI_BASE is not a directory: "+FUSEKI_BASE) ;
+ if ( ! Files.isWritable(FUSEKI_BASE) )
+ throw new FusekiConfigException("FUSEKI_BASE is not writable: "+FUSEKI_BASE) ;
+ } else {
+ ensureDir(FUSEKI_BASE);
+ }
+
+ // Ensure FUSEKI_BASE has the assumed directories.
+ dirTemplates = writeableDirectory(FUSEKI_BASE, templatesNameBase) ;
+ dirDatabases = writeableDirectory(FUSEKI_BASE, databasesLocationBase) ;
+ dirBackups = writeableDirectory(FUSEKI_BASE, backupDirNameBase) ;
+ dirConfiguration = writeableDirectory(FUSEKI_BASE, configDirNameBase) ;
+ dirLogs = writeableDirectory(FUSEKI_BASE, logsNameBase) ;
+ dirSystemDatabase = writeableDirectory(FUSEKI_BASE, systemDatabaseNameBase) ;
+ dirFileArea = writeableDirectory(FUSEKI_BASE, systemFileAreaBase) ;
+ //Possible intercept point
+
+ // ---- Initialize with files.
+
+ if ( Files.isRegularFile(FUSEKI_BASE) )
+ throw new FusekiConfigException("FUSEKI_BASE exists but is a file") ;
+
+ // Copy missing files into FUSEKI_BASE
+ copyFileIfMissing(null, DFT_SHIRO_INI, FUSEKI_BASE) ;
+ copyFileIfMissing(null, DFT_CONFIG, FUSEKI_BASE) ;
+ for ( String n : Template.templateNames ) {
+ copyFileIfMissing(null, n, FUSEKI_BASE) ;
+ }
+
+ serverInitialized = true ;
+ } catch (RuntimeException ex) {
+ Fuseki.serverLog.error("Exception in server initialization", ex) ;
+ throw ex ;
+ }
+ }
+
+ private static boolean emptyDir(Path dir) {
+ return dir.toFile().list().length <= 2 ;
+ }
+
+ /** Copy a file from src to dst under name fn.
+ * If src is null, try as a classpath resource
+ * @param src Source directory, or null meaning use java resource.
+ * @param fn File name, a relative path.
+ * @param dst Destination directory.
+ *
+ */
+ private static void copyFileIfMissing(Path src, String fn, Path dst) {
+
+ Path dstFile = dst.resolve(fn) ;
+ if ( Files.exists(dstFile) )
+ return ;
+
+ // fn may be a path.
+ if ( src != null ) {
+ try {
+ Files.copy(src.resolve(fn), dstFile, StandardCopyOption.COPY_ATTRIBUTES) ;
+ } catch (IOException e) {
+ IO.exception("Failed to copy file "+src, e);
+ e.printStackTrace();
+ }
+ } else {
+ try {
+ // Get from the file from area "org/apache/jena/fuseki/server" (our package)
+ InputStream in = FusekiServer.class.getResource(fn).openStream() ;
+ Files.copy(in, dstFile) ;
+ }
+ catch (IOException e) {
+ IO.exception("Failed to copy file from resource: "+src, e);
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static void initializeDataAccessPoints(ServerInitialConfig initialSetup, String configDir) {
+ List<DataAccessPoint> configFileDBs = initServerConfiguration(initialSetup) ;
+ List<DataAccessPoint> directoryDBs = FusekiConfig.readConfigurationDirectory(configDir) ;
+ List<DataAccessPoint> systemDBs = FusekiConfig.readSystemDatabase(SystemState.getDataset()) ;
+
+ List<DataAccessPoint> datapoints = new ArrayList<DataAccessPoint>() ;
+ datapoints.addAll(configFileDBs) ;
+ datapoints.addAll(directoryDBs) ;
+ datapoints.addAll(systemDBs) ;
+
+ // Having found them, set them all running.
+ enable(datapoints);
+ }
+
+ private static void enable(List<DataAccessPoint> datapoints) {
+ for ( DataAccessPoint dap : datapoints ) {
+ Fuseki.configLog.info("Register: "+dap.getName()) ;
+ DataAccessPointRegistry.register(dap.getName(), dap);
+ }
+ }
+
+ private static List<DataAccessPoint> initServerConfiguration(ServerInitialConfig params) {
+ // Has a side effect of global context setting
+ // when processing a config file.
+ // Compatibility.
+
+ List<DataAccessPoint> datasets = DS.list() ;
+ if ( params == null )
+ return datasets ;
+
+ if ( params.fusekiConfigFile != null ) {
+ if ( FileOps.exists(params.fusekiConfigFile ) ) {
+ Fuseki.configLog.info("Configuration file: " + params.fusekiConfigFile) ;
+ List<DataAccessPoint> cmdLineDatasets = FusekiConfig.readConfigFile(params.fusekiConfigFile) ;
+ datasets.addAll(cmdLineDatasets) ;
+ } else {
+ Fuseki.configLog.info("Configuration file '" + params.fusekiConfigFile+"' does not exist") ;
+ }
+ } else if ( params.dsg != null ) {
+ DataAccessPoint dap = defaultConfiguration(params.datasetPath, params.dsg, params.allowUpdate) ;
+ datasets.add(dap) ;
+ } else if ( params.templateFile != null ) {
+ Fuseki.configLog.info("Template file: " + params.templateFile) ;
+ String dir = params.params.get(Template.DIR) ;
+ if ( dir != null ) {
+ if ( Lib.equal(dir, Names.memName) ) {
+ Fuseki.configLog.info("TDB dataset: in-memory") ;
+ } else {
+ if ( !FileOps.exists(dir) )
+ throw new CmdException("Directory not found: " + dir) ;
+ Fuseki.configLog.info("TDB dataset: directory=" + dir) ;
+ }
+ }
+ DataAccessPoint dap = configFromTemplate(params.templateFile, params.datasetPath, params.params) ;
+ datasets.add(dap) ;
+ }
+ // No datasets is valid.
+ return datasets ;
+ }
+
+ private static DataAccessPoint configFromTemplate(String templateFile,
+ String datasetPath,
+ Map<String, String> params) {
+ datasetPath = DataAccessPoint.canonical(datasetPath) ;
+
+ // DRY -- ActionDatasets (and others?)
+ if ( params == null ) {
+ params = new HashMap<>() ;
+ params.put(Template.NAME, datasetPath) ;
+ } else {
+ if ( ! params.containsKey(Template.NAME) ) {
+ Fuseki.configLog.warn("No NAME found in template parameters (added)") ;
+ params.put(Template.NAME, datasetPath) ;
+ }
+ }
+
+ addGlobals(params);
+
+ String str = TemplateFunctions.templateFile(templateFile, params) ;
+ Lang lang = RDFLanguages.filenameToLang(str, Lang.TTL) ;
+ StringReader sr = new StringReader(str) ;
+ Model model = ModelFactory.createDefaultModel() ;
+ RDFDataMgr.read(model, sr, datasetPath, lang);
+
+ // Find DataAccessPoint
+ Statement stmt = getOne(model, null, FusekiVocab.pServiceName, null) ;
+ if ( stmt == null ) {
+ StmtIterator sIter = model.listStatements(null, FusekiVocab.pServiceName, (RDFNode)null ) ;
+ if ( ! sIter.hasNext() )
+ ServletOps.errorBadRequest("No name given in description of Fuseki service") ;
+ sIter.next() ;
+ if ( sIter.hasNext() )
+ ServletOps.errorBadRequest("Multiple names given in description of Fuseki service") ;
+ throw new InternalErrorException("Inconsistent: getOne didn't fail the second time") ;
+ }
+ Resource subject = stmt.getSubject() ;
+ DataAccessPoint dap = Builder.buildDataAccessPoint(subject) ;
+ return dap ;
+ }
+
+ public static void addGlobals(Map<String, String> params) {
+ if ( params == null ) {
+ Fuseki.configLog.warn("FusekiServer.addGlobals : params is null", new Throwable()) ;
+ return ;
+ }
+
+ if ( ! params.containsKey("FUSEKI_BASE") )
+ params.put("FUSEKI_BASE", pathStringOrElse(FusekiEnv.FUSEKI_BASE, "unset")) ;
+ if ( ! params.containsKey("FUSEKI_HOME") )
+ params.put("FUSEKI_HOME", pathStringOrElse(FusekiEnv.FUSEKI_HOME, "unset")) ;
+ }
+
+ private static String pathStringOrElse(Path path, String dft) {
+ if ( path == null )
+ return dft ;
+ return path.toString() ;
+ }
+
+ // DRY -- ActionDatasets (and others?)
+ private static Statement getOne(Model m, Resource s, Property p, RDFNode o) {
+ StmtIterator iter = m.listStatements(s, p, o) ;
+ if ( ! iter.hasNext() )
+ return null ;
+ Statement stmt = iter.next() ;
+ if ( iter.hasNext() )
+ return null ;
+ return stmt ;
+ }
+
+ private static DataAccessPoint defaultConfiguration( String name, DatasetGraph dsg, boolean updatable) {
+ name = DataAccessPoint.canonical(name) ;
+ DataAccessPoint dap = new DataAccessPoint(name) ;
+ DataService ds = Builder.buildDataService(dsg, updatable) ;
+ dap.setDataService(ds) ;
+ return dap ;
+ }
+
+ // ---- Helpers
+
+ /** Ensure a directory exists, creating it if necessary.
+ */
+ private static void ensureDir(Path directory) {
+ File dir = directory.toFile() ;
+ if ( ! dir.exists() ) {
+ boolean b = dir.mkdirs() ;
+ if ( ! b )
+ throw new FusekiConfigException("Failed to create directory: "+directory) ;
+ }
+ else if ( ! dir.isDirectory())
+ throw new FusekiConfigException("Not a directory: "+directory) ;
+ }
+
+ private static void mustExist(Path directory) {
+ File dir = directory.toFile() ;
+ if ( ! dir.exists() )
+ throw new FusekiConfigException("Does not exist: "+directory) ;
+ if ( ! dir.isDirectory())
+ throw new FusekiConfigException("Not a directory: "+directory) ;
+ }
+
+ private static boolean exists(Path directory) {
+ File dir = directory.toFile() ;
+ return dir.exists() ;
+ }
+
+ private static Path writeableDirectory(Path root , String relName ) {
+ Path p = makePath(root, relName) ;
+ ensureDir(p);
+ if ( ! Files.isWritable(p) )
+ throw new FusekiConfigException("Not writable: "+p) ;
+ return p ;
+ }
+
+ private static Path makePath(Path root , String relName ) {
+ Path path = root.resolve(relName) ;
+ // Must exist
+// try { path = path.toRealPath() ; }
+// catch (IOException e) { IO.exception(e) ; }
+ return path ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServerEnvironmentInit.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServerEnvironmentInit.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServerEnvironmentInit.java
new file mode 100644
index 0000000..356dc82
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServerEnvironmentInit.java
@@ -0,0 +1,41 @@
+/**
+ * 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.server;
+
+import javax.servlet.ServletContextEvent ;
+import javax.servlet.ServletContextListener ;
+
+import org.apache.jena.fuseki.FusekiLogging ;
+
+/** Setup the enviroment and logging.
+ * Runs before the ShiroEnvironmentLoader.
+ */
+public class FusekiServerEnvironmentInit implements ServletContextListener {
+
+ public FusekiServerEnvironmentInit() { }
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ FusekiEnv.setEnvironment();
+ FusekiLogging.setLogging();
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent sce) {}
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServerListener.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServerListener.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServerListener.java
new file mode 100644
index 0000000..334fc73
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiServerListener.java
@@ -0,0 +1,81 @@
+/**
+ * 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.server;
+
+import javax.servlet.ServletContext ;
+import javax.servlet.ServletContextEvent ;
+import javax.servlet.ServletContextListener ;
+
+import org.apache.jena.fuseki.Fuseki ;
+
+public class FusekiServerListener implements ServletContextListener {
+
+ public FusekiServerListener() { }
+
+ public static ServerInitialConfig initialSetup = null ;
+
+ private boolean initialized = false ;
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ ServletContext servletContext = sce.getServletContext() ;
+ String x = servletContext.getContextPath() ;
+ if ( ! x.isEmpty() )
+ Fuseki.configLog.info("Context path = "+x) ;
+// String x = System.getProperty("user.dir") ;
+// Path currentRelativePath = Paths.get("");
+// String s = currentRelativePath.toAbsolutePath().toString();
+// confLog.info("dir1 = "+x+" : dir2 = "+s) ;
+ init() ;
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent sce) {}
+
+ public synchronized void init() {
+ if ( initialized )
+ return ;
+ initialized = true ;
+
+ try {
+ FusekiServer.init() ;
+ if ( ! FusekiServer.serverInitialized ) {
+ Fuseki.serverLog.error("Failed to initialize : Server not running") ;
+ return ;
+ }
+
+ if ( initialSetup == null ) {
+ initialSetup = new ServerInitialConfig() ;
+ String cfg = FusekiEnv.FUSEKI_BASE.resolve(FusekiServer.DFT_CONFIG).toAbsolutePath().toString() ;
+ initialSetup.fusekiConfigFile = cfg ;
+ }
+
+ if ( initialSetup != null ) {
+ FusekiServer.initializeDataAccessPoints(initialSetup, FusekiServer.dirConfiguration.toString()) ;
+ } else {
+ Fuseki.serverLog.error("No configuration") ;
+ System.exit(0) ;
+ }
+ } catch (Throwable th) {
+ Fuseki.serverLog.error("Exception in initialization: {}", th.getMessage()) ;
+ throw th ;
+ }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java
new file mode 100644
index 0000000..ddae32c
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java
@@ -0,0 +1,77 @@
+/*
+ * 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.server;
+
+import org.apache.jena.fuseki.FusekiException ;
+import org.apache.jena.iri.IRI ;
+import org.apache.jena.riot.system.IRIResolver ;
+
+import com.hp.hpl.jena.rdf.model.* ;
+
+public class FusekiVocab
+{
+ public static String NS = "http://jena.apache.org/fuseki#" ;
+ private static Model model = ModelFactory.createDefaultModel() ;
+
+ public static final Resource tServer = resource("Server") ;
+
+ public static final Resource fusekiService = resource("Service") ;
+
+ public static final Property pServices = property("services") ;
+ public static final Property pServiceName = property("name") ;
+
+ public static final Property pServiceQueryEP = property("serviceQuery") ;
+ public static final Property pServiceUpdateEP = property("serviceUpdate") ;
+ public static final Property pServiceUploadEP = property("serviceUpload") ;
+ public static final Property pServiceReadWriteGraphStoreEP = property("serviceReadWriteGraphStore") ;
+ public static final Property pServiceReadgraphStoreEP = property("serviceReadGraphStore") ;
+
+ public static final Property pAllowTimeoutOverride = property("allowTimeoutOverride");
+ public static final Property pMaximumTimeoutOverride = property("maximumTimeoutOverride");
+
+ // Internal
+
+ private static final String stateNameActive = DatasetStatus.ACTIVE.name ;
+ private static final String stateNameOffline = DatasetStatus.OFFLINE.name ;
+ private static final String stateNameClosing = DatasetStatus.CLOSING.name ;
+ private static final String stateNameClosed = DatasetStatus.CLOSED.name ;
+
+ public static final Resource stateActive = resource(stateNameActive) ;
+ public static final Resource stateOffline = resource(stateNameOffline) ;
+ public static final Resource stateClosing = resource(stateNameClosing) ;
+ public static final Resource stateClosed = resource(stateNameClosed) ;
+
+ public static final Property pStatus = property("status") ;
+
+ private static Resource resource(String localname) { return model.createResource(iri(localname)) ; }
+ private static Property property(String localname) { return model.createProperty(iri(localname)) ; }
+
+ private static String iri(String localname)
+ {
+ String uri = NS+localname ;
+ IRI iri = IRIResolver.parseIRI(uri) ;
+ if ( iri.hasViolation(true) )
+ throw new FusekiException("Bad IRI: "+iri) ;
+ if ( ! iri.isAbsolute() )
+ throw new FusekiException("Bad IRI: "+iri) ;
+
+ return uri ;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/OperationName.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/OperationName.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/OperationName.java
new file mode 100644
index 0000000..0abcf20
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/OperationName.java
@@ -0,0 +1,37 @@
+/**
+ * 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.server;
+
+public enum OperationName {
+ // Fixed names give the codebase some resilience.
+
+ Query("SPARQL Query"),
+ Update("SPARQL Update"),
+ Upload("File Upload"),
+ GSP("Graph Store Protocol"),
+ GSP_R("Graph Store Protocol (Read)"),
+ Quads("HTTP Quads")
+ ;
+
+ private final String description ;
+ private OperationName(String description) { this.description = description ; }
+ public String getDescription() { return description ; }
+
+}
+