Skip to content

Commit

Permalink
[GEOS-8165] Layer groups not queryable when members are not advertised
Browse files Browse the repository at this point in the history
  • Loading branch information
aaime committed Apr 27, 2018
1 parent 909bce8 commit 50c643f
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class AdvertisedCatalog extends AbstractFilteredCatalog {
*
* @author Andrea Aime - GeoSolutions
*/
static final class AdvertisedLayerGroup extends DecoratingLayerGroupInfo {
public static final class AdvertisedLayerGroup extends DecoratingLayerGroupInfo {
private static final long serialVersionUID = 1037043388874118840L;
private List<PublishedInfo> filteredLayers;
private List<StyleInfo> filteredStyles;
Expand All @@ -62,6 +62,15 @@ public List<PublishedInfo> getLayers() {
public List<StyleInfo> getStyles() {
return new FilteredList<>(filteredStyles, delegate.getStyles());
}

/**
* Returns the original layers, including the advertised ones. Use this method only if
* strictly necessary (current use case, figuring out if the group is queryable or not)
* @return
*/
public List<PublishedInfo> getOriginalLayers() {
return delegate.getLayers();
}
}

private LayerGroupVisibilityPolicy layerGroupPolicy = LayerGroupVisibilityPolicy.HIDE_NEVER;
Expand Down
38 changes: 35 additions & 3 deletions src/wms/src/main/java/org/geoserver/wms/WMS.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.geoserver.catalog.StyleInfo;
import org.geoserver.catalog.WMSLayerInfo;
import org.geoserver.catalog.WMTSLayerInfo;
import org.geoserver.catalog.impl.AdvertisedCatalog;
import org.geoserver.catalog.util.ReaderDimensionsAccessor;
import org.geoserver.config.GeoServer;
import org.geoserver.config.GeoServerInfo;
Expand All @@ -44,6 +45,7 @@
import org.geotools.data.ows.Layer;
import org.geotools.data.ows.OperationType;
import org.geotools.data.ows.WMSCapabilities;
import org.geotools.decorate.Wrapper;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.factory.GeoTools;
import org.geotools.feature.FeatureCollection;
Expand Down Expand Up @@ -1030,13 +1032,12 @@ public Integer getCascadedHopCount(LayerInfo layer) {
}

public boolean isQueryable(LayerGroupInfo layerGroup) {

if (layerGroup.isQueryDisabled())
return false;

boolean queryable = false;

for (PublishedInfo published : layerGroup.getLayers()) {
List<PublishedInfo> layers = getLayersForQueryableChecks(layerGroup);
for (PublishedInfo published : layers) {
if (published instanceof LayerInfo) {
queryable |= isQueryable((LayerInfo) published);
} else {
Expand All @@ -1046,6 +1047,37 @@ public boolean isQueryable(LayerGroupInfo layerGroup) {
return queryable;
}

/**
* For queryability purposes, a group is queryable if any layer inside of it, advertised or not,
* is queriable (because the non advertised layer is still available in GetFeatureInfo). So,
* just for this use case, we are going to unwrap {@link
* org.geoserver.catalog.impl.AdvertisedCatalog.AdvertisedLayerGroup} and get the original list
* of layers. The security wrappers are below it by construction, so this won't case, per se,
* security issues.
*
* @param layerGroup the group whose query-ability needs to be checked
* @return a list of {@link PublishedInfo} contained in the layer (queryable or not)
*/
private List<PublishedInfo> getLayersForQueryableChecks(LayerGroupInfo layerGroup) {
List<PublishedInfo> layers = layerGroup.getLayers();
// direct wrapper?
if (layerGroup instanceof AdvertisedCatalog.AdvertisedLayerGroup) {
AdvertisedCatalog.AdvertisedLayerGroup wrapper =
(AdvertisedCatalog.AdvertisedLayerGroup) layerGroup;
layers = wrapper.getOriginalLayers();
} else if (layerGroup instanceof Wrapper) {
// hidden inside some other wrapper?
Wrapper wrapper = (Wrapper) layerGroup;
if (wrapper.isWrapperFor(AdvertisedCatalog.AdvertisedLayerGroup.class)) {
wrapper.unwrap(AdvertisedCatalog.AdvertisedLayerGroup.class);
AdvertisedCatalog.AdvertisedLayerGroup alg =
(AdvertisedCatalog.AdvertisedLayerGroup) layerGroup;
layers = alg.getOriginalLayers();
}
}
return layers;
}

/**
* Returns the read parameters for the specified layer, merging some well known request
* parameters into the read parameters if possible
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import static org.custommonkey.xmlunit.XMLAssert.assertXpathNotExists;
import static org.custommonkey.xmlunit.XMLUnit.newXpathEngine;
import static org.junit.Assert.*;
import java.util.ArrayList;

import java.util.HashSet;

import static org.hamcrest.CoreMatchers.is;
Expand All @@ -19,6 +19,7 @@
import java.io.StringWriter;
import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
Expand Down Expand Up @@ -54,7 +55,6 @@
import org.geoserver.wms.WMSTestSupport;
import org.geoserver.wms.capabilities.Capabilities_1_3_0_Transformer;
import org.geoserver.wms.capabilities.GetCapabilitiesTransformer;
import org.geotools.data.Base64;
import org.geotools.referencing.CRS;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletResponse;
Expand Down Expand Up @@ -727,4 +727,68 @@ private Document findCapabilities(Boolean scaleHintUnitsPerDiaPixel) throws Exce

return dom;
}

@Test
public void testNonAdvertisedQueriableWithinGroup() throws Exception {
// make layers non advertised
Catalog catalog = getCatalog();
setAdvertised(catalog, MockData.LAKES, false);
setAdvertised(catalog, MockData.NAMED_PLACES, false);
LayerGroupInfo group = null;
try {
group = createLakesPlacesLayerGroup(catalog,
LayerGroupInfo.Mode.SINGLE, null);
Document dom = dom(get("wms?request=GetCapabilities&version=1.1.0"), true);
// print(dom);

assertXpathEvaluatesTo("1", "//Layer[Name='lakes_and_places']/@queryable", dom);
} finally {
if (group != null) {
catalog.remove(group);
}
setAdvertised(catalog, MockData.LAKES, true);
setAdvertised(catalog, MockData.NAMED_PLACES, true);
}
}

@Test
public void testNonAdvertisedNonQueriableWithinGroup() throws Exception {
// make layers non advertised
Catalog catalog = getCatalog();
setAdvertised(catalog, MockData.LAKES, false);
setQueryable(catalog, MockData.LAKES, false);
setAdvertised(catalog, MockData.NAMED_PLACES, false);
setQueryable(catalog, MockData.NAMED_PLACES, false);
LayerGroupInfo group = null;
try {
group = createLakesPlacesLayerGroup(catalog, LayerGroupInfo.Mode.SINGLE, null);
Document dom = dom(get("wms?request=GetCapabilities&version=1.1.0"), true);
// print(dom);

assertXpathEvaluatesTo("0", "//Layer[Name='lakes_and_places']/@queryable", dom);
} finally {
if (group != null) {
catalog.remove(group);
}
setAdvertised(catalog, MockData.LAKES, true);
setQueryable(catalog, MockData.LAKES, true);
setAdvertised(catalog, MockData.NAMED_PLACES, true);
setQueryable(catalog, MockData.NAMED_PLACES, true);
}


}

private void setAdvertised(Catalog catalog, QName name, boolean advertised) {
LayerInfo lakes = catalog.getLayerByName(getLayerId(name));
lakes.setAdvertised(advertised);
catalog.save(lakes);
}

private void setQueryable(Catalog catalog, QName name, boolean queryable) {
LayerInfo lakes = catalog.getLayerByName(getLayerId(name));
lakes.setQueryable(queryable);
catalog.save(lakes);
}

}

0 comments on commit 50c643f

Please sign in to comment.