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 ; } + +} +
