Skip to content

Commit

Permalink
Fixup FeatureTypeController behavior to pass gsconfig tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tbarsballe committed Apr 5, 2017
1 parent 1c889a6 commit 5fef79c
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 174 deletions.
Expand Up @@ -15,15 +15,7 @@
import java.util.logging.Logger; import java.util.logging.Logger;


import freemarker.template.ObjectWrapper; import freemarker.template.ObjectWrapper;
import org.geoserver.catalog.AttributeTypeInfo; import org.geoserver.catalog.*;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CatalogBuilder;
import org.geoserver.catalog.CatalogInfo;
import org.geoserver.catalog.DataStoreInfo;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.MetadataMap;
import org.geoserver.catalog.NamespaceInfo;
import org.geoserver.config.util.XStreamPersister; import org.geoserver.config.util.XStreamPersister;
import org.geoserver.rest.ObjectToMapWrapper; import org.geoserver.rest.ObjectToMapWrapper;
import org.geoserver.rest.ResourceNotFoundException; import org.geoserver.rest.ResourceNotFoundException;
Expand Down Expand Up @@ -92,13 +84,8 @@ public Object getFeatureTypes(
@PathVariable(name = "datastoreName", required = false) String datastoreName, @PathVariable(name = "datastoreName", required = false) String datastoreName,
@RequestParam(name = "list", required = true, defaultValue = "configured") String list) { @RequestParam(name = "list", required = true, defaultValue = "configured") String list) {


ensureResourcesExist(workspaceName, datastoreName);

if ("available".equalsIgnoreCase(list) || "available_with_geom".equalsIgnoreCase(list)) { if ("available".equalsIgnoreCase(list) || "available_with_geom".equalsIgnoreCase(list)) {
DataStoreInfo info = catalog.getDataStoreByName(workspaceName, datastoreName); DataStoreInfo info = getExistingDataStore(workspaceName, datastoreName);
if (info == null) {
throw new ResourceNotFoundException("No such datastore: " + datastoreName);
}


// flag to control whether to filter out types without geometry // flag to control whether to filter out types without geometry
boolean skipNoGeom = "available_with_geom".equalsIgnoreCase(list); boolean skipNoGeom = "available_with_geom".equalsIgnoreCase(list);
Expand Down Expand Up @@ -157,117 +144,115 @@ public Object getFeatureTypes(
CatalogController.TEXT_JSON, MediaType.APPLICATION_JSON_VALUE, CatalogController.TEXT_JSON, MediaType.APPLICATION_JSON_VALUE,
MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_XML_VALUE }) MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_XML_VALUE })
public ResponseEntity postFeatureType( public ResponseEntity postFeatureType(
@PathVariable(name = "workspaceName", required = true) String workspace, @PathVariable(name = "workspaceName", required = true) String workspaceName,
@PathVariable(name = "datastoreName", required = false) String dataStore, @PathVariable(name = "datastoreName", required = false) String dataStoreName,
@RequestBody FeatureTypeInfo featureType, UriComponentsBuilder builder) @RequestBody FeatureTypeInfo ftInfo, UriComponentsBuilder builder)
throws Exception { throws Exception {


ensureResourcesExist(workspace, dataStore); DataStoreInfo dsInfo = getExistingDataStore(workspaceName, dataStoreName);

// ensure the store matches up // ensure the store matches up
if (featureType.getStore() != null) { if (ftInfo.getStore() != null) {
if (!dataStore.equals(featureType.getStore().getName())) { if (!dataStoreName.equals(ftInfo.getStore().getName())) {
throw new RestException("Expected datastore " + dataStore + " but client specified " throw new RestException("Expected datastore " + dataStoreName + " but client specified "
+ featureType.getStore().getName(), HttpStatus.FORBIDDEN); + ftInfo.getStore().getName(), HttpStatus.FORBIDDEN);
} }
} else { } else {
featureType.setStore(catalog.getDataStoreByName(workspace, dataStore)); ftInfo.setStore(dsInfo);
} }


// ensure workspace/namespace matches up // ensure workspace/namespace matches up
if (featureType.getNamespace() != null) { if (ftInfo.getNamespace() != null) {
if (!workspace.equals(featureType.getNamespace().getPrefix())) { if (!workspaceName.equals(ftInfo.getNamespace().getPrefix())) {
throw new RestException("Expected workspace " + workspace + " but client specified " throw new RestException("Expected workspace " + workspaceName + " but client specified "
+ featureType.getNamespace().getPrefix(), HttpStatus.FORBIDDEN); + ftInfo.getNamespace().getPrefix(), HttpStatus.FORBIDDEN);
} }
} else { } else {
featureType.setNamespace(catalog.getNamespaceByPrefix(workspace)); ftInfo.setNamespace(catalog.getNamespaceByPrefix(workspaceName));
} }
featureType.setEnabled(true); ftInfo.setEnabled(true);


// now, does the feature type exist? If not, create it // now, does the feature type exist? If not, create it
DataStoreInfo ds = catalog.getDataStoreByName(workspace, dataStore); DataAccess dataAccess = dsInfo.getDataStore(null);
DataAccess gtda = ds.getDataStore(null); if (dataAccess instanceof DataStore) {
if (gtda instanceof DataStore) { String typeName = ftInfo.getName();
String typeName = featureType.getName(); if (ftInfo.getNativeName() != null) {
if (featureType.getNativeName() != null) { typeName = ftInfo.getNativeName();
typeName = featureType.getNativeName();
} }
boolean typeExists = false; boolean typeExists = false;
DataStore gtds = (DataStore) gtda; DataStore dataStore = (DataStore) dataAccess;
for (String name : gtds.getTypeNames()) { for (String name : dataStore.getTypeNames()) {
if (name.equals(typeName)) { if (name.equals(typeName)) {
typeExists = true; typeExists = true;
break; break;
} }
} }


// check to see if this is a virtual JDBC feature type // check to see if this is a virtual JDBC feature type
MetadataMap mdm = featureType.getMetadata(); MetadataMap mdm = ftInfo.getMetadata();
boolean virtual = mdm != null && mdm.containsKey(FeatureTypeInfo.JDBC_VIRTUAL_TABLE); boolean virtual = mdm != null && mdm.containsKey(FeatureTypeInfo.JDBC_VIRTUAL_TABLE);


if (!virtual && !typeExists) { if (!virtual && !typeExists) {
gtds.createSchema(buildFeatureType(featureType)); dataStore.createSchema(buildFeatureType(ftInfo));
// the attributes created might not match up 1-1 with the actual spec due to // the attributes created might not match up 1-1 with the actual spec due to
// limitations of the data store, have it re-compute them // limitations of the data store, have it re-compute them
featureType.getAttributes().clear(); ftInfo.getAttributes().clear();
List<String> typeNames = Arrays.asList(gtds.getTypeNames()); List<String> typeNames = Arrays.asList(dataStore.getTypeNames());
// handle Oracle oddities // handle Oracle oddities
// TODO: use the incoming store capabilites API to better handle the name transformation // TODO: use the incoming store capabilites API to better handle the name transformation
if (!typeNames.contains(typeName) && typeNames.contains(typeName.toUpperCase())) { if (!typeNames.contains(typeName) && typeNames.contains(typeName.toUpperCase())) {
featureType.setNativeName(featureType.getName().toLowerCase()); ftInfo.setNativeName(ftInfo.getName().toLowerCase());
} }
} }
} }


CatalogBuilder cb = new CatalogBuilder(catalog); CatalogBuilder cb = new CatalogBuilder(catalog);
cb.initFeatureType(featureType); cb.initFeatureType(ftInfo);


// attempt to fill in metadata from underlying feature source // attempt to fill in metadata from underlying feature source
try { try {
FeatureSource featureSource = gtda FeatureSource featureSource = dataAccess
.getFeatureSource(new NameImpl(featureType.getNativeName())); .getFeatureSource(new NameImpl(ftInfo.getNativeName()));
if (featureSource != null) { if (featureSource != null) {
cb.setupMetadata(featureType, featureSource); cb.setupMetadata(ftInfo, featureSource);
} }
} catch (Exception e) { } catch (Exception e) {
LOGGER.log(Level.WARNING, "Unable to fill in metadata from underlying feature source", LOGGER.log(Level.WARNING, "Unable to fill in metadata from underlying feature source",
e); e);
} }


if (featureType.getStore() == null) { if (ftInfo.getStore() == null) {
// get from requests // get from requests
featureType.setStore(ds); ftInfo.setStore(dsInfo);
} }


NamespaceInfo ns = featureType.getNamespace(); NamespaceInfo ns = ftInfo.getNamespace();
if (ns != null && !ns.getPrefix().equals(workspace)) { if (ns != null && !ns.getPrefix().equals(workspaceName)) {
// TODO: change this once the two can be different and we untie namespace // TODO: change this once the two can be different and we untie namespace
// from workspace // from workspace
LOGGER.warning("Namespace: " + ns.getPrefix() + " does not match workspace: " LOGGER.warning("Namespace: " + ns.getPrefix() + " does not match workspace: "
+ workspace + ", overriding."); + workspaceName + ", overriding.");
ns = null; ns = null;
} }


if (ns == null) { if (ns == null) {
// infer from workspace // infer from workspace
ns = catalog.getNamespaceByPrefix(workspace); ns = catalog.getNamespaceByPrefix(workspaceName);
featureType.setNamespace(ns); ftInfo.setNamespace(ns);
} }


featureType.setEnabled(true); ftInfo.setEnabled(true);
catalog.validate(featureType, true).throwIfInvalid(); catalog.validate(ftInfo, true).throwIfInvalid();
catalog.add(featureType); catalog.add(ftInfo);


// create a layer for the feature type // create a layer for the feature type
catalog.add(new CatalogBuilder(catalog).buildLayer(featureType)); catalog.add(new CatalogBuilder(catalog).buildLayer(ftInfo));


LOGGER.info("POST feature type" + dataStore + "," + featureType.getName()); LOGGER.info("POST feature type" + dataStoreName + "," + ftInfo.getName());


HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setLocation( headers.setLocation(
builder.path("/workspaces/{workspaceName}/datastores/{datastoreName}/featuretypes/" builder.path("/workspaces/{workspaceName}/datastores/{datastoreName}/featuretypes/"
+ featureType.getName()).buildAndExpand(workspace, dataStore).toUri()); + ftInfo.getName()).buildAndExpand(workspaceName, dataStoreName).toUri());
return new ResponseEntity<String>("", headers, HttpStatus.CREATED); return new ResponseEntity<String>("", headers, HttpStatus.CREATED);
} }


Expand All @@ -281,51 +266,11 @@ public RestWrapper getFeatureType(
@PathVariable(name = "featureTypeName", required = true) String featureTypeName, @PathVariable(name = "featureTypeName", required = true) String featureTypeName,
@RequestParam(name = "quietOnNotFound", required = false, defaultValue = "false") Boolean quietOnNotFound) { @RequestParam(name = "quietOnNotFound", required = false, defaultValue = "false") Boolean quietOnNotFound) {


ensureResourcesExist(workspaceName, datastoreName); DataStoreInfo dsInfo = getExistingDataStore(workspaceName, datastoreName);

FeatureTypeInfo ftInfo = catalog.getFeatureTypeByDataStore(dsInfo, featureTypeName);
if (datastoreName != null && catalog.getFeatureTypeByDataStore( checkFeatureTypeExists(ftInfo, workspaceName, datastoreName, featureTypeName);
catalog.getDataStoreByName(workspaceName, datastoreName),
featureTypeName) == null) {
throw new ResourceNotFoundException("No such feature type: " + workspaceName + ","
+ datastoreName + "," + featureTypeName);
} else {
// look up by workspace/namespace
NamespaceInfo ns = catalog.getNamespaceByPrefix(workspaceName);

if (ns == null || catalog.getFeatureTypeByName(ns, featureTypeName) == null) {
throw new ResourceNotFoundException(
"No such feature type: " + workspaceName + "," + featureTypeName);
}
}


FeatureTypeInfo ftInfo; return wrapObject(ftInfo, FeatureTypeInfo.class, "No such feature type: "+featureTypeName, quietOnNotFound);

if (datastoreName == null) {
LOGGER.fine("GET feature type" + workspaceName + "," + featureTypeName);

// grab the corresponding namespace for this workspace
NamespaceInfo ns = catalog.getNamespaceByPrefix(workspaceName);
if (ns != null) {
ftInfo = catalog.getFeatureTypeByName(ns, featureTypeName);
} else {
return wrapObject(null, FeatureTypeInfo.class,
"No namespace found for prefix: " + workspaceName, quietOnNotFound);
}
} else { // datastore != null
LOGGER.fine("GET feature type" + datastoreName + "," + featureTypeName);
DataStoreInfo dsInfo = catalog.getDataStoreByName(workspaceName, datastoreName);
ftInfo = catalog.getFeatureTypeByDataStore(dsInfo, featureTypeName);
}

String msgIfNotFound;
if (datastoreName != null) {
msgIfNotFound = "No such feature type: " + workspaceName + "," + datastoreName + ","
+ featureTypeName;
} else {
msgIfNotFound = "No such feature type: " + workspaceName + "," + featureTypeName;
}

return wrapObject(ftInfo, FeatureTypeInfo.class, msgIfNotFound, quietOnNotFound);
} }


@PutMapping(path = { "/workspaces/{workspaceName}/featuretypes/{featureTypeName}", @PutMapping(path = { "/workspaces/{workspaceName}/featuretypes/{featureTypeName}",
Expand All @@ -339,38 +284,22 @@ public void putFeatureType(
@RequestBody(required = true) FeatureTypeInfo featureTypeUpdate, @RequestBody(required = true) FeatureTypeInfo featureTypeUpdate,
@RequestParam(name = "recalculate", required = false) String recalculate) { @RequestParam(name = "recalculate", required = false) String recalculate) {


ensureResourcesExist(workspaceName, datastoreName); DataStoreInfo dsInfo = getExistingDataStore(workspaceName, datastoreName);

FeatureTypeInfo ftInfo = catalog.getFeatureTypeByDataStore(dsInfo, featureTypeName);
if (datastoreName != null checkFeatureTypeExists(ftInfo, workspaceName, datastoreName, featureTypeName);
&& catalog.getFeatureTypeByDataStore(catalog.getDataStoreByName(workspaceName), Map<String, Serializable> parametersCheck = ftInfo.getStore()
featureTypeName) == null) {

throw new ResourceNotFoundException("No such feature type: " + workspaceName + ","
+ datastoreName + "," + featureTypeName);
} else {
// look up by workspace/namespace
NamespaceInfo ns = catalog.getNamespaceByPrefix(workspaceName);
if (ns == null || catalog.getFeatureTypeByName(ns, featureTypeName) == null) {
throw new ResourceNotFoundException(
"No such feature type: " + workspaceName + "," + featureTypeName);
}
}

DataStoreInfo ds = catalog.getDataStoreByName(workspaceName, datastoreName);
FeatureTypeInfo featureTypeInfo = catalog.getFeatureTypeByDataStore(ds, featureTypeName);
Map<String, Serializable> parametersCheck = featureTypeInfo.getStore()
.getConnectionParameters(); .getConnectionParameters();


calculateOptionalFields(featureTypeUpdate, featureTypeInfo, recalculate); calculateOptionalFields(featureTypeUpdate, ftInfo, recalculate);
CatalogBuilder helper = new CatalogBuilder(catalog); CatalogBuilder helper = new CatalogBuilder(catalog);
helper.updateFeatureType(featureTypeInfo, featureTypeUpdate); helper.updateFeatureType(ftInfo, featureTypeUpdate);


catalog.validate(featureTypeInfo, false).throwIfInvalid(); catalog.validate(ftInfo, false).throwIfInvalid();
catalog.save(featureTypeInfo); catalog.save(ftInfo);
catalog.getResourcePool().clear(featureTypeInfo); catalog.getResourcePool().clear(ftInfo);


Map<String, Serializable> parameters = featureTypeInfo.getStore().getConnectionParameters(); Map<String, Serializable> parameters = ftInfo.getStore().getConnectionParameters();
MetadataMap mdm = featureTypeInfo.getMetadata(); MetadataMap mdm = ftInfo.getMetadata();
boolean virtual = mdm != null && mdm.containsKey(FeatureTypeInfo.JDBC_VIRTUAL_TABLE); boolean virtual = mdm != null && mdm.containsKey(FeatureTypeInfo.JDBC_VIRTUAL_TABLE);


if (!virtual && parameters.equals(parametersCheck)) { if (!virtual && parameters.equals(parametersCheck)) {
Expand All @@ -379,7 +308,7 @@ public void putFeatureType(
} else { } else {
LOGGER.info("PUT featureType" + datastoreName + "," + featureTypeName LOGGER.info("PUT featureType" + datastoreName + "," + featureTypeName
+ " updated metadata and data access"); + " updated metadata and data access");
catalog.getResourcePool().clear(featureTypeInfo.getStore()); catalog.getResourcePool().clear(ftInfo.getStore());
} }


} }
Expand All @@ -394,27 +323,10 @@ public void deleteFeatureType(
@PathVariable(name = "featureTypeName", required = true) String featureTypeName, @PathVariable(name = "featureTypeName", required = true) String featureTypeName,
@RequestParam(name = "recurse", defaultValue = "false") Boolean recurse) { @RequestParam(name = "recurse", defaultValue = "false") Boolean recurse) {


ensureResourcesExist(workspaceName, datastoreName); DataStoreInfo dsInfo = getExistingDataStore(workspaceName, datastoreName);

FeatureTypeInfo ftInfo = catalog.getFeatureTypeByDataStore(dsInfo, featureTypeName);
if (datastoreName != null checkFeatureTypeExists(ftInfo, workspaceName, datastoreName, featureTypeName);
&& catalog.getFeatureTypeByDataStore(catalog.getDataStoreByName(workspaceName, datastoreName), List<LayerInfo> layers = catalog.getLayers(ftInfo);
featureTypeName) == null) {
throw new RestException("No such feature type: " + workspaceName + "," + datastoreName
+ "," + featureTypeName, HttpStatus.NOT_FOUND);
} else {
// look up by workspace/namespace
NamespaceInfo ns = catalog.getNamespaceByPrefix(workspaceName);
if (ns == null || catalog.getFeatureTypeByName(ns, featureTypeName) == null) {

throw new RestException(
"No such feature type: " + workspaceName + "," + featureTypeName,
HttpStatus.NOT_FOUND);
}
}

DataStoreInfo ds = catalog.getDataStoreByName(workspaceName, datastoreName);
FeatureTypeInfo ft = catalog.getFeatureTypeByDataStore(ds, featureTypeName);
List<LayerInfo> layers = catalog.getLayers(ft);


if (recurse) { if (recurse) {
// by recurse we clear out all the layers that public this resource // by recurse we clear out all the layers that public this resource
Expand All @@ -429,31 +341,33 @@ public void deleteFeatureType(
} }
} }


catalog.remove(ft); catalog.remove(ftInfo);
LOGGER.info("DELETE feature type" + datastoreName + "," + featureTypeName); LOGGER.info("DELETE feature type" + datastoreName + "," + featureTypeName);
} }


/** /**
* Check if the provided workspace and datastore exist. <br/> * If the feature type doesn't exists throws a REST exception with HTTP 404 code.
* <br/>
* If the parameter is null, no check is performed. <br/>
* <br/>
* If the workspaceName / datastoreName parameter is provided but the corresponding resource does not exist, throws a 404 exception.
*
* @param workspaceName
* @param datastoreName
*/ */
public void ensureResourcesExist(String workspaceName, String datastoreName) { private void checkFeatureTypeExists(FeatureTypeInfo featureType, String workspaceName, String dataStoreName, String featureTypeName) {
// ensure referenced resources exist if (featureType == null && dataStoreName == null) {
if (workspaceName != null && catalog.getWorkspaceByName(workspaceName) == null) { throw new ResourceNotFoundException(String.format(
throw new ResourceNotFoundException("No such workspace: " + workspaceName); "No such feature type: %s,%s", workspaceName, featureTypeName));
} else if (featureType == null) {
throw new ResourceNotFoundException(String.format(
"No such feature type: %s,%s,%s", workspaceName, dataStoreName, featureTypeName));
} }
}


if (datastoreName != null /**
&& catalog.getDataStoreByName(workspaceName, datastoreName) == null) { * Helper method that find a store based on the workspace name and store name.
*/
private DataStoreInfo getExistingDataStore(String workspaceName, String storeName) {
DataStoreInfo original = catalog.getDataStoreByName(workspaceName, storeName);
if (original == null) {
throw new ResourceNotFoundException( throw new ResourceNotFoundException(
"No such datastore: " + workspaceName + "," + datastoreName); "No such data store: " + workspaceName + "," + storeName);
} }
return original;
} }


SimpleFeatureType buildFeatureType(FeatureTypeInfo fti) { SimpleFeatureType buildFeatureType(FeatureTypeInfo fti) {
Expand Down

0 comments on commit 5fef79c

Please sign in to comment.