-
Notifications
You must be signed in to change notification settings - Fork 4
GSIP 76 Extend REST API to configure settings and OWS services
Provide the capability to configure global and workspace specific settings and OWS services.
Juan Marin
2.2 if possible
Choose one of: Under Discussion, In Progress, Completed, Rejected, Deferred
Currently the REST API only exposes Catalog related functionality and configuration, such as workspaces, layers, layer groups, styles, etc. This enhancement would allow it to also include REST endpoints to configure general purpose settings (i.e. contact info) and OWS services (WMS, WFS, WCS), both at the global and workspace specific level (virtual services)
This proposal intends to extend the REST API to cover other configuration aspects of GeoServer, besides the Catalog related objects. The only modification needed in existent objects is adding a reference to the GeoServer interface in CatalogResourceBase, so that subclasses have access to other parts of GeoServer configuration besides the Catalog. Complete patch with unit tests and documentation has been submitted as a JIRA ticket at https://jira.codehaus.org/browse/GEOS-5122
public abstract class CatalogResourceBase extends ReflectiveResource {
protected GeoServer geoServer;
...
public CatalogResourceBase(Context context,Request request, Response response,
Class clazz, Catalog catalog) {
super( context, request, response );
this.clazz = clazz;
this.catalog = catalog;
this.xpf = GeoServerExtensions.bean(XStreamPersisterFactory.class);
this.geoServer = GeoServerExtensions.bean(GeoServer.class);
}
....
}
All the new endpoints have been implemented following the same conventions and structure present in the Catalog REST API, by creating an AbstractGeoServerFinder that is extended by each implementation to provide the Restlet Finder, and its corresponding Resource to describe the REST endpoint.
public class AbstractGeoServerFinder extends AbstractCatalogFinder {
protected GeoServer geoServer;
protected AbstractGeoServerFinder(GeoServer geoServer) {
super(geoServer.getCatalog());
this.geoServer = geoServer;
}
}
The proposal includes implementation of REST endpoints for the following (example URL endpoints assume locally deployed GeoServer running on port 8080):
1. Global settings
The endpoint is at http://localhost:8080/geoserver/rest/settings
It allows GET and PUT operations, and supports HTML (default), XML and JSON
Classes created: GlobalSettingsFinder, GlobalSettingsResource (package org.geoserver.rest, please see patch for details)
2. Global contact
This endpoint can be accessed at http://localhost:8080/geoserver/rest/settings/contact
It allows GET and PUT operations, and supports HTML (default), XML and JSON
Classes created: GlobalContactFinder, GlobalContactResource (package org.geoserver.rest, please see patch for details) *3. Workspace specific settings (GET, POST, PUT, DELETE)*
This endpoint can be accessed at http://localhost:8080/geoserver/rest/workspaces/LocalWorkspace/settings
It allows GET, POST, PUT and DELETE operations, and supports HTML (default), XML and JSON
Classes created: LocalSettingsFinder, LocalSettingsResource (package org.geoserver.rest, please see patch for details)
4. OWS Services configuration
Both global and local settings for OWS services have been implemented by providing a parent class that deals with ServiceInfo objects. Subclasses provide specifics for each OWS service by using the appropriate instance (WMSInfo, WFSInfo, WCSInfo)
The service settings parent class is as follows:
public class ServiceSettingsResource extends AbstractCatalogResource {
protected GeoServer geoServer;
private Class clazz;
public ServiceSettingsResource(Context context, Request request, Response response,
Class clazz, GeoServer geoServer) {
super(context, request, response, clazz, geoServer.getCatalog());
this.clazz = clazz;
this.geoServer = geoServer;
}
@Override
public boolean allowPost() {
return allowNew();
}
@Override
public boolean allowPut() {
return allowExisting();
}
@Override
public boolean allowDelete() {
String workspace = getAttribute("workspace");
if (workspace != null) {
WorkspaceInfo ws = geoServer.getCatalog().getWorkspaceByName(workspace);
return geoServer.getService(ws, clazz) != null;
}
return false;
}
private boolean allowNew() {
String workspace = getAttribute("workspace");
WorkspaceInfo ws = geoServer.getCatalog().getWorkspaceByName(workspace);
assert (ws != null);
return geoServer.getService(ws, clazz) == null;
}
private boolean allowExisting() {
String workspace = getAttribute("workspace");
if (workspace != null) {
WorkspaceInfo ws = geoServer.getCatalog().getWorkspaceByName(workspace);
return geoServer.getService(ws, clazz) != null;
}
return geoServer.getService(clazz) != null;
}
@Override
protected Object handleObjectGet() throws Exception {
String workspace = getAttribute("workspace");
if (workspace != null) {
WorkspaceInfo ws = geoServer.getCatalog().getWorkspaceByName(workspace);
if (geoServer.getService(ws, clazz) == null) {
throw new RestletException("Service for workspace " + workspace + " does not exist",
Status.CLIENT_ERROR_NOT_FOUND);
}
return geoServer.getService(ws, clazz);
}
if (geoServer.getService(clazz) == null) {
throw new RestletException("Service for workspace " + workspace + " does not exist",
Status.CLIENT_ERROR_NOT_FOUND);
}
return (ServiceInfo) geoServer.getService(clazz);
}
@Override
protected String handleObjectPost(Object object) throws Exception {
String name = "";
ServiceInfo serviceInfo = handlePost(object);
name = serviceInfo.getName();
if (name == null) {
throw new RestletException("Service name cannot be null",
Status.CLIENT_ERROR_BAD_REQUEST);
}
geoServer.add(serviceInfo);
return name;
}
protected ServiceInfo handlePost(Object object) {
String workspace = getAttribute("workspace");
if (workspace != null) {
WorkspaceInfo ws = geoServer.getCatalog().getWorkspaceByName(workspace);
if (ws == null) {
throw new RestletException("Workspace does not exist",
Status.CLIENT_ERROR_BAD_REQUEST);
}
if (geoServer.getService(ws, clazz) != null) {
throw new RestletException(
"Service information already exists, creation of a new object is not allowed",
Status.CLIENT_ERROR_FORBIDDEN);
}
ServiceInfo serviceInfo = (ServiceInfo) object;
serviceInfo.setWorkspace(ws);
return serviceInfo;
}
return null;
}
@Override
protected void handleObjectPut(Object object) throws Exception {
String workspace = getAttribute("workspace");
ServiceInfo original = null;
if (workspace != null) {
WorkspaceInfo ws = geoServer.getCatalog().getWorkspaceByName(workspace);
original = geoServer.getService(ws, clazz);
OwsUtils.copy(object, original, clazz);
original.setWorkspace(ws);
} else {
original = geoServer.getService(clazz);
}
OwsUtils.copy(object, original, clazz);
geoServer.save(original);
}
@Override
protected void handleObjectDelete() throws Exception {
String workspace = getAttribute("workspace");
if (workspace != null) {
WorkspaceInfo ws = geoServer.getCatalog().getWorkspaceByName(workspace);
ServiceInfo serviceInfo = geoServer.getService(ws, clazz);
if (serviceInfo != null) {
geoServer.remove(serviceInfo);
}
}
}
}
Classes created: ServiceSettingsResource, WCSSettingsFinder, WCSSettingsResource,WFSSettingsFinder, WFSSettingsResource, WMSSettingsFinder, WMSSettingsResource (package org.geoserver.service.rest, please see patch for details)
4.1 Global OWS Service settings
These endpoints can be accessed at the following URLs:
http://localhost:8080/geoserver/rest/services/wcs/settings http://localhost:8080/geoserver/rest/services/wfs/settings http://localhost:8080/geoserver/rest/services/wms/settings
They allow GET and PUT operations, and support HTML (default), XML and JSON
4.2 Workspace specific OWS Service settings
These endpoints can be accessed at the following URLs:
http://localhost:8080/geoserver/rest/services/wcs//settings http://localhost:8080/geoserver/rest/services/wfs//settings http://localhost:8080/geoserver/rest/services/wms//settings
They allow GET, POST, PUT and DELETE operations, and support HTML (default), XML and JSON
This section should contain feedback provided by PSC members who may have a problem with the proposal.
No backwards compatibility issues.
Andrea Aime: Alessio Fabiani: Ben Caradoc Davies: Gabriel Roldan: Justin Deoliveira: Jody Garnett: Mark Leslie: Rob Atkinson: Simone Giannecchini:
JIRA Task Email Discussion Wiki Page