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:48 UTC
[46/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/ActionAsyncTask.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionAsyncTask.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionAsyncTask.java
new file mode 100644
index 0000000..8d8a080
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionAsyncTask.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.mgt;
+
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.atlas.json.JsonValue ;
+import org.apache.jena.atlas.lib.InternalErrorException ;
+import org.apache.jena.fuseki.async.AsyncPool ;
+import org.apache.jena.fuseki.async.AsyncTask ;
+import org.apache.jena.fuseki.servlets.HttpAction ;
+import org.apache.jena.fuseki.servlets.ServletOps ;
+
+/** Base helper class for creating async tasks on "items", based on POST */
+public abstract class ActionAsyncTask extends ActionItem
+{
+ // ?? Better as a library (mixin) so can be used outside ActionItem
+ private static AsyncPool asyncPool = AsyncPool.get() ;
+
+ public ActionAsyncTask() { super() ; }
+
+ @Override
+ final
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) {
+ ServletOps.errorMethodNotAllowed(METHOD_GET);
+ }
+
+ @Override
+ final
+ protected JsonValue execGetItem(HttpAction action) {
+ throw new InternalErrorException("GET for AsyncTask -- Should not be here!") ;
+ }
+
+ @Override
+ final
+ protected JsonValue execPostItem(HttpAction action) {
+ Runnable task = createRunnable(action) ;
+ AsyncTask aTask = Async.execASyncTask(action, AsyncPool.get(), "backup", task) ;
+ Async.setLocationHeader(action, aTask);
+ return Async.asJson(aTask) ;
+ }
+
+ public static AsyncTask execASyncTask(HttpAction action, AsyncPool asyncPool, String displayName, Runnable task) {
+ AsyncTask atask = Async.asyncTask(asyncPool, displayName, action.getDataService(), task) ;
+ Async.setLocationHeader(action, atask);
+ JsonValue v = Async.asJson(atask) ;
+ ServletOps.sendJsonReponse(action, v);
+ return atask ;
+ }
+
+ protected abstract Runnable createRunnable(HttpAction action) ;
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackup.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackup.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackup.java
new file mode 100644
index 0000000..34f134e
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionBackup.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.mgt;
+
+import static java.lang.String.format ;
+
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.fuseki.servlets.HttpAction ;
+import org.apache.jena.fuseki.servlets.ServletOps ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+
+public class ActionBackup extends ActionAsyncTask
+{
+ public ActionBackup() { super() ; }
+
+ // Only POST
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) {
+ doCommon(request, response);
+ }
+
+ @Override
+ protected Runnable createRunnable(HttpAction action) {
+ String name = action.getDatasetName() ;
+ if ( name == null ) {
+ action.log.error("Null for dataset name in item request") ;
+ ServletOps.errorOccurred("Null for dataset name in item request");
+ return null ;
+ }
+ action.log.info(format("[%d] Backup dataset %s", action.id, name)) ;
+ return new BackupTask(action) ;
+ }
+
+ static class BackupTask implements Runnable {
+ static private Logger log = LoggerFactory.getLogger("Backup") ;
+
+ private final long actionId ;
+ private final DatasetGraph dataset ;
+ private final String datasetName ;
+
+ public BackupTask(HttpAction action) {
+ this.actionId = action.id ;
+ action.getDataAccessPoint() ;
+ action.getDataAccessPoint().getDataService() ;
+ action.getDataAccessPoint().getDataService().getDataset() ;
+ this.dataset = action.getDataAccessPoint().getDataService().getDataset() ;
+ this.datasetName = action.getDatasetName() ;
+ }
+
+ @Override
+ public void run() {
+ try {
+ String backupFilename = Backup.chooseFileName(datasetName) ;
+ log.info(format("[%d] >>>> Start backup %s -> %s", actionId, datasetName, backupFilename)) ;
+ Backup.backup(dataset, backupFilename) ;
+ log.info(format("[%d] <<<< Finish backup %s -> %s", actionId, datasetName, backupFilename)) ;
+ } catch (Exception ex) {
+ log.info(format("[%d] **** Exception in backup", actionId), ex) ;
+ }
+ }
+ }
+}
+
\ 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/mgt/ActionContainerItem.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionContainerItem.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionContainerItem.java
new file mode 100644
index 0000000..134afc4
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionContainerItem.java
@@ -0,0 +1,94 @@
+/**
+ * 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 org.apache.jena.atlas.json.JsonValue ;
+import org.apache.jena.fuseki.servlets.HttpAction ;
+import org.apache.jena.fuseki.servlets.ServletOps ;
+import org.apache.jena.web.HttpSC ;
+
+/** Base for actions that are container and also have action on items */
+public abstract class ActionContainerItem extends ActionCtl {
+
+ public ActionContainerItem() { super() ; }
+
+ @Override
+ final
+ protected void perform(HttpAction action) {
+ String method = action.request.getMethod() ;
+ if ( method.equals(METHOD_GET) )
+ execGet(action) ;
+ else if ( method.equals(METHOD_POST) )
+ execPost(action) ;
+ else if ( method.equals(METHOD_DELETE) )
+ execDelete(action) ;
+ else
+ ServletOps.error(HttpSC.METHOD_NOT_ALLOWED_405) ;
+ }
+
+ protected void execGet(HttpAction action) {
+ JsonValue v ;
+ if ( isContainerAction(action) )
+ v = execGetContainer(action) ;
+ else
+ v = execGetItem(action) ;
+
+ ServletOps.sendJsonReponse(action, v);
+ }
+
+ /** GET request on the container - respond with JSON, or null for plain 200 */
+ protected abstract JsonValue execGetContainer(HttpAction action) ;
+ /** GET request on an item in the container - repond with JSON, or null for plain 200 */
+ protected abstract JsonValue execGetItem(HttpAction action) ;
+
+ protected void execPost(HttpAction action) {
+ JsonValue v ;
+ if ( isContainerAction(action) )
+ v = execPostContainer(action) ;
+ else
+ v = execPostItem(action) ;
+
+ ServletOps.sendJsonReponse(action, v);
+ }
+
+ /** POST request on an item in the container - respond with JSON, or null for plain 200 */
+ protected abstract JsonValue execPostContainer(HttpAction action) ;
+ /** POST request on an item in the container - respond with JSON, or null for plain 200 */
+ protected abstract JsonValue execPostItem(HttpAction action) ;
+
+
+ /** DELETE request */
+ protected void execDelete(HttpAction action) {
+ if ( isContainerAction(action) )
+ execDeleteContainer(action) ;
+ else
+ execDeleteItem(action) ;
+ ServletOps.success(action) ;
+ }
+
+ /** DELETE request on an item in the container */
+ protected void execDeleteContainer(HttpAction action) {
+ ServletOps.errorMethodNotAllowed(METHOD_DELETE, "DELETE applied to a container") ;
+ }
+
+ /** DELETE request on an item in the container */
+ protected void execDeleteItem(HttpAction action) {
+ ServletOps.errorMethodNotAllowed(METHOD_DELETE) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionCtl.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionCtl.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionCtl.java
new file mode 100644
index 0000000..20073d9
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionCtl.java
@@ -0,0 +1,97 @@
+/*
+ * 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 org.apache.jena.fuseki.Fuseki ;
+import org.apache.jena.fuseki.server.DataAccessPoint ;
+import org.apache.jena.fuseki.server.DataAccessPointRegistry ;
+import org.apache.jena.fuseki.server.DataService ;
+import org.apache.jena.fuseki.servlets.ActionBase ;
+import org.apache.jena.fuseki.servlets.HttpAction ;
+import org.apache.jena.fuseki.servlets.ServletOps ;
+
+/** Control/admin request lifecycle */
+public abstract class ActionCtl extends ActionBase
+{
+ protected ActionCtl() { super(Fuseki.adminLog) ; }
+
+ @Override
+ final
+ protected void execCommonWorker(HttpAction action) {
+ DataAccessPoint dataAccessPoint ;
+ DataService dSrv ;
+
+ String datasetUri = mapRequestToDatasetName(action) ;
+ if ( datasetUri != null ) {
+ dataAccessPoint = DataAccessPointRegistry.get().get(datasetUri) ;
+ if ( dataAccessPoint == null ) {
+ ServletOps.errorNotFound("Not found: "+datasetUri) ;
+ return ;
+ }
+ }
+ else {
+ // This is a placeholder when creating new DatasetRefs
+ // and also if addressing a container, not a dataset
+ dataAccessPoint = null ;
+ dSrv = DataService.serviceOnlyDataService() ;
+ }
+
+ action.setControlRequest(dataAccessPoint, datasetUri) ;
+ action.setEndpoint(null, null) ; // No operation or service name.
+ executeAction(action) ;
+ }
+
+ protected String mapRequestToDatasetName(HttpAction action) {
+ return extractItemName(action) ;
+ }
+
+ // Execute - no stats.
+ // Intercept point for the UberServlet
+ protected void executeAction(HttpAction action) {
+ executeLifecycle(action) ;
+ }
+
+ // This is the service request lifecycle.
+ final
+ protected void executeLifecycle(HttpAction action)
+ {
+ startRequest(action) ;
+ try {
+ perform(action) ;
+ }
+ finally {
+ finishRequest(action) ;
+ }
+ }
+
+ final
+ protected boolean isContainerAction(HttpAction action) {
+ return (action.getDataAccessPoint() == null ) ;
+ }
+
+ protected abstract void perform(HttpAction action) ;
+
+// /** Map request to uri in the registry.
+// * null means no mapping done (passthrough).
+// */
+// protected String mapRequestToDataset(HttpAction action)
+// {
+// return ActionLib.mapRequestToDataset(action.request.getRequestURI()) ;
+// }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
new file mode 100644
index 0000000..ea3d44e
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
@@ -0,0 +1,404 @@
+/**
+ * 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 static java.lang.String.format ;
+
+import java.io.* ;
+import java.util.HashMap ;
+import java.util.Iterator ;
+import java.util.Map ;
+
+import javax.servlet.ServletException ;
+import javax.servlet.ServletOutputStream ;
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.atlas.io.IO ;
+import org.apache.jena.atlas.json.JsonBuilder ;
+import org.apache.jena.atlas.json.JsonValue ;
+import org.apache.jena.atlas.lib.InternalErrorException ;
+import org.apache.jena.atlas.lib.StrUtils ;
+import org.apache.jena.atlas.web.ContentType ;
+import org.apache.jena.fuseki.FusekiLib ;
+import org.apache.jena.fuseki.build.Builder ;
+import org.apache.jena.fuseki.build.Template ;
+import org.apache.jena.fuseki.build.TemplateFunctions ;
+import org.apache.jena.fuseki.server.* ;
+import org.apache.jena.fuseki.servlets.* ;
+import org.apache.jena.riot.Lang ;
+import org.apache.jena.riot.RDFDataMgr ;
+import org.apache.jena.riot.RDFLanguages ;
+import org.apache.jena.riot.WebContent ;
+import org.apache.jena.riot.system.StreamRDF ;
+import org.apache.jena.riot.system.StreamRDFLib ;
+import org.apache.jena.web.HttpSC ;
+
+import com.hp.hpl.jena.datatypes.xsd.XSDDatatype ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.NodeFactory ;
+import com.hp.hpl.jena.query.Dataset ;
+import com.hp.hpl.jena.query.ReadWrite ;
+import com.hp.hpl.jena.rdf.model.* ;
+import com.hp.hpl.jena.shared.uuid.JenaUUID ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.Quad ;
+import com.hp.hpl.jena.sparql.util.FmtUtils ;
+import com.hp.hpl.jena.tdb.transaction.DatasetGraphTransaction ;
+import com.hp.hpl.jena.update.UpdateAction ;
+import com.hp.hpl.jena.update.UpdateFactory ;
+import com.hp.hpl.jena.update.UpdateRequest ;
+
+public class ActionDatasets extends ActionContainerItem {
+
+ private static Dataset system = SystemState.getDataset() ;
+ private static DatasetGraphTransaction systemDSG = SystemState.getDatasetGraph() ;
+
+ static private Property pServiceName = FusekiVocab.pServiceName ;
+ static private Property pStatus = FusekiVocab.pStatus ;
+
+ private static final String paramDatasetName = "dbName" ;
+ private static final String paramDatasetType = "dbType" ;
+ private static final String tDatabasetTDB = "tdb" ;
+ private static final String tDatabasetMem = "mem" ;
+
+ public ActionDatasets() { super() ; }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) {
+ doCommon(request, response);
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) {
+ doCommon(request, response);
+ }
+
+ @Override
+ protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ doCommon(request, response);
+ }
+
+ // ---- GET : return details of dataset or datasets.
+ @Override
+ protected JsonValue execGetContainer(HttpAction action) {
+ action.log.info(format("[%d] GET datasets", action.id)) ;
+ JsonBuilder builder = new JsonBuilder() ;
+ builder.startObject("D") ;
+ builder.key(JsonConst.datasets) ;
+ JsonDescription.arrayDatasets(builder, DataAccessPointRegistry.get());
+ builder.finishObject("D") ;
+ return builder.build() ;
+ }
+
+ @Override
+ protected JsonValue execGetItem(HttpAction action) {
+ action.log.info(format("[%d] GET dataset %s", action.id, action.getDatasetName())) ;
+ JsonBuilder builder = new JsonBuilder() ;
+ DataAccessPoint dsDesc = DataAccessPointRegistry.get().get(action.getDatasetName()) ;
+ if ( dsDesc == null )
+ ServletOps.errorNotFound("Not found: dataset "+action.getDatasetName());
+ JsonDescription.describe(builder, dsDesc) ;
+ return builder.build() ;
+ }
+
+ // ---- POST
+
+ @Override
+ protected JsonValue execPostContainer(HttpAction action) {
+ JenaUUID uuid = JenaUUID.generate() ;
+ String newURI = uuid.asURI() ;
+ Node gn = NodeFactory.createURI(newURI) ;
+
+ ContentType ct = FusekiLib.getContentType(action) ;
+
+ boolean committed = false ;
+ system.begin(ReadWrite.WRITE) ;
+ try {
+ Model model = system.getNamedModel(gn.getURI()) ;
+ StreamRDF dest = StreamRDFLib.graph(model.getGraph()) ;
+
+ if ( WebContent.isHtmlForm(ct) )
+ assemblerFromForm(action, dest) ;
+ else if ( WebContent.isMultiPartForm(ct) )
+ assemblerFromUpload(action, dest) ;
+ else
+ assemblerFromBody(action, dest) ;
+
+ // Keep a persistent copy.
+ String filename = FusekiServer.dirFileArea.resolve(uuid.asString()).toString() ;
+ try ( OutputStream outCopy = new FileOutputStream(filename) ) {
+ RDFDataMgr.write(outCopy, model, Lang.TURTLE) ;
+ }
+
+ Statement stmt = getOne(model, null, pServiceName, null) ;
+ if ( stmt == null ) {
+ StmtIterator sIter = model.listStatements(null, 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") ;
+ }
+
+ if ( ! stmt.getObject().isLiteral() )
+ ServletOps.errorBadRequest("Found "+FmtUtils.stringForRDFNode(stmt.getObject())+" : Service names are strings, then used to build the external URI") ;
+
+ Resource subject = stmt.getSubject() ;
+ Literal object = stmt.getObject().asLiteral() ;
+
+ if ( object.getDatatype() != null && ! object.getDatatype().equals(XSDDatatype.XSDstring) )
+ action.log.warn(format("[%d] Service name '%s' is not a string", action.id, FmtUtils.stringForRDFNode(object)));
+
+ String datasetName = object.getLexicalForm() ;
+ String datasetPath = DataAccessPoint.canonical(datasetName) ;
+ action.log.info(format("[%d] Create database : name = %s", action.id, datasetPath)) ;
+
+ if ( DataAccessPointRegistry.get().isRegistered(datasetPath) )
+ // And abort.
+ ServletOps.error(HttpSC.CONFLICT_409, "Name already registered "+datasetPath) ;
+
+ model.removeAll(null, pStatus, null) ;
+ model.add(subject, pStatus, FusekiVocab.stateActive) ;
+
+ // Need to be in Resource space at this point.
+ DataAccessPoint ref = Builder.buildDataAccessPoint(subject) ;
+ DataAccessPointRegistry.register(datasetPath, ref) ;
+ action.getResponse().setContentType(WebContent.contentTypeTextPlain);
+ ServletOutputStream out = action.getResponse().getOutputStream() ;
+ out.println("That went well") ;
+ ServletOps.success(action) ;
+ system.commit();
+ committed = true ;
+
+ } catch (IOException ex) { IO.exception(ex); }
+ finally {
+ if ( ! committed ) system.abort() ;
+ system.end() ;
+ }
+ return null ;
+ }
+
+ @Override
+ protected JsonValue execPostItem(HttpAction action) {
+ String name = action.getDatasetName() ;
+ if ( name == null )
+ name = "''" ;
+ action.log.info(format("[%d] POST dataset %s", action.id, name)) ;
+
+ if ( action.getDataAccessPoint() == null )
+ ServletOps.errorNotFound("Not found: dataset "+action.getDatasetName());
+
+ DataService dSrv = action.getDataService() ;
+ if ( dSrv == null )
+ // If not set explicitly, take from DataAccessPoint
+ dSrv = action.getDataAccessPoint().getDataService() ;
+
+ String s = action.request.getParameter("state") ;
+ if ( s == null || s.isEmpty() )
+ ServletOps.errorBadRequest("No state change given") ;
+
+ // setDatasetState is a transaction on the persistent state of the server.
+ if ( s.equalsIgnoreCase("active") ) {
+ action.log.info(format("[%d] REBUILD DATASET %s", action.id, name)) ;
+ setDatasetState(name, FusekiVocab.stateActive) ;
+ dSrv.goActive() ;
+ // DatasetGraph dsg = ???? ;
+ //dSrv.activate(dsg) ;
+ //dSrv.activate() ;
+ } else if ( s.equalsIgnoreCase("offline") ) {
+ action.log.info(format("[%d] OFFLINE DATASET %s", action.id, name)) ;
+ DataAccessPoint access = action.getDataAccessPoint() ;
+ //access.goOffline() ;
+ dSrv.goOffline() ; // Affects the target of the name.
+ setDatasetState(name, FusekiVocab.stateOffline) ;
+ //dSrv.offline() ;
+ } else if ( s.equalsIgnoreCase("unlink") ) {
+ action.log.info(format("[%d] UNLINK ACCESS NAME %s", action.id, name)) ;
+ DataAccessPoint access = action.getDataAccessPoint() ;
+ ServletOps.errorNotImplemented("unlink: dataset"+action.getDatasetName());
+ //access.goOffline() ;
+ // Registry?
+ }
+ else
+ ServletOps.errorBadRequest("State change operation '"+s+"' not recognized");
+ return null ;
+ }
+
+ private void assemblerFromBody(HttpAction action, StreamRDF dest) {
+ bodyAsGraph(action, dest) ;
+ }
+
+ private void assemblerFromForm(HttpAction action, StreamRDF dest) {
+ String dbType = action.getRequest().getParameter(paramDatasetType) ;
+ String dbName = action.getRequest().getParameter(paramDatasetName) ;
+ Map<String, String> params = new HashMap<>() ;
+ params.put(Template.NAME, dbName) ;
+ FusekiServer.addGlobals(params);
+
+ //action.log.info(format("[%d] Create database : name = %s, type = %s", action.id, dbName, dbType )) ;
+ if ( dbType == null || dbName == null )
+ ServletOps.errorBadRequest("Required parameters: dbName and dbType");
+ if ( ! dbType.equals(tDatabasetTDB) && ! dbType.equals(tDatabasetMem) )
+ ServletOps.errorBadRequest(format("dbType can be only '%s' or '%s'", tDatabasetTDB, tDatabasetMem)) ;
+
+ String template = null ;
+ if ( dbType.equalsIgnoreCase(tDatabasetTDB))
+ template = TemplateFunctions.templateFile(Template.templateTDBFN, params) ;
+ if ( dbType.equalsIgnoreCase(tDatabasetMem))
+ template = TemplateFunctions.templateFile(Template.templateMemFN, params) ;
+ RDFDataMgr.parse(dest, new StringReader(template), "http://base/", Lang.TTL) ;
+ }
+
+ private void assemblerFromUpload(HttpAction action, StreamRDF dest) {
+ Upload.fileUploadWorker(action, dest);
+ }
+
+ // ---- DELETE
+
+ @Override
+ protected void execDeleteItem(HttpAction action) {
+// if ( isContainerAction(action) ) {
+// ServletOps.errorBadRequest("DELETE only applies to a specific dataset.") ;
+// return ;
+// }
+
+ // Does not exist?
+ String name = action.getDatasetName() ;
+ if ( name == null )
+ name = "" ;
+ action.log.info(format("[%d] DELETE ds=%s", action.id, name)) ;
+
+ if ( ! DataAccessPointRegistry.get().isRegistered(name) )
+ ServletOps.errorNotFound("No such dataset registered: "+name);
+
+ systemDSG.begin(ReadWrite.WRITE) ;
+ boolean committed = false ;
+ try {
+ // Here, go offline.
+ // Need to reference count operations when they drop to zero
+ // or a timer goes off, we delete the dataset.
+
+ DataAccessPoint ref = DataAccessPointRegistry.get().get(name) ;
+ // Redo check inside transaction.
+ if ( ref == null )
+ ServletOps.errorNotFound("No such dataset registered: "+name);
+
+ // Make it invisible to the outside.
+ DataAccessPointRegistry.get().remove(name) ;
+
+ // Name to graph
+ // Statically configured databases aren't in the system database.
+ Quad q = getOne(systemDSG, null, null, pServiceName.asNode(), null) ;
+// if ( q == null )
+// ServletOps.errorBadRequest("Failed to find dataset for '"+name+"'");
+ if ( q != null ) {
+ Node gn = q.getGraph() ;
+ //action.log.info("SHUTDOWN NEEDED"); // To ensure it goes away?
+ systemDSG.deleteAny(gn, null, null, null) ;
+ }
+ systemDSG.commit() ;
+ committed = true ;
+ ServletOps.success(action) ;
+ } finally {
+ if ( ! committed ) systemDSG.abort() ;
+ systemDSG.end() ;
+ }
+ }
+
+ // Persistent state change.
+ private void setDatasetState(String name, Resource newState) {
+ boolean committed = false ;
+ system.begin(ReadWrite.WRITE) ;
+ try {
+ String dbName = name ;
+ if ( dbName.startsWith("/") )
+ dbName = dbName.substring(1) ;
+
+ String update = StrUtils.strjoinNL
+ (SystemState.PREFIXES,
+ "DELETE { GRAPH ?g { ?s fu:status ?state } }",
+ "INSERT { GRAPH ?g { ?s fu:status "+FmtUtils.stringForRDFNode(newState)+" } }",
+ "WHERE {",
+ " GRAPH ?g { ?s fu:name '"+dbName+"' ; ",
+ " fu:status ?state .",
+ " }",
+ "}"
+ ) ;
+ UpdateRequest req = UpdateFactory.create(update) ;
+ UpdateAction.execute(req, system);
+ system.commit();
+ committed = true ;
+ } finally {
+ if ( ! committed ) system.abort() ;
+ system.end() ;
+ }
+ }
+
+ // ---- Auxilary functions
+
+ private static Quad getOne(DatasetGraph dsg, Node g, Node s, Node p, Node o) {
+ Iterator<Quad> iter = dsg.findNG(g, s, p, o) ;
+ if ( ! iter.hasNext() )
+ return null ;
+ Quad q = iter.next() ;
+ if ( iter.hasNext() )
+ return null ;
+ return q ;
+ }
+
+ 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 ;
+ }
+
+ // XXX Merge with Upload.incomingData
+
+ private static void bodyAsGraph(HttpAction action, StreamRDF dest) {
+ HttpServletRequest request = action.request ;
+ String base = ActionLib.wholeRequestURL(request) ;
+ ContentType ct = FusekiLib.getContentType(request) ;
+ Lang lang = RDFLanguages.contentTypeToLang(ct.getContentType()) ;
+ if ( lang == null ) {
+ ServletOps.errorBadRequest("Unknown content type for triples: " + ct) ;
+ return ;
+ }
+ InputStream input = null ;
+ try { input = request.getInputStream() ; }
+ catch (IOException ex) { IO.exception(ex) ; }
+
+ int len = request.getContentLength() ;
+// if ( verbose ) {
+// if ( len >= 0 )
+// alog.info(format("[%d] Body: Content-Length=%d, Content-Type=%s, Charset=%s => %s", action.id, len,
+// ct.getContentType(), ct.getCharset(), lang.getName())) ;
+// else
+// alog.info(format("[%d] Body: Content-Type=%s, Charset=%s => %s", action.id, ct.getContentType(),
+// ct.getCharset(), lang.getName())) ;
+// }
+ dest.prefix("root", base+"#");
+ ActionSPARQL.parse(action, dest, input, lang, base) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionItem.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionItem.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionItem.java
new file mode 100644
index 0000000..72d3c65
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionItem.java
@@ -0,0 +1,45 @@
+/**
+ * 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 org.apache.jena.atlas.json.JsonValue ;
+import org.apache.jena.fuseki.servlets.HttpAction ;
+import org.apache.jena.fuseki.servlets.ServletOps ;
+import org.apache.jena.web.HttpSC ;
+
+/** Action on items in a container, but not the container itself */
+public abstract class ActionItem extends ActionContainerItem
+{
+ public ActionItem() { super() ; }
+
+ @Override
+ final
+ protected JsonValue execGetContainer(HttpAction action) {
+ ServletOps.error(HttpSC.METHOD_NOT_ALLOWED_405) ;
+ return null ;
+ }
+
+ @Override
+ final
+ protected JsonValue execPostContainer(HttpAction action) {
+ ServletOps.error(HttpSC.METHOD_NOT_ALLOWED_405) ;
+ 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/mgt/ActionLogs.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionLogs.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionLogs.java
new file mode 100644
index 0000000..c4d6579
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionLogs.java
@@ -0,0 +1,59 @@
+/**
+ * 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 static org.apache.jena.riot.WebContent.charsetUTF8 ;
+import static org.apache.jena.riot.WebContent.contentTypeTextPlain ;
+
+import java.io.IOException ;
+
+import javax.servlet.ServletOutputStream ;
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.fuseki.servlets.HttpAction ;
+import org.apache.jena.fuseki.servlets.ServletOps ;
+
+public class ActionLogs extends ActionCtl
+{
+ public ActionLogs() { super() ; }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
+ doCommon(req, resp);
+ }
+
+ @Override
+ protected void perform(HttpAction action) {
+ execGet(action) ;
+ }
+
+ protected void execGet(HttpAction action) {
+ try {
+ HttpServletResponse response = action.response ;
+ ServletOutputStream out = response.getOutputStream() ;
+ response.setContentType(contentTypeTextPlain) ;
+ response.setCharacterEncoding(charsetUTF8) ;
+ out.println("Not implemented yet") ;
+ out.println() ;
+ out.flush() ;
+ ServletOps.success(action);
+ } catch (IOException ex) { ServletOps.errorOccurred(ex) ; }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionPing.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionPing.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionPing.java
new file mode 100644
index 0000000..b43b9f1
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionPing.java
@@ -0,0 +1,78 @@
+/**
+ * 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 static org.apache.jena.riot.WebContent.charsetUTF8 ;
+import static org.apache.jena.riot.WebContent.contentTypeTextPlain ;
+
+import java.io.IOException ;
+
+import javax.servlet.ServletOutputStream ;
+import javax.servlet.http.HttpServlet ;
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import com.hp.hpl.jena.sparql.util.Utils ;
+
+import org.apache.jena.fuseki.Fuseki ;
+import org.apache.jena.fuseki.servlets.ServletOps ;
+import org.apache.jena.web.HttpSC ;
+
+/** The ping servlet provides a low costy, uncached endpoint that can be used
+ * to determine if this component is running and responding. For example,
+ * a nagios check should use this endpoint.
+ */
+public class ActionPing extends HttpServlet
+{
+ // Ping is special.
+ // To avoid excessive logging and id allocation for a "noise" operation,
+ // this is a raw servlet.
+ public ActionPing() { super() ; }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
+ doCommon(req, resp);
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
+ doCommon(req, resp);
+ }
+
+
+ @Override
+ protected void doHead(HttpServletRequest req, HttpServletResponse resp) {
+ doCommon(req, resp);
+ }
+
+ protected void doCommon(HttpServletRequest request, HttpServletResponse response) {
+ try {
+ ServletOps.setNoCache(response) ;
+ response.setContentType(contentTypeTextPlain);
+ response.setCharacterEncoding(charsetUTF8) ;
+ response.setStatus(HttpSC.OK_200);
+ ServletOutputStream out = response.getOutputStream() ;
+ out.println(Utils.nowAsXSDDateTimeString());
+ } catch (IOException ex) {
+ Fuseki.serverLog.warn("ping :: IOException :: "+ex.getMessage());
+ }
+ }
+}
+
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionServerStatus.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionServerStatus.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionServerStatus.java
new file mode 100644
index 0000000..d8f5b1e
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionServerStatus.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.mgt;
+
+import static org.apache.jena.riot.WebContent.charsetUTF8 ;
+import static org.apache.jena.riot.WebContent.contentTypeJSON ;
+
+import java.io.IOException ;
+
+import javax.servlet.ServletOutputStream ;
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.atlas.json.JSON ;
+import org.apache.jena.atlas.json.JsonBuilder ;
+import org.apache.jena.atlas.json.JsonValue ;
+import org.apache.jena.fuseki.Fuseki ;
+import org.apache.jena.fuseki.server.DataAccessPointRegistry ;
+import org.apache.jena.fuseki.servlets.HttpAction ;
+import org.apache.jena.fuseki.servlets.ServletOps ;
+
+/** Description of datasets for a server */
+public class ActionServerStatus extends ActionCtl
+{
+ public ActionServerStatus() { super() ; }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
+ doCommon(req, resp) ;
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
+ doCommon(req, resp) ;
+ }
+
+ @Override
+ protected void perform(HttpAction action) {
+ try {
+ description(action) ;
+ ServletOps.success(action) ;
+ } catch (IOException e) {
+ ServletOps.errorOccurred(e) ;
+ }
+ }
+
+ private void description(HttpAction action) throws IOException {
+ ServletOutputStream out = action.response.getOutputStream() ;
+ action.response.setContentType(contentTypeJSON);
+ action.response.setCharacterEncoding(charsetUTF8) ;
+
+ JsonBuilder builder = new JsonBuilder() ;
+ builder.startObject() ;
+ describeServer(builder, action.request.getLocalPort()) ;
+ describeDatasets(builder) ;
+ builder.finishObject() ;
+
+ JsonValue v = builder.build() ;
+ JSON.write(out, v) ;
+ out.println() ;
+ out.flush() ;
+ }
+
+ private void describeServer(JsonBuilder builder, int requestPort) {
+ String versionStr = Fuseki.VERSION ;
+ String builtDateStr = Fuseki.BUILD_DATE ;
+ if ( versionStr == null || versionStr.startsWith("${") )
+ versionStr = "Development" ;
+ if ( builtDateStr == null || builtDateStr.startsWith("${") )
+ builtDateStr = "Unknown" ;
+
+// builder
+// .key(JsonConst.server)
+// .startObject()
+// .key(JsonConst.port).value(port)
+// .finishObject() ;
+ builder
+ .key(JsonConst.admin)
+ .startObject()
+ .key(JsonConst.port).value(requestPort)
+ .finishObject() ;
+
+ builder
+ .key(JsonConst.version).value(versionStr)
+ .key(JsonConst.built).value(builtDateStr)
+ .key(JsonConst.startDT).value(Fuseki.serverStartedAt())
+ .key(JsonConst.uptime).value(Fuseki.serverUptimeSeconds())
+ ;
+
+ }
+
+ private void describeDatasets(JsonBuilder builder) {
+ builder.key(JsonConst.datasets) ;
+ JsonDescription.arrayDatasets(builder, DataAccessPointRegistry.get());
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionSleep.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionSleep.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionSleep.java
new file mode 100644
index 0000000..e53eb9a
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionSleep.java
@@ -0,0 +1,98 @@
+/**
+ * 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 static java.lang.String.format ;
+
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.atlas.json.JsonValue ;
+import org.apache.jena.atlas.lib.Lib ;
+import org.apache.jena.fuseki.async.AsyncPool ;
+import org.apache.jena.fuseki.async.AsyncTask ;
+import org.apache.jena.fuseki.servlets.HttpAction ;
+import org.apache.jena.fuseki.servlets.ServletOps ;
+import org.slf4j.Logger ;
+
+/** A task that kicks off a asynchornous operation that simply waits and exits. For testing. */
+public class ActionSleep extends ActionCtl /* Not ActionAsyncTask - that is a container */
+{
+ public ActionSleep() { super() ; }
+
+ // And only POST
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) {
+ doCommon(request, response);
+ }
+
+ @Override
+ protected void perform(HttpAction action) {
+ Runnable task = createRunnable(action) ;
+ AsyncTask aTask = Async.execASyncTask(action, AsyncPool.get(), "sleep", task) ;
+ JsonValue v = Async.asJson(aTask) ;
+ Async.setLocationHeader(action, aTask);
+ ServletOps.sendJsonReponse(action, v);
+ }
+
+ protected Runnable createRunnable(HttpAction action) {
+ String name = action.getDatasetName() ;
+ if ( name == null ) {
+// action.log.error("Null for dataset name in item request") ;
+// ServletOps.errorOccurred("Null for dataset name in item request");
+// return null ;
+ name = "''" ;
+ }
+
+ String interval = action.request.getParameter("interval") ;
+ int sleepMilli = 5000 ;
+ if ( interval != null )
+ try {
+ sleepMilli = Integer.parseInt(interval) ;
+ } catch (NumberFormatException ex) {
+ action.log.error(format("[%d] NumberFormatException: %s", action.id, interval)) ;
+ }
+ action.log.info(format("[%d] Sleep %s %d ms", action.id, name, sleepMilli)) ;
+ return new SleepTask(action, sleepMilli) ;
+ }
+
+ static class SleepTask implements Runnable {
+ private final Logger log ;
+ private final long actionId ;
+ private final int sleepMilli ;
+
+ public SleepTask(HttpAction action, int sleepMilli ) {
+ this.log = action.log ;
+ this.actionId = action.id ;
+ this.sleepMilli = sleepMilli ;
+ }
+
+ @Override
+ public void run() {
+ try {
+ log.info(format("[%d] >> Sleep start", actionId)) ;
+ Lib.sleep(sleepMilli) ;
+ log.info(format("[%d] << Sleep finish", actionId)) ;
+ } catch (Exception ex) {
+ log.info(format("[%d] **** Exception", actionId), ex) ;
+ }
+ }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionStats.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionStats.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionStats.java
new file mode 100644
index 0000000..490bce2
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionStats.java
@@ -0,0 +1,214 @@
+/**
+ * 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 static java.lang.String.format ;
+import static org.apache.jena.riot.WebContent.charsetUTF8 ;
+import static org.apache.jena.riot.WebContent.contentTypeTextPlain ;
+
+import java.io.IOException ;
+import java.util.Iterator ;
+import java.util.List ;
+
+import javax.servlet.ServletOutputStream ;
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.atlas.json.JsonBuilder ;
+import org.apache.jena.atlas.json.JsonValue ;
+import org.apache.jena.fuseki.server.* ;
+import org.apache.jena.fuseki.servlets.HttpAction ;
+
+public class ActionStats extends ActionContainerItem
+{
+ // XXX Use ActionContainerItem
+ public ActionStats() { super() ; }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
+ doCommon(req, resp);
+ }
+
+ // This does not consult the system database for dormant etc.
+ @Override
+ protected JsonValue execGetContainer(HttpAction action) {
+ action.log.info(format("[%d] GET stats all", action.id)) ;
+ JsonBuilder builder = new JsonBuilder() ;
+ builder.startObject("top") ;
+
+ builder.key(JsonConst.datasets) ;
+ builder.startObject("datasets") ;
+ for ( String ds : DataAccessPointRegistry.get().keys() )
+ statsDataset(builder, ds) ;
+ builder.finishObject("datasets") ;
+
+ builder.finishObject("top") ;
+ return builder.build() ;
+ }
+
+ @Override
+ protected JsonValue execGetItem(HttpAction action) {
+ action.log.info(format("[%d] GET stats dataset %s", action.id, action.getDatasetName())) ;
+
+ JsonBuilder builder = new JsonBuilder() ;
+ String datasetPath = DataAccessPoint.canonical(action.getDatasetName()) ;
+ builder.startObject("TOP") ;
+
+ builder.key(JsonConst.datasets) ;
+ builder.startObject("datasets") ;
+ statsDataset(builder, datasetPath) ;
+ builder.finishObject("datasets") ;
+
+ builder.finishObject("TOP") ;
+ return builder.build() ;
+ }
+
+ private void statsDataset(JsonBuilder builder, String ds) {
+ // Object started
+ builder.key(ds) ;
+
+ DataAccessPoint access = DataAccessPointRegistry.get().get(ds) ;
+ DataService dSrv = access.getDataService() ;
+ builder.startObject("counters") ;
+
+ builder.key(CounterName.Requests.name()).value(dSrv.getCounters().value(CounterName.Requests)) ;
+ builder.key(CounterName.RequestsGood.name()).value(dSrv.getCounters().value(CounterName.RequestsGood)) ;
+ builder.key(CounterName.RequestsBad.name()).value(dSrv.getCounters().value(CounterName.RequestsBad)) ;
+
+
+ // Build the operation -> endpoint list map.
+
+// MultiMap<OperationName, Endpoint> map = MultiMap.createMapList() ;
+// for ( OperationName operName : dSrv.getOperations() ) {
+// List<Endpoint> endpoints = access.getDataService().getOperation(operName) ;
+// for ( Endpoint endpoint : endpoints )
+// map.put(operName, endpoint) ;
+// }
+
+
+ builder.key(JsonConst.endpoints).startObject("endpoints") ;
+
+ for ( OperationName operName : dSrv.getOperations() ) {
+ List<Endpoint> endpoints = access.getDataService().getOperation(operName) ;
+// System.err.println(operName+" : "+endpoints.size()) ;
+// for ( Endpoint endpoint : endpoints )
+// System.err.println(" "+endpoint.getEndpoint()) ;
+
+ for ( Endpoint endpoint : endpoints ) {
+
+ // Endpoint names are unique but not services.
+
+ builder.key(endpoint.getEndpoint()) ;
+ builder.startObject() ;
+
+ operationCounters(builder, endpoint);
+ builder.key(JsonConst.operation).value(operName.name()) ;
+ builder.key(JsonConst.description).value(operName.getDescription()) ;
+
+ builder.finishObject() ;
+ }
+ }
+ builder.finishObject("endpoints") ;
+ builder.finishObject("counters") ;
+
+ }
+
+ private void operationCounters(JsonBuilder builder, Endpoint operation) {
+ for (CounterName cn : operation.getCounters().counters()) {
+ Counter c = operation.getCounters().get(cn) ;
+ builder.key(cn.name()).value(c.value()) ;
+ }
+ }
+
+ private void statsTxt(HttpServletResponse resp) throws IOException
+ {
+ ServletOutputStream out = resp.getOutputStream() ;
+ resp.setContentType(contentTypeTextPlain);
+ resp.setCharacterEncoding(charsetUTF8) ;
+
+ Iterator<String> iter = DataAccessPointRegistry.get().keys().iterator() ;
+ while(iter.hasNext())
+ {
+ String ds = iter.next() ;
+ DataAccessPoint desc = DataAccessPointRegistry.get().get(ds) ;
+ statsTxt(out, desc) ;
+ if ( iter.hasNext() )
+ out.println() ;
+ }
+ out.flush() ;
+ }
+
+ private void statsTxt(ServletOutputStream out, DataAccessPoint desc) throws IOException
+ {
+ DataService dSrv = desc.getDataService() ;
+ out.println("Dataset: "+desc.getName()) ;
+ out.println(" Requests = "+dSrv.getCounters().value(CounterName.Requests)) ;
+ out.println(" Good = "+dSrv.getCounters().value(CounterName.RequestsGood)) ;
+ out.println(" Bad = "+dSrv.getCounters().value(CounterName.RequestsBad)) ;
+
+ out.println(" SPARQL Query:") ;
+ out.println(" Request = "+counter(dSrv, OperationName.Query, CounterName.Requests)) ;
+ out.println(" Good = "+counter(dSrv, OperationName.Query, CounterName.RequestsGood)) ;
+ out.println(" Bad requests = "+counter(dSrv, OperationName.Query, CounterName.RequestsBad)) ;
+ out.println(" Timeouts = "+counter(dSrv, OperationName.Query, CounterName.QueryTimeouts)) ;
+ out.println(" Bad exec = "+counter(dSrv, OperationName.Query, CounterName.QueryExecErrors)) ;
+ out.println(" IO Errors = "+counter(dSrv, OperationName.Query, CounterName.QueryIOErrors)) ;
+
+ out.println(" SPARQL Update:") ;
+ out.println(" Request = "+counter(dSrv, OperationName.Update, CounterName.Requests)) ;
+ out.println(" Good = "+counter(dSrv, OperationName.Update, CounterName.RequestsGood)) ;
+ out.println(" Bad requests = "+counter(dSrv, OperationName.Update, CounterName.RequestsBad)) ;
+ out.println(" Bad exec = "+counter(dSrv, OperationName.Update, CounterName.UpdateExecErrors)) ;
+
+ out.println(" Upload:") ;
+ out.println(" Requests = "+counter(dSrv, OperationName.Upload, CounterName.Requests)) ;
+ out.println(" Good = "+counter(dSrv, OperationName.Upload, CounterName.RequestsGood)) ;
+ out.println(" Bad = "+counter(dSrv, OperationName.Upload, CounterName.RequestsBad)) ;
+
+ out.println(" SPARQL Graph Store Protocol:") ;
+ out.println(" GETs = "+gspValue(dSrv, CounterName.HTTPget)+ " (good="+gspValue(dSrv, CounterName.HTTPgetGood)+"/bad="+gspValue(dSrv, CounterName.HTTPGetBad)+")") ;
+ out.println(" PUTs = "+gspValue(dSrv, CounterName.HTTPput)+ " (good="+gspValue(dSrv, CounterName.HTTPputGood)+"/bad="+gspValue(dSrv, CounterName.HTTPputBad)+")") ;
+ out.println(" POSTs = "+gspValue(dSrv, CounterName.HTTPpost)+ " (good="+gspValue(dSrv, CounterName.HTTPpostGood)+"/bad="+gspValue(dSrv, CounterName.HTTPpostBad)+")") ;
+ out.println(" DELETEs = "+gspValue(dSrv, CounterName.HTTPdelete)+ " (good="+gspValue(dSrv, CounterName.HTTPdeleteGood)+"/bad="+gspValue(dSrv, CounterName.HTTPdeleteBad)+")") ;
+ out.println(" HEADs = "+gspValue(dSrv, CounterName.HTTPhead)+ " (good="+gspValue(dSrv, CounterName.HTTPheadGood)+"/bad="+gspValue(dSrv, CounterName.HTTPheadBad)+")") ;
+ }
+
+ private long counter(DataService dSrv, OperationName opName, CounterName cName) {
+ return 0 ;
+ }
+
+ private long gspValue(DataService dSrv, CounterName cn) {
+ return counter(dSrv, OperationName.GSP, cn) +
+ counter(dSrv, OperationName.GSP_R, cn) ;
+ }
+
+ // We shouldn't get here - no doPost above.
+
+ @Override
+ protected JsonValue execPostContainer(HttpAction action) {
+ throw new InternalError(METHOD_POST+" container") ;
+ }
+
+ @Override
+ protected JsonValue execPostItem(HttpAction action) {
+ throw new InternalError(METHOD_POST+" item") ;
+ }
+}
+
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionTasks.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionTasks.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionTasks.java
new file mode 100644
index 0000000..97f8027
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/ActionTasks.java
@@ -0,0 +1,125 @@
+/**
+ * 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 static java.lang.String.format ;
+
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.atlas.json.JsonBuilder ;
+import org.apache.jena.atlas.json.JsonValue ;
+import org.apache.jena.fuseki.Fuseki ;
+import org.apache.jena.fuseki.async.AsyncPool ;
+import org.apache.jena.fuseki.async.AsyncTask ;
+import org.apache.jena.fuseki.servlets.ActionBase ;
+import org.apache.jena.fuseki.servlets.HttpAction ;
+import org.apache.jena.fuseki.servlets.ServletOps ;
+import org.apache.jena.web.HttpSC ;
+
+public class ActionTasks extends ActionBase //ActionContainerItem
+{
+ private static AsyncPool[] pools = { AsyncPool.get() } ;
+
+ public ActionTasks() { super(Fuseki.serverLog) ; }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) {
+ doCommon(request, response);
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) {
+ doCommon(request, response);
+ }
+
+ private static String prefix = "/" ;
+
+ @Override
+ protected void execCommonWorker(HttpAction action) {
+ String name = extractItemName(action) ;
+ if ( name != null ) {
+ if ( name.startsWith(prefix))
+ name = name.substring(prefix.length()) ;
+ else
+ log.warn("Unexpected task name : "+name) ;
+ }
+
+ String method = action.request.getMethod() ;
+ if ( method.equals(METHOD_GET) )
+ execGet(action, name) ;
+ else if ( method.equals(METHOD_POST) )
+ execPost(action, name) ;
+ else
+ ServletOps.error(HttpSC.METHOD_NOT_ALLOWED_405) ;
+ }
+
+ private void execGet(HttpAction action, String name) {
+ if ( name == null )
+ log.info(format("[%d] Tasks", action.id));
+ else
+ log.info(format("[%d] Task %s", action.id, name));
+
+ JsonValue responseBody = null ;
+
+ if ( name == null ) {
+ JsonBuilder builder = new JsonBuilder() ;
+ builder.startArray() ;
+
+ for ( AsyncPool pool : pools ) {
+ for ( AsyncTask aTask : pool.tasks() ) {
+ //builder.value(aTask.getTaskId()) ;
+ descOneTask(builder, aTask) ;
+ }
+ }
+ builder.finishArray() ;
+ responseBody = builder.build();
+ } else {
+ for ( AsyncPool pool : pools ) {
+ // Assumes first is only.
+ AsyncTask aTask = pool.getTask(name) ;
+ if ( aTask != null ) {
+ JsonBuilder builder = new JsonBuilder() ;
+ descOneTask(builder, aTask);
+ responseBody = builder.build() ;
+ }
+ }
+ }
+
+ if ( responseBody == null )
+ ServletOps.errorNotFound("Task '"+name+"' not found") ;
+ ServletOps.setNoCache(action) ;
+ ServletOps.sendJsonReponse(action, responseBody);
+ }
+
+ private void execPost(HttpAction action, String name) {
+
+ }
+
+ private static void descOneTask(JsonBuilder builder, AsyncTask aTask) {
+ builder.startObject("SingleTask") ;
+ builder.key(JsonConst.task).value(aTask.displayName()) ;
+ builder.key(JsonConst.taskId).value(aTask.getTaskId()) ;
+ if ( aTask.getStartPoint() != null )
+ builder.key(JsonConst.started).value(aTask.getStartPoint()) ;
+ if ( aTask.getFinishPoint() != null )
+ builder.key(JsonConst.finished).value(aTask.getFinishPoint()) ;
+ builder.finishObject("SingleTask") ;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/Async.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/Async.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/Async.java
new file mode 100644
index 0000000..1cbda48
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/Async.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.mgt;
+
+import org.apache.http.HttpHeaders ;
+import org.apache.jena.atlas.json.JsonBuilder ;
+import org.apache.jena.atlas.json.JsonValue ;
+import org.apache.jena.fuseki.async.AsyncPool ;
+import org.apache.jena.fuseki.async.AsyncTask ;
+import org.apache.jena.fuseki.server.DataService ;
+import org.apache.jena.fuseki.servlets.HttpAction ;
+
+public class Async
+{
+ public static AsyncTask asyncTask(AsyncPool asyncPool, String displayName, DataService dataService, Runnable task) {
+ AsyncTask asyncTask = asyncPool.submit(task, displayName, dataService) ;
+ return asyncTask ;
+ }
+
+ public static JsonValue asJson(AsyncTask asyncTask) {
+ JsonBuilder builder = new JsonBuilder() ;
+ builder.startObject("outer") ;
+ builder.key(JsonConst.taskId).value(asyncTask.getTaskId()) ;
+ builder.finishObject("outer") ;
+ return builder.build() ;
+ }
+
+ public static void setLocationHeader(HttpAction action, AsyncTask asyncTask) {
+ String x = action.getRequest().getRequestURI() ;
+ if ( ! x.endsWith("/") )
+ x += "/" ;
+ x += asyncTask.getTaskId() ;
+ //String x = "/$/tasks/"+asyncTask.getTaskId() ;
+ action.getResponse().setHeader(HttpHeaders.LOCATION, x) ;
+ }
+
+ public static AsyncTask execASyncTask(HttpAction action, AsyncPool asyncPool, String displayName, Runnable runnable) {
+ AsyncTask atask = Async.asyncTask(asyncPool, "backup", action.getDataService(), runnable) ;
+ Async.setLocationHeader(action, atask);
+ return atask ;
+ }
+
+ // Combined does not work very well - e.g sleep does not set Location.
+// public static AsyncTask execASyncTask(HttpAction action, AsyncPool asyncPool, String displayName, Runnable task) {
+// AsyncTask atask = Async.asyncTask(asyncPool, displayName, action.getDataService(), task) ;
+// Async.setLocationHeader(action, atask);
+// JsonValue v = Async.asJson(atask) ;
+// ServletOps.sendJsonReponse(action, v);
+// return atask ;
+// }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/Backup.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/Backup.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/Backup.java
new file mode 100644
index 0000000..1b1d823
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/Backup.java
@@ -0,0 +1,102 @@
+/**
+ * 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.io.* ;
+import java.util.HashSet ;
+import java.util.Set ;
+import java.util.zip.GZIPOutputStream ;
+
+import org.apache.jena.atlas.io.IO ;
+import org.apache.jena.atlas.lib.FileOps ;
+import org.apache.jena.atlas.logging.Log ;
+import org.apache.jena.fuseki.Fuseki ;
+import org.apache.jena.fuseki.FusekiException ;
+import org.apache.jena.riot.Lang ;
+import org.apache.jena.riot.RDFDataMgr ;
+
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.util.Utils ;
+
+/** Perform a backup */
+public class Backup
+{
+ public static final String BackupArea = "backups" ;
+
+ public static String chooseFileName(String dsName) {
+ FileOps.ensureDir(BackupArea) ;
+ final String ds = dsName.startsWith("/") ? dsName : "/" + dsName ;
+
+ String timestamp = Utils.nowAsString("yyyy-MM-dd_HH-mm-ss") ;
+ final String filename = BackupArea + ds + "_" + timestamp ;
+ return filename ;
+ }
+
+ // Rcord of all backups so we don't attempt to backup the
+ // same dataset multiple times at the same time.
+ private static Set<DatasetGraph> activeBackups = new HashSet<>() ;
+
+ public static void backup(DatasetGraph dsg, String backupfile) {
+ if ( !backupfile.endsWith(".nq") )
+ backupfile = backupfile + ".nq" ;
+
+ // Per backup source lock.
+ synchronized(activeBackups) {
+ // Atomically check-and-set
+ if ( activeBackups.contains(backupfile) )
+ Log.warn(Fuseki.serverLog, "Backup already in progress") ;
+ activeBackups.add(dsg) ;
+ }
+
+ OutputStream out = null ;
+ try {
+
+ if ( true ) {
+ // This seems to achive about the same as "gzip -6"
+ // It's not too expensive in elapsed time but it's not
+ // zero cost. GZip, large buffer.
+ out = new FileOutputStream(backupfile + ".gz") ;
+ out = new GZIPOutputStream(out, 8 * 1024) ;
+ out = new BufferedOutputStream(out) ;
+ } else {
+ out = new FileOutputStream(backupfile) ;
+ out = new BufferedOutputStream(out) ;
+ }
+
+ RDFDataMgr.write(out, dsg, Lang.NQUADS) ;
+ out.close() ;
+ out = null ;
+ } catch (FileNotFoundException e) {
+ Log.warn(Fuseki.serverLog, "File not found: " + backupfile) ;
+ throw new FusekiException("File not found: " + backupfile) ;
+ } catch (IOException e) {
+ IO.exception(e) ;
+ } finally {
+ try {
+ if ( out != null )
+ out.close() ;
+ } catch (IOException e) { /* ignore */}
+ // Remove lock.
+ synchronized(activeBackups) {
+ activeBackups.remove(dsg) ;
+ }
+ }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/DumpServlet.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/DumpServlet.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/DumpServlet.java
new file mode 100644
index 0000000..0b2a070
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/DumpServlet.java
@@ -0,0 +1,312 @@
+/*
+ * 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.
+ */
+
+/** A servlet that dumps its request
+ */
+
+// Could be neater - much, much neater!
+package org.apache.jena.fuseki.mgt;
+
+import java.io.BufferedReader ;
+import java.io.IOException ;
+import java.io.PrintWriter ;
+import java.io.StringWriter ;
+import java.util.Date ;
+import java.util.Enumeration ;
+import java.util.Locale ;
+import java.util.Properties ;
+
+import javax.servlet.ServletContext ;
+import javax.servlet.http.Cookie ;
+import javax.servlet.http.HttpServlet ;
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.atlas.io.IO ;
+
+public class DumpServlet extends HttpServlet
+{
+ private static final long serialVersionUID = 99L; // Serilizable.
+
+
+ public DumpServlet()
+ {
+
+ }
+
+ @Override
+ public void init()
+ {
+ return ;
+ }
+
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp)
+ {
+ try {
+ PrintWriter out = resp.getWriter() ;
+ resp.setContentType("text/html");
+
+ String now = new Date().toString() ;
+
+ // HEAD
+ out.println("<html>") ;
+ out.println("<head>") ;
+ out.println("<Title>Dump @ "+now+"</Title>") ;
+ // Reduce the desire to cache it.
+ out.println("<meta CONTENT=now HTTP-EQUIV=expires>") ;
+ out.println("</head>") ;
+
+ // BODY
+ out.println("<body>") ;
+ out.println("<pre>") ;
+
+ out.println("Dump : "+now);
+ out.println() ;
+ out.println("==== Request");
+ out.println() ;
+ out.print(dumpRequest(req)) ;
+ out.println() ;
+
+ out.println(">>>> Body");
+ out.println() ;
+ printBody(out, req) ;
+ out.println("<<<< Body");
+
+ out.println("==== ServletContext");
+ out.println() ;
+ out.print(dumpServletContext());
+ out.println() ;
+
+ out.println("==== Environment");
+ out.println() ;
+ out.print(dumpEnvironment());
+ out.println() ;
+
+ out.println("</pre>") ;
+
+ out.println("</body>") ;
+ out.println("</html>") ;
+ out.flush() ;
+ } catch (IOException e)
+ { }
+ }
+
+ // This resets the input stream
+
+ static public String dumpRequest(HttpServletRequest req)
+ {
+ try ( StringWriter sw = new StringWriter() ;
+ PrintWriter pw = new PrintWriter(sw) ) {
+ // Standard environment
+ pw.println("Method: "+req.getMethod());
+ pw.println("getContentLength: "+Integer.toString(req.getContentLength()));
+ pw.println("getContentType: "+req.getContentType());
+ pw.println("getRequestURI: "+req.getRequestURI());
+ pw.println("getRequestURL: "+req.getRequestURL());
+ pw.println("getContextPath: "+req.getContextPath());
+ pw.println("getServletPath: "+req.getServletPath());
+ pw.println("getPathInfo: "+req.getPathInfo());
+ pw.println("getPathTranslated: "+req.getPathTranslated());
+ pw.println("getQueryString: "+req.getQueryString());
+ pw.println("getProtocol: "+req.getProtocol());
+ pw.println("getScheme: "+req.getScheme());
+ pw.println("getServerName: "+req.getServerName());
+ pw.println("getServerPort: "+req.getServerPort());
+ pw.println("getRemoteUser: "+req.getRemoteUser());
+ pw.println("getRemoteAddr: "+req.getRemoteAddr());
+ pw.println("getRemoteHost: "+req.getRemoteHost());
+ pw.println("getRequestedSessionId: "+req.getRequestedSessionId());
+ {
+ Cookie c[] = req.getCookies() ;
+ if ( c == null )
+ pw.println("getCookies: <none>");
+ else
+ {
+ for ( int i = 0 ; i < c.length ; i++ )
+ {
+ pw.println("Cookie: "+c[i].getName());
+ pw.println(" value: "+c[i].getValue());
+ pw.println(" version: "+c[i].getVersion());
+ pw.println(" comment: "+c[i].getComment());
+ pw.println(" domain: "+c[i].getDomain());
+ pw.println(" maxAge: "+c[i].getMaxAge());
+ pw.println(" path: "+c[i].getPath());
+ pw.println(" secure: "+c[i].getSecure());
+ pw.println();
+ }
+ }
+ }
+
+ {
+ // To do: create a string for the output so can send to console and return it.
+ Enumeration<String> en = req.getHeaderNames() ;
+
+ for ( ; en.hasMoreElements() ; )
+ {
+ String name = en.nextElement() ;
+ String value = req.getHeader(name) ;
+ pw.println("Head: "+name + " = " + value) ;
+ }
+ }
+
+ Enumeration<String> en2 = req.getAttributeNames() ;
+ if ( en2.hasMoreElements() )
+ pw.println();
+ for ( ; en2.hasMoreElements() ; )
+ {
+ String name = en2.nextElement() ;
+ String value = req.getAttribute(name).toString() ;
+ pw.println("Attr: "+name + " = " + value) ;
+ }
+
+ // Note that doing this on a form causes the forms content (body) to be read
+ // and parsed as form variables.
+// en = req.getParameterNames() ;
+// if ( en.hasMoreElements() )
+// pw.println();
+// for ( ; en.hasMoreElements() ; )
+// {
+// String name = (String)en.nextElement() ;
+// String value = req.getParameter(name) ;
+// pw.println("Param: "+name + " = " + value) ;
+// }
+
+
+
+// MultiMap<String, String> map = WebLib.parseQueryString(req) ;
+// for ( String name : map.keys() )
+// for ( String value : map.get(name) )
+// pw.println("Param: "+name + " = " + value) ;
+
+ Enumeration<Locale> en = req.getLocales() ;
+ if ( en.hasMoreElements() )
+ pw.println();
+ for ( ; en.hasMoreElements() ; )
+ {
+ String name = en.nextElement().toString() ;
+ pw.println("Locale: "+name) ;
+ }
+
+ pw.println() ;
+ //printBody(pw, req) ;
+
+ return sw.toString() ;
+ } catch (IOException e) { return null ; }
+ }
+
+ static void printBody(PrintWriter pw, HttpServletRequest req) throws IOException
+ {
+ BufferedReader in = req.getReader() ;
+ if ( req.getContentLength() > 0 )
+ // Need +2 because last line may not have a CR/LF on it.
+ in.mark(req.getContentLength()+2) ;
+ else
+ // This is a dump - try to do something that works, even if inefficient.
+ in.mark(100*1024) ;
+
+ while(true)
+ {
+ String x = in.readLine() ;
+ if ( x == null )
+ break ;
+ x = x.replaceAll("&", "&") ;
+ x = x.replaceAll("<", "<") ;
+ x = x.replaceAll(">", ">") ;
+ pw.println(x) ;
+ }
+ try { in.reset() ; } catch (IOException e) { System.out.println("DumpServlet: Reset of content failed: "+e) ; }
+ }
+
+ /**
+ * <code>dumpEnvironment</code>
+ * @return String that is the HTML of the System properties as name/value pairs.
+ * The values are with single quotes independent of whether or not the value has
+ * single quotes in it.
+ */
+ static public String dumpEnvironment()
+ {
+ Properties properties = System.getProperties();
+ try ( StringWriter sw = new StringWriter() ;
+ PrintWriter pw = new PrintWriter(sw) ; ) {
+ Enumeration<Object> en = properties.keys();
+ while(en.hasMoreElements())
+ {
+ String key = en.nextElement().toString();
+ pw.println(key+": '"+properties.getProperty(key)+"'");
+ }
+
+ pw.println() ;
+ return sw.toString() ;
+ } catch (IOException e) { IO.exception(e); return null ; }
+ }
+
+ public String dumpServletContext()
+ {
+ try ( StringWriter sw = new StringWriter() ;
+ PrintWriter pw = new PrintWriter(sw) ; ) {
+ ServletContext sc = getServletContext();
+ pw.println("majorVersion: '"+sc.getMajorVersion()+"'");
+ pw.println("minorVersion: '"+sc.getMinorVersion()+"'");
+ pw.println("contextName: '"+sc.getServletContextName()+"'");
+ pw.println("servletInfo: '"+getServletInfo()+"'");
+ pw.println("serverInfo: '"+sc.getServerInfo()+"'");
+
+ {
+ Enumeration<String> en = sc.getInitParameterNames();
+ if (en != null) {
+ pw.println("initParameters: ");
+ while(en.hasMoreElements())
+ {
+ String key = en.nextElement();
+ pw.println(key+": '"+sc.getInitParameter(key)+"'");
+ }
+ }
+ }
+
+ {
+ Enumeration<String> en = sc.getAttributeNames();
+ if (en != null) {
+ pw.println("attributes: ");
+ while(en.hasMoreElements())
+ {
+ String key = en.nextElement();
+ pw.println(key+": '"+sc.getAttribute(key)+"'");
+ }
+ }
+ }
+ pw.println() ;
+
+ return sw.toString() ;
+ } catch (IOException e) { IO.exception(e); return null ; }
+ }
+
+
+ @Override
+ public void doPost(HttpServletRequest req, HttpServletResponse resp)
+ {
+ doGet(req, resp) ;
+ }
+
+
+ @Override
+ public String getServletInfo()
+ {
+ return "Dump";
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/470ee4d7/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/JsonConst.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/JsonConst.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/JsonConst.java
new file mode 100644
index 0000000..e943ac1
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/mgt/JsonConst.java
@@ -0,0 +1,52 @@
+/**
+ * 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 JsonConst
+{
+ public static final String taskId = "taskId" ;
+ public static final String task = "task" ;
+ public static final String datasets = "datasets" ;
+
+ public static final String finished = "finished" ;
+ public static final String started = "started" ;
+
+ public static final String uptime = "uptime" ;
+ public static final String startDT = "startDateTime" ;
+ public static final String server = "server" ;
+ public static final String port = "port" ;
+ public static final String hostname = "hostname" ;
+ public static final String admin = "admin" ;
+ public static final String version = "version" ;
+ public static final String built = "built" ;
+
+ public static final String services = "services" ;
+ public static final String operation = "operation" ;
+ public static final String description = "description" ;
+ public static final String endpoints = "endpoints" ;
+
+ public static final String dsName = "ds.name" ;
+ public static final String dsState = "ds.state" ;
+ public static final String dsService = "ds.services" ;
+
+ public static final String srvType = "srv.type" ;
+ public static final String srvDescription = "srv.description" ;
+ public static final String srvEndpoints = "srv.endpoints" ;
+
+}