Skip to content

Commit

Permalink
[GEOS-9985] Impossible to configure a WMS cascading layer with JDBCCo…
Browse files Browse the repository at this point in the history
…nfig
  • Loading branch information
aaime committed Mar 19, 2021
1 parent 35b060c commit 69c099a
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,11 @@ private void addAttribute(

if (isRelationShip) {
Info relatedObject = lookUpRelatedObject(info, prop, colIndex);
if (relatedObject == null) {
// Layer styles might not be actually persisted, in the case of WMS cascaded layers,
// where they are created on the fly based on the style names found in the caps
// documents. So check if the id is not null, in addition to checking
// if the related object is not null.
if (relatedObject == null || relatedObject.getId() == null) {
concreteTargetPropertyOid = null;
} else {
// the related property may refer to an abstract type (e.g.
Expand Down Expand Up @@ -1758,17 +1762,25 @@ public void visit(WMTSLayerInfo wmtsLayer) {

@Override
public void visit(LayerInfo layer) {
if (layer.getDefaultStyle() != null) {
layer.setDefaultStyle(getById(layer.getDefaultStyle().getId(), StyleInfo.class));
}
Set<StyleInfo> newStyles = new HashSet<>();
for (StyleInfo style : layer.getStyles()) {
if (style != null) {
newStyles.add(getById(style.getId(), StyleInfo.class));
// avoids concurrent modification exceptions on the list contents
// Layer styles might not be actually persisted, in the case of WMS cascaded layers,
// where they are created on the fly based on the style names found in the caps
// documents. So check if the id is not null, in addition to checking if the style is
// not null.
synchronized (layer) {
if (layer.getDefaultStyle() != null && layer.getDefaultStyle().getId() != null) {
layer.setDefaultStyle(
getById(layer.getDefaultStyle().getId(), StyleInfo.class));
}
Set<StyleInfo> newStyles = new HashSet<>();
for (StyleInfo style : new ArrayList<>(layer.getStyles())) {
if (style != null && style.getId() != null) {
newStyles.add(getById(style.getId(), StyleInfo.class));
}
}
layer.getStyles().clear();
layer.getStyles().addAll(newStyles);
}
layer.getStyles().clear();
layer.getStyles().addAll(newStyles);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,21 @@
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Set;
import org.easymock.Capture;
import org.easymock.CaptureType;
import org.easymock.IAnswer;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CatalogBuilder;
import org.geoserver.catalog.CatalogException;
import org.geoserver.catalog.DataStoreInfo;
import org.geoserver.catalog.Info;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.StyleInfo;
import org.geoserver.catalog.WorkspaceInfo;
import org.geoserver.catalog.event.CatalogAddEvent;
import org.geoserver.catalog.event.CatalogListener;
Expand All @@ -43,6 +47,9 @@
import org.geoserver.catalog.impl.FeatureTypeInfoImpl;
import org.geoserver.catalog.impl.LayerInfoImpl;
import org.geoserver.catalog.impl.ModificationProxy;
import org.geoserver.catalog.impl.StyleInfoImpl;
import org.geoserver.catalog.impl.WMSLayerInfoImpl;
import org.geoserver.catalog.impl.WMSStoreInfoImpl;
import org.geoserver.catalog.impl.WorkspaceInfoImpl;
import org.geoserver.config.ConfigurationListener;
import org.geoserver.config.GeoServer;
Expand Down Expand Up @@ -411,4 +418,43 @@ public void testGetServiceWithGeoServerRef() {
service = database.getAll(WMSInfo.class).iterator().next();
assertNotNull(service.getGeoServer());
}

@Test
public void testWMSCascadingInfos() throws Exception {
WorkspaceInfo ws = addWorkspace();

WMSStoreInfoImpl wmsStore = new WMSStoreInfoImpl(database.getCatalog());
wmsStore.setCapabilitiesURL(
ConfigDatabaseTest.class.getResource("/capabilities.xml").toString());
wmsStore.setId("theWmsStore");
wmsStore.setName("fakeGeoServer");
wmsStore.setWorkspace(ws);
wmsStore.setUseConnectionPooling(false); // allows to hit the file system
database.add(wmsStore);

CatalogBuilder cb = new CatalogBuilder(database.getCatalog());
cb.setStore(wmsStore);
WMSLayerInfoImpl wmsLayer = (WMSLayerInfoImpl) cb.buildWMSLayer("states");
wmsLayer.reset();
wmsLayer.setId("theWmsLayer");
wmsLayer.setForcedRemoteStyle("population");
wmsLayer.setSelectedRemoteStyles(new ArrayList<>(Arrays.asList("pophatch", "polygon")));
database.add(wmsLayer);
LayerInfoImpl layer = (LayerInfoImpl) cb.buildLayer(wmsLayer);
layer.setId("theLayer");
// used to fail here, as the styles are generated on the fly
database.add(layer);

StyleInfo defaultStyle = layer.getDefaultStyle();
assertRemoteStyle(defaultStyle);

Set<StyleInfo> styles = layer.getStyles();
assertEquals(2, styles.size());
styles.forEach(this::assertRemoteStyle);
}

private void assertRemoteStyle(StyleInfo defaultStyle) {
assertNull(defaultStyle.getId());
assertEquals(true, defaultStyle.getMetadata().get(StyleInfoImpl.IS_REMOTE, Boolean.class));
}
}
171 changes: 171 additions & 0 deletions src/community/jdbcconfig/src/test/resources/capabilities.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
<?xml version="1.0" encoding="UTF-8"?>
<WMS_Capabilities version="1.3.0" updateSequence="152" xmlns="http://www.opengis.net/wms" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wms http://localhost:8080/geoserver/schemas/wms/1.3.0/capabilities_1_3_0.xsd">
<Service>
<Name>WMS</Name>
<Title>GeoServer Web Map Service</Title>
<Abstract>A compliant implementation of WMS plus most of the SLD extension (dynamic styling). Can also generate PDF, SVG, KML, GeoRSS</Abstract>
<KeywordList>
<Keyword>WFS</Keyword>
<Keyword>WMS</Keyword>
<Keyword>GEOSERVER</Keyword>
</KeywordList>
<OnlineResource xlink:type="simple" xlink:href="http://geoserver.org"/>
<ContactInformation>
<ContactPersonPrimary>
<ContactPerson>Claudius Ptolomaeus</ContactPerson>
<ContactOrganization>The Ancient Geographers</ContactOrganization>
</ContactPersonPrimary>
<ContactPosition>Chief Geographer</ContactPosition>
<ContactAddress>
<AddressType>Work</AddressType>
<Address/>
<City>Alexandria</City>
<StateOrProvince/>
<PostCode/>
<Country>Egypt</Country>
</ContactAddress>
<ContactVoiceTelephone/>
<ContactFacsimileTelephone/>
<ContactElectronicMailAddress>claudius.ptolomaeus@gmail.com</ContactElectronicMailAddress>
</ContactInformation>
<Fees>NONE</Fees>
<AccessConstraints>NONE</AccessConstraints>
</Service>
<Capability>
<Request>
<GetCapabilities>
<Format>text/xml</Format>
<DCPType>
<HTTP>
<Get>
<OnlineResource xlink:type="simple" xlink:href="http://localhost:8080/geoserver/topp/states/ows?SERVICE=WMS&amp;"/>
</Get>
<Post>
<OnlineResource xlink:type="simple" xlink:href="http://localhost:8080/geoserver/topp/states/ows?SERVICE=WMS&amp;"/>
</Post>
</HTTP>
</DCPType>
</GetCapabilities>
<GetMap>
<Format>image/png</Format>
<Format>application/atom+xml</Format>
<Format>application/json;type=geojson</Format>
<Format>application/json;type=topojson</Format>
<Format>application/json;type=utfgrid</Format>
<Format>application/pdf</Format>
<Format>application/rss+xml</Format>
<Format>application/vnd.google-earth.kml+xml</Format>
<Format>application/vnd.google-earth.kml+xml;mode=networklink</Format>
<Format>application/vnd.google-earth.kmz</Format>
<Format>application/vnd.mapbox-vector-tile</Format>
<Format>image/geotiff</Format>
<Format>image/geotiff8</Format>
<Format>image/gif</Format>
<Format>image/jpeg</Format>
<Format>image/png; mode=8bit</Format>
<Format>image/svg+xml</Format>
<Format>image/tiff</Format>
<Format>image/tiff8</Format>
<Format>image/vnd.jpeg-png</Format>
<Format>image/vnd.jpeg-png8</Format>
<Format>text/html; subtype=openlayers</Format>
<Format>text/html; subtype=openlayers2</Format>
<Format>text/html; subtype=openlayers3</Format>
<DCPType>
<HTTP>
<Get>
<OnlineResource xlink:type="simple" xlink:href="http://localhost:8080/geoserver/topp/states/ows?SERVICE=WMS&amp;"/>
</Get>
</HTTP>
</DCPType>
</GetMap>
<GetFeatureInfo>
<Format>text/plain</Format>
<Format>application/vnd.ogc.gml</Format>
<Format>text/xml</Format>
<Format>application/vnd.ogc.gml/3.1.1</Format>
<Format>text/xml; subtype=gml/3.1.1</Format>
<Format>text/html</Format>
<Format>application/json</Format>
<DCPType>
<HTTP>
<Get>
<OnlineResource xlink:type="simple" xlink:href="http://localhost:8080/geoserver/topp/states/ows?SERVICE=WMS&amp;"/>
</Get>
</HTTP>
</DCPType>
</GetFeatureInfo>
</Request>
<Exception>
<Format>XML</Format>
<Format>INIMAGE</Format>
<Format>BLANK</Format>
<Format>JSON</Format>
</Exception>
<Layer>
<Title>GeoServer Web Map Service</Title>
<Abstract>A compliant implementation of WMS plus most of the SLD extension (dynamic styling). Can also generate PDF, SVG, KML, GeoRSS</Abstract>
<!--All supported EPSG projections:-->
<CRS>EPSG:4326</CRS>
<CRS>CRS:84</CRS>
<EX_GeographicBoundingBox>
<westBoundLongitude>-124.731422</westBoundLongitude>
<eastBoundLongitude>-66.969849</eastBoundLongitude>
<southBoundLatitude>24.955967</southBoundLatitude>
<northBoundLatitude>49.371735</northBoundLatitude>
</EX_GeographicBoundingBox>
<BoundingBox CRS="CRS:84" minx="-124.731422" miny="24.955967" maxx="-66.969849" maxy="49.371735"/>
<Layer queryable="1" opaque="0">
<Name>states</Name>
<Title>USA Population</Title>
<Abstract>This is some census data on the states.</Abstract>
<KeywordList>
<Keyword>census</Keyword>
<Keyword>united</Keyword>
<Keyword>boundaries</Keyword>
<Keyword>state</Keyword>
<Keyword>states</Keyword>
</KeywordList>
<CRS>EPSG:4326</CRS>
<CRS>CRS:84</CRS>
<EX_GeographicBoundingBox>
<westBoundLongitude>-124.731422</westBoundLongitude>
<eastBoundLongitude>-66.969849</eastBoundLongitude>
<southBoundLatitude>24.955967</southBoundLatitude>
<northBoundLatitude>49.371735</northBoundLatitude>
</EX_GeographicBoundingBox>
<BoundingBox CRS="CRS:84" minx="-124.731422" miny="24.955967" maxx="-66.969849" maxy="49.371735"/>
<BoundingBox CRS="EPSG:4326" minx="24.955967" miny="-124.73142200000001" maxx="49.371735" maxy="-66.969849"/>
<Style>
<Name>population</Name>
<Title>Population in the United States</Title>
<Abstract>A sample filter that filters the United States into three
categories of population, drawn in different colors</Abstract>
<LegendURL width="84" height="80">
<Format>image/png</Format>
<OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://localhost:8080/geoserver/topp/states/ows?service=WMS&amp;request=GetLegendGraphic&amp;format=image%2Fpng&amp;width=20&amp;height=20&amp;layer=states"/>
</LegendURL>
</Style>
<Style>
<Name>pophatch</Name>
<Title>Population in the United States</Title>
<Abstract>A sample filter that filters the United States into three
categories of population, drawn in different colors</Abstract>
<LegendURL width="84" height="80">
<Format>image/png</Format>
<OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://localhost:8080/geoserver/topp/states/ows?service=WMS&amp;request=GetLegendGraphic&amp;format=image%2Fpng&amp;width=20&amp;height=20&amp;layer=states&amp;style=pophatch"/>
</LegendURL>
</Style>
<Style>
<Name>polygon</Name>
<Title>Default Polygon</Title>
<Abstract>A sample style that draws a polygon</Abstract>
<LegendURL width="20" height="20">
<Format>image/png</Format>
<OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://localhost:8080/geoserver/topp/states/ows?service=WMS&amp;request=GetLegendGraphic&amp;format=image%2Fpng&amp;width=20&amp;height=20&amp;layer=states&amp;style=polygon"/>
</LegendURL>
</Style>
</Layer>
</Layer>
</Capability>
</WMS_Capabilities>
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

public class StyleInfoImpl implements StyleInfo {

/** Marks a remote style, generated on the fly from a capabilites document */
public static final String IS_REMOTE = "isRemote";

protected String id;

protected String name;
Expand Down Expand Up @@ -106,7 +109,7 @@ public Style getStyle() throws IOException {
// remote style does not exist in local catalog
// do not look for this style inside ResourcePool
if (metadata != null)
if (metadata.containsKey("isRemote")) return WMSLayerInfoImpl.getStyleInfo(this);
if (metadata.containsKey(IS_REMOTE)) return WMSLayerInfoImpl.getStyleInfo(this);
return catalog.getResourcePool().getStyle(this);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,8 @@ public Optional<Style> findRemoteStyleByName(final String name) {
public static StyleInfo getStyleInfo(StyleImpl gtWmsStyle) {

StyleInfoImpl styleInfo = new StyleInfoImpl();

styleInfo.setId(gtWmsStyle.getName());
// do not set an id, this is not a persiste object, it could otherwise confuse custom
// catalog facades (e..g, JDBCConfig)
styleInfo.setName(gtWmsStyle.getName());
// a hint
styleInfo.getMetadata().put("isRemote", true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,23 +226,25 @@ protected void doSaveInternal() throws IOException {
}

catalog.validate(resourceInfo, true).throwIfInvalid();
LayerInfo publishedInfo = getPublishedInfo();
catalog.add(resourceInfo);
try {
catalog.add(getPublishedInfo());
} catch (IllegalArgumentException e) {
catalog.add(publishedInfo);
} catch (Exception e) {
catalog.remove(resourceInfo);
throw e;
}
} else {
ResourceInfo oldState = catalog.getResource(resourceInfo.getId(), ResourceInfo.class);

catalog.validate(resourceInfo, true).throwIfInvalid();
LayerInfo publishedInfo = getPublishedInfo();
catalog.save(resourceInfo);
try {
LayerInfo layer = getPublishedInfo();
LayerInfo layer = publishedInfo;
layer.setResource(resourceInfo);
catalog.save(layer);
} catch (IllegalArgumentException e) {
} catch (Exception e) {
catalog.save(oldState);
throw e;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ protected void doSave() {

onSuccessfulSave();
} catch (Exception e) {
LOGGER.log(Level.INFO, "Error saving layer", e);
LOGGER.log(Level.SEVERE, "Error saving layer", e);
error(e.getMessage() == null ? e.toString() : e.getMessage());
}
}
Expand Down

0 comments on commit 69c099a

Please sign in to comment.