Skip to content

Commit

Permalink
Layer service configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
fernandor777 committed Nov 30, 2018
1 parent 4c0a5b0 commit 0b2d622
Show file tree
Hide file tree
Showing 32 changed files with 931 additions and 54 deletions.
4 changes: 3 additions & 1 deletion src/extension/csw/core/src/main/java/applicationContext.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2014 - 2015 - Open Source Geospatial Foundation. All rights reserved.
Copyright (C) 2014 - 2018 - Open Source Geospatial Foundation. All rights reserved.
This code is licensed under the GPL 2.0 license, available at the root
application directory.
-->
Expand Down Expand Up @@ -246,4 +246,6 @@
<bean id="zipResponse" class="org.geoserver.csw.response.ZipOutputFormat" />

<bean id="DirectDownloadXStreamInitializer" class="org.geoserver.csw.DirectDownloadSettingsXStreamInitializer" />

<bean id="cswResourceVoter" class="org.geoserver.csw.CSWResourceVoter" />
</beans>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* (c) 2018 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.csw;

import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.ServiceResourceVoter;

public class CSWResourceVoter implements ServiceResourceVoter {

@Override
public boolean hideService(ResourceInfo resource) {
return false;
}

@Override
public String serviceName() {
return "CSW";
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* (c) 2017 Open Source Geospatial Foundation - all rights reserved
/* (c) 2017 -2018 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
Expand All @@ -8,7 +8,10 @@
import static org.custommonkey.xmlunit.XMLAssert.assertXpathExists;
import static org.custommonkey.xmlunit.XMLAssert.assertXpathNotExists;

import java.util.ArrayList;
import java.util.Arrays;
import org.geoserver.catalog.Keyword;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.data.test.SystemTestData;
import org.geotools.geometry.jts.ReferencedEnvelope;
Expand Down Expand Up @@ -305,4 +308,57 @@ public void testTitleFilterCSWRecord() throws Exception {
"//gmd:MD_Metadata[gmd:identificationInfo/gmd:AbstractMD_Identification/gmd:citation/gmd:CI_Citation/gmd:title/gco:CharacterString='Seven']",
d);
}

/** Tests CSW service disabled on layer-resource */
@Test
public void testLayerDisabledServiceRecords() throws Exception {
disableCWSOnLinesLayer();
String request =
"csw?service=CSW&version=2.0.2&request=GetRecords&typeNames=gmd:MD_Metadata"
+ "&resultType=results&elementSetName=full&outputSchema=http://www.isotc211.org/2005/gmd";
Document doc = getAsDOM(request);

assertXpathEvaluatesTo(
"0",
"count(/csw:GetRecordsResponse/csw:SearchResults/gmd:MD_Metadata/"
+ "gmd:distributionInfo/gmd:MD_Distribution/gmd:transferOptions/gmd:MD_DigitalTransferOptions/"
+ "gmd:onLine/gmd:CI_OnlineResource/gmd:name/gco:CharacterString[.='Lines'])",
doc);
enableCWSOnLinesLayer();
}

/** Tests CSW service enabled on layer-resource */
@Test
public void testLayerEnabledServiceRecords() throws Exception {
enableCWSOnLinesLayer();
String request =
"csw?service=CSW&version=2.0.2&request=GetRecords&typeNames=gmd:MD_Metadata"
+ "&resultType=results&elementSetName=full&outputSchema=http://www.isotc211.org/2005/gmd";
Document doc = getAsDOM(request);

assertXpathEvaluatesTo(
"2",
"count(/csw:GetRecordsResponse/csw:SearchResults/gmd:MD_Metadata/"
+ "gmd:distributionInfo/gmd:MD_Distribution/gmd:transferOptions/gmd:MD_DigitalTransferOptions/"
+ "gmd:onLine/gmd:CI_OnlineResource/gmd:name/gco:CharacterString[.='Lines'])",
doc);
}

private void enableCWSOnLinesLayer() {
LayerInfo linfo = getCatalog().getLayerByName("Lines");
ResourceInfo ri = linfo.getResource();
ri.setServiceConfiguration(false);
ri.setDisabledServices(new ArrayList<>());
getCatalog().save(ri);
getCatalog().save(linfo);
}

private void disableCWSOnLinesLayer() {
LayerInfo linfo = getCatalog().getLayerByName("Lines");
ResourceInfo ri = linfo.getResource();
ri.setServiceConfiguration(true);
ri.setDisabledServices(new ArrayList<>(Arrays.asList("CSW")));
getCatalog().save(ri);
getCatalog().save(linfo);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -322,4 +322,6 @@
<bean id="rawDataSizeEstimator" class="org.geoserver.wps.validator.RawDataSizeEstimator"/>
<bean id="geometrySizeEstimator" class="org.geoserver.wps.validator.GeometrySizeEstimator"/>
<bean id="processStartupFilter" class="org.geoserver.wps.executor.ProcessStartupFilter"/>

<bean id="wpsResourceVoter" class="org.geoserver.wps.WPSResourceVoter"/>
</beans>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* (c) 2018 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wps;

import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.ServiceResourceVoter;

public class WPSResourceVoter implements ServiceResourceVoter {

@Override
public boolean hideService(ResourceInfo resource) {
return true;
}

@Override
public String serviceName() {
return "WPS";
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
/* (c) 2014 - 2018 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
Expand All @@ -21,6 +21,8 @@
import java.io.InputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
Expand All @@ -36,6 +38,8 @@
import org.custommonkey.xmlunit.XMLUnit;
import org.custommonkey.xmlunit.XpathEngine;
import org.custommonkey.xmlunit.exceptions.XpathException;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.data.test.MockData;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.data.test.SystemTestData.LayerProperty;
Expand Down Expand Up @@ -864,35 +868,42 @@ public void testShapeZip() throws Exception {
*/
@Test
public void testBoundsPost() throws Exception {
String request =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<wps:Execute version=\"1.0.0\" service=\"WPS\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.opengis.net/wps/1.0.0\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:wps=\"http://www.opengis.net/wps/1.0.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:wcs=\"http://www.opengis.net/wcs/1.1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xsi:schemaLocation=\"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd\">\n"
+ " <ows:Identifier>gs:Bounds</ows:Identifier>\n"
+ " <wps:DataInputs>\n"
+ " <wps:Input>\n"
+ " <ows:Identifier>features</ows:Identifier>\n"
+ " <wps:Reference mimeType=\"text/xml; subtype=wfs-collection/1.0\" xlink:href=\"http://geoserver/wfs\" method=\"POST\">\n"
+ " <wps:Body>\n"
+ " <wfs:GetFeature service=\"WFS\" version=\"1.0.0\">\n"
+ " <wfs:Query typeName=\"cite:Streams\"/>\n"
+ " </wfs:GetFeature>\n"
+ " </wps:Body>\n"
+ " </wps:Reference>\n"
+ " </wps:Input>\n"
+ " </wps:DataInputs>\n"
+ " <wps:ResponseForm>\n"
+ " <wps:RawDataOutput>\n"
+ " <ows:Identifier>bounds</ows:Identifier>\n"
+ " </wps:RawDataOutput>\n"
+ " </wps:ResponseForm>\n"
+ "</wps:Execute>";
String request = streamsBoundsRequest();

Document dom = postAsDOM(root(), request);
print(dom);
checkStreamsProcessBounds(dom);
}

private void checkStreamsProcessBounds(Document dom) throws XpathException {
assertXpathEvaluatesTo("-4.0E-4 -0.0024", "/ows:BoundingBox/ows:LowerCorner", dom);
assertXpathEvaluatesTo("0.0036 0.0024", "/ows:BoundingBox/ows:UpperCorner", dom);
}

private String streamsBoundsRequest() {
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<wps:Execute version=\"1.0.0\" service=\"WPS\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.opengis.net/wps/1.0.0\" xmlns:wfs=\"http://www.opengis.net/wfs\" xmlns:wps=\"http://www.opengis.net/wps/1.0.0\" xmlns:ows=\"http://www.opengis.net/ows/1.1\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:wcs=\"http://www.opengis.net/wcs/1.1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xsi:schemaLocation=\"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd\">\n"
+ " <ows:Identifier>gs:Bounds</ows:Identifier>\n"
+ " <wps:DataInputs>\n"
+ " <wps:Input>\n"
+ " <ows:Identifier>features</ows:Identifier>\n"
+ " <wps:Reference mimeType=\"text/xml; subtype=wfs-collection/1.0\" xlink:href=\"http://geoserver/wfs\" method=\"POST\">\n"
+ " <wps:Body>\n"
+ " <wfs:GetFeature service=\"WFS\" version=\"1.0.0\">\n"
+ " <wfs:Query typeName=\"cite:Streams\"/>\n"
+ " </wfs:GetFeature>\n"
+ " </wps:Body>\n"
+ " </wps:Reference>\n"
+ " </wps:Input>\n"
+ " </wps:DataInputs>\n"
+ " <wps:ResponseForm>\n"
+ " <wps:RawDataOutput>\n"
+ " <ows:Identifier>bounds</ows:Identifier>\n"
+ " </wps:RawDataOutput>\n"
+ " </wps:ResponseForm>\n"
+ "</wps:Execute>";
}

/**
* Tests a process execution with a BoudingBox as the output and check internal layer request
* handling as well
Expand All @@ -919,8 +930,7 @@ public void testBoundsGet() throws Exception {
Document dom = postAsDOM(root(), request);
// print(dom);

assertXpathEvaluatesTo("-4.0E-4 -0.0024", "/ows:BoundingBox/ows:LowerCorner", dom);
assertXpathEvaluatesTo("0.0036 0.0024", "/ows:BoundingBox/ows:UpperCorner", dom);
checkStreamsProcessBounds(dom);
}

/** Tests a process grabbing a remote layer */
Expand Down Expand Up @@ -2139,4 +2149,47 @@ private void checkShapefileIntegrity(String[] typeNames, final InputStream in)
}
zis.close();
}

/** Tests WPS service disabled on layer-resource */
@Test
public void testDisableLayerService() throws Exception {
disableWPSOnStreams();
String request = streamsBoundsRequest();

Document dom = postAsDOM(root(), request);
print(dom);
assertXpathExists("//wps:Status/wps:ProcessFailed", dom);
enableWPSOnStreams();
}

/** Tests WPS service enabled on layer-resource */
@Test
public void testEnableLayerService() throws Exception {
enableWPSOnStreams();
String request = streamsBoundsRequest();

Document dom = postAsDOM(root(), request);
print(dom);
checkStreamsProcessBounds(dom);
}

private void disableWPSOnStreams() {
String layerName = "cite:Streams";
LayerInfo linfo = getCatalog().getLayerByName(layerName);
ResourceInfo ri = linfo.getResource();
ri.setServiceConfiguration(true);
ri.setDisabledServices(new ArrayList<>(Arrays.asList("WPS")));
getCatalog().save(ri);
getCatalog().save(linfo);
}

private void enableWPSOnStreams() {
String layerName = "cite:Streams";
LayerInfo linfo = getCatalog().getLayerByName(layerName);
ResourceInfo ri = linfo.getResource();
ri.setServiceConfiguration(false);
ri.setDisabledServices(new ArrayList<>());
getCatalog().save(ri);
getCatalog().save(linfo);
}
}
4 changes: 4 additions & 0 deletions src/main/src/main/java/applicationContext.xml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
<constructor-arg ref="advertisedCatalog" />
</bean>
<bean id="disabledResourceFilter" class="org.geoserver.security.DisabledResourceFilter"/>
<bean id="disabledServiceResourceFilter" class="org.geoserver.security.DisabledServiceResourceFilter"/>

<!-- Switch this when you want to enable the secure catalog by default -->
<!--alias name="secureCatalog" alias="catalog"/-->
Expand Down Expand Up @@ -292,4 +293,7 @@
<bean id="capabilitiesCachingHeadersCallback" class="org.geoserver.config.CapabilitiesCacheHeadersCallback">
<constructor-arg ref="geoServer"/>
</bean>

<bean id="serviceResourceUtil" class="org.geoserver.catalog.ServiceResourceUtil"/>

</beans>
14 changes: 13 additions & 1 deletion src/main/src/main/java/org/geoserver/catalog/ResourceInfo.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
/* (c) 2014 - 2018 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
Expand Down Expand Up @@ -367,4 +367,16 @@ public interface ResourceInfo extends CatalogInfo {
* @param advertised
*/
void setAdvertised(boolean advertised);

/** Returns true if the resource will configure services access, false otherwise */
boolean isServiceConfiguration();

/** Set to true if the resource will configure services access, false otherwise */
void setServiceConfiguration(boolean serviceConfiguration);

/** Returns a list of disabled services names for this resource */
List<String> getDisabledServices();

/** Set the list of disabled services names for this resource */
void setDisabledServices(List<String> disabledServices);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* (c) 2018 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.catalog;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.geoserver.platform.GeoServerExtensions;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class ServiceResourceUtil implements ApplicationContextAware {

public static final String BEAN_ID = "serviceResourceUtil";

protected ApplicationContext context;

public ServiceResourceUtil() {}

public List<String> getLayerVotedServices(ResourceInfo resource) {
List<ServiceResourceVoter> voters =
GeoServerExtensions.extensions(ServiceResourceVoter.class, context);
return voters.stream()
.filter(v -> !v.hideService(resource))
.map(v -> v.serviceName())
.collect(Collectors.toCollection(ArrayList::new));
}

@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.context = context;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* (c) 2018 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.catalog;

/**
* Allows to verify if a given layer is suitable for publishing on a given service. A single
* negative vote will make the service disappear from the selective service layer UI
*
* @author Andrea Aime, Geosolutions
* @author Fernando Mino, Geosolutions
*/
public interface ServiceResourceVoter {

/**
* Returns true if the services is not considered suitable for the given layer. In case the
* answer is unknown by this voter, false will be returned
*/
boolean hideService(ResourceInfo resource);

/** Returns service name for registered Resource voter */
String serviceName();
}

0 comments on commit 0b2d622

Please sign in to comment.