Skip to content

Commit

Permalink
GEOS-7887: use GML3 format from WFS Spring context to avoid memory leak
Browse files Browse the repository at this point in the history
  • Loading branch information
jandm authored and aaime committed Dec 16, 2016
1 parent c9ddb9a commit 1cf0910
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 40 deletions.
2 changes: 1 addition & 1 deletion src/community/wms-eo/src/main/java/applicationContext.xml
Expand Up @@ -13,7 +13,7 @@
</bean> </bean>


<bean id="wmsGetFeatureInfoXML" class="org.geoserver.wms.eo.XMLFeatureInfoOutputFormat"> <bean id="wmsGetFeatureInfoXML" class="org.geoserver.wms.eo.XMLFeatureInfoOutputFormat">
<constructor-arg ref="wms" /> <constructor-arg ref="gml3OutputFormat" />
</bean> </bean>


<bean id="wmsEoLayerGroupMenuPage" class="org.geoserver.web.MenuPageInfo"> <bean id="wmsEoLayerGroupMenuPage" class="org.geoserver.web.MenuPageInfo">
Expand Down
Expand Up @@ -7,7 +7,7 @@


import org.geoserver.wms.WMS; import org.geoserver.wms.WMS;
import org.geoserver.wms.featureinfo.GML3FeatureInfoOutputFormat; import org.geoserver.wms.featureinfo.GML3FeatureInfoOutputFormat;

import org.geoserver.wfs.xml.GML3OutputFormat;


/** /**
* A GetFeatureInfo response handler specialized in producing xml data for a GetFeatureInfo request. * A GetFeatureInfo response handler specialized in producing xml data for a GetFeatureInfo request.
Expand All @@ -25,7 +25,7 @@ public class XMLFeatureInfoOutputFormat extends GML3FeatureInfoOutputFormat {
/** /**
* Default constructor, sets up the supported output format string. * Default constructor, sets up the supported output format string.
*/ */
public XMLFeatureInfoOutputFormat(final WMS wms) { public XMLFeatureInfoOutputFormat(final GML3OutputFormat outputFormat) {
super(wms, FORMAT); super(outputFormat, FORMAT);
} }
} }
4 changes: 2 additions & 2 deletions src/wms/src/main/java/applicationContext.xml
Expand Up @@ -82,11 +82,11 @@
</bean> </bean>


<bean id="wmsGetFeatureInfoGML3" class="org.geoserver.wms.featureinfo.GML3FeatureInfoOutputFormat"> <bean id="wmsGetFeatureInfoGML3" class="org.geoserver.wms.featureinfo.GML3FeatureInfoOutputFormat">
<constructor-arg ref="wms" /> <constructor-arg ref="gml3OutputFormat" />
</bean> </bean>


<bean id="wmsGetFeatureInfoXML311" class="org.geoserver.wms.featureinfo.XML311FeatureInfoOutputFormat"> <bean id="wmsGetFeatureInfoXML311" class="org.geoserver.wms.featureinfo.XML311FeatureInfoOutputFormat">
<constructor-arg ref="wms" /> <constructor-arg ref="gml3OutputFormat" />
</bean> </bean>


<bean id="wmsGetFeatureInfoHTML" class="org.geoserver.wms.featureinfo.HTMLFeatureInfoOutputFormat"> <bean id="wmsGetFeatureInfoHTML" class="org.geoserver.wms.featureinfo.HTMLFeatureInfoOutputFormat">
Expand Down
Expand Up @@ -18,30 +18,25 @@
import net.opengis.wfs.QueryType; import net.opengis.wfs.QueryType;
import net.opengis.wfs.WfsFactory; import net.opengis.wfs.WfsFactory;


import org.geoserver.config.GeoServer;
import org.geoserver.platform.Operation; import org.geoserver.platform.Operation;
import org.geoserver.platform.Service; import org.geoserver.platform.Service;
import org.geoserver.platform.ServiceException; import org.geoserver.platform.ServiceException;
import org.geoserver.wfs.xml.FeatureTypeSchemaBuilder;
import org.geoserver.wfs.xml.GML3OutputFormat; import org.geoserver.wfs.xml.GML3OutputFormat;
import org.geoserver.wfs.xml.v1_1_0.WFS;
import org.geoserver.wfs.xml.v1_1_0.WFSConfiguration;
import org.geoserver.wms.GetFeatureInfoRequest; import org.geoserver.wms.GetFeatureInfoRequest;
import org.geoserver.wms.WMS;
import org.geotools.feature.FeatureCollection; import org.geotools.feature.FeatureCollection;
import org.geotools.gml2.bindings.GML2EncodingUtils; import org.geotools.gml2.bindings.GML2EncodingUtils;
import org.opengis.feature.type.Name; import org.opengis.feature.type.Name;


/** /**
* A GetFeatureInfo response handler specialized in producing GML 3 data for a GetFeatureInfo request. * A GetFeatureInfo response handler specialized in producing GML 3 data for a GetFeatureInfo request.
* *
* <p> * <p>
* This class does not deals directly with GML encoding. Instead, it works by taking the * This class does not deals directly with GML encoding. Instead, it works by taking the
* FeatureResults produced in <code>execute()</code> and constructs a <code>GetFeaturesResult</code> * FeatureResults produced in <code>execute()</code> and constructs a <code>GetFeaturesResult</code>
* wich is passed to a <code>GML2FeatureResponseDelegate</code>, as if it where the result of a * wich is passed to a <code>GML2FeatureResponseDelegate</code>, as if it where the result of a
* GetFeature WFS request. * GetFeature WFS request.
* </p> * </p>
* *
* @author Niels Charlier * @author Niels Charlier
*/ */
public class GML3FeatureInfoOutputFormat extends GetFeatureInfoOutputFormat { public class GML3FeatureInfoOutputFormat extends GetFeatureInfoOutputFormat {
Expand All @@ -50,26 +45,25 @@ public class GML3FeatureInfoOutputFormat extends GetFeatureInfoOutputFormat {
*/ */
public static final String FORMAT = "application/vnd.ogc.gml/3.1.1"; public static final String FORMAT = "application/vnd.ogc.gml/3.1.1";


private WMS wms; private GML3OutputFormat outputFormat;


/** /**
* Default constructor, sets up the supported output format string. * Default constructor, sets up the supported output format string.
*/ */
public GML3FeatureInfoOutputFormat(final WMS wms) { public GML3FeatureInfoOutputFormat(final GML3OutputFormat outputFormat) {
this(wms, FORMAT); this(outputFormat, FORMAT);
} }

protected GML3FeatureInfoOutputFormat(WMS wms, String format) { protected GML3FeatureInfoOutputFormat(GML3OutputFormat outputFormat, String format) {
super(format); super(format);
this.wms = wms; this.outputFormat = outputFormat;
} }


/** /**
* Takes the <code>FeatureResult</code>s generated by the <code>execute</code> method in the * Takes the <code>FeatureResult</code>s generated by the <code>execute</code> method in the
* superclass and constructs a <code>GetFeaturesResult</code> wich is passed to a * superclass and constructs a <code>GetFeaturesResult</code> wich is passed to a
* <code>GML2FeatureResponseDelegate</code>. * <code>GML2FeatureResponseDelegate</code>.
* *
* @see AbstractFeatureInfoResponse#writeTo(OutputStream)
*/ */
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({ "rawtypes", "unchecked" })
@Override @Override
Expand All @@ -82,25 +76,25 @@ public void write(FeatureCollectionType results, GetFeatureInfoRequest fInfoReq,
// the 'request' object we'll pass to our OutputFormat // the 'request' object we'll pass to our OutputFormat
GetFeatureType gfreq = WfsFactory.eINSTANCE.createGetFeatureType(); GetFeatureType gfreq = WfsFactory.eINSTANCE.createGetFeatureType();
gfreq.setBaseUrl(fInfoReq.getBaseUrl()); gfreq.setBaseUrl(fInfoReq.getBaseUrl());

for (int i=0; i < results.getFeature().size(); i++) { for (int i=0; i < results.getFeature().size(); i++) {

FeatureCollection fc = (FeatureCollection) results.getFeature().get(i); FeatureCollection fc = (FeatureCollection) results.getFeature().get(i);
Name name = FeatureCollectionDecorator.getName(fc); Name name = FeatureCollectionDecorator.getName(fc);
QName qname = new QName(name.getNamespaceURI(), name.getLocalPart()); QName qname = new QName(name.getNamespaceURI(), name.getLocalPart());

features.getFeature().add(fc); features.getFeature().add(fc);


QueryType qt = WfsFactory.eINSTANCE.createQueryType(); QueryType qt = WfsFactory.eINSTANCE.createQueryType();

qt.setTypeName(Collections.singletonList(qname)); qt.setTypeName(Collections.singletonList(qname));

String crs = GML2EncodingUtils.epsgCode(fc.getSchema().getCoordinateReferenceSystem()); String crs = GML2EncodingUtils.epsgCode(fc.getSchema().getCoordinateReferenceSystem());
if (crs != null) { if (crs != null) {
final String srsName = "EPSG:" + crs; final String srsName = "EPSG:" + crs;
try { try {
qt.setSrsName(new URI(srsName)); qt.setSrsName(new URI(srsName));

} catch (URISyntaxException e) { } catch (URISyntaxException e) {
throw new ServiceException( throw new ServiceException(
"Unable to determite coordinate system for featureType " "Unable to determite coordinate system for featureType "
Expand All @@ -116,14 +110,7 @@ public void write(FeatureCollectionType results, GetFeatureInfoRequest fInfoReq,
// accept it. // accept it.
Service serviceDesc = new Service("wms", null, null, Collections.EMPTY_LIST); Service serviceDesc = new Service("wms", null, null, Collections.EMPTY_LIST);
Operation opDescriptor = new Operation("", serviceDesc, null, new Object[] { gfreq }); Operation opDescriptor = new Operation("", serviceDesc, null, new Object[] { gfreq });

outputFormat.write(features, out, opDescriptor);
final GeoServer gs = wms.getGeoServer();

FeatureTypeSchemaBuilder sb = new FeatureTypeSchemaBuilder.GML3(gs);
WFSConfiguration configuration = new WFSConfiguration(gs, sb, new WFS(sb));

GML3OutputFormat format = new GML3OutputFormat(gs, configuration);
format.write(features, out, opDescriptor);
} }


} }
Expand Up @@ -5,7 +5,7 @@
*/ */
package org.geoserver.wms.featureinfo; package org.geoserver.wms.featureinfo;


import org.geoserver.wms.WMS; import org.geoserver.wfs.xml.GML3OutputFormat;


/** /**
* A GetFeatureInfo response handler specialized in producing GML 3.1.1 data for a GetFeatureInfo request. * A GetFeatureInfo response handler specialized in producing GML 3.1.1 data for a GetFeatureInfo request.
Expand All @@ -28,10 +28,10 @@ public class XML311FeatureInfoOutputFormat extends GML3FeatureInfoOutputFormat {
/** /**
* Default constructor, sets up the supported output format String. * Default constructor, sets up the supported output format String.
* *
* @param wms WMS to use. * @param outputFormat format to use
*/ */
public XML311FeatureInfoOutputFormat(WMS wms) { public XML311FeatureInfoOutputFormat(GML3OutputFormat outputFormat) {
super(wms, FORMAT); super(outputFormat, FORMAT);
} }


} }
Expand Up @@ -21,6 +21,7 @@
import org.custommonkey.xmlunit.XMLAssert; import org.custommonkey.xmlunit.XMLAssert;
import org.custommonkey.xmlunit.XMLUnit; import org.custommonkey.xmlunit.XMLUnit;
import org.custommonkey.xmlunit.XpathEngine; import org.custommonkey.xmlunit.XpathEngine;
import org.eclipse.xsd.XSDSchema;
import org.geoserver.catalog.Catalog; import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.LayerInfo; import org.geoserver.catalog.LayerInfo;
import org.geoserver.data.test.MockData; import org.geoserver.data.test.MockData;
Expand All @@ -35,6 +36,7 @@
import org.geoserver.wms.featureinfo.TextFeatureInfoOutputFormat; import org.geoserver.wms.featureinfo.TextFeatureInfoOutputFormat;
import org.geoserver.wms.featureinfo.XML311FeatureInfoOutputFormat; import org.geoserver.wms.featureinfo.XML311FeatureInfoOutputFormat;
import org.geoserver.wms.wms_1_1_1.CapabilitiesTest; import org.geoserver.wms.wms_1_1_1.CapabilitiesTest;
import org.geotools.filter.v1_1.OGC;
import org.geotools.util.logging.Logging; import org.geotools.util.logging.Logging;
import org.junit.Test; import org.junit.Test;
import org.w3c.dom.Document; import org.w3c.dom.Document;
Expand Down Expand Up @@ -840,4 +842,23 @@ public void testGetFeatureInfoOnLineStringsWithGenericGeometry() throws Exceptio
assertThat(xpath.evaluate("boolean(//wfs:FeatureCollection/gml:featureMember/gs:genericLines[@fid='line.2'][gs:name='line2'])", result), is("true")); assertThat(xpath.evaluate("boolean(//wfs:FeatureCollection/gml:featureMember/gs:genericLines[@fid='line.2'][gs:name='line2'])", result), is("true"));
assertThat(xpath.evaluate("boolean(//wfs:FeatureCollection/gml:featureMember/gs:genericLines[@fid='line.3'][gs:name='line3'])", result), is("true")); assertThat(xpath.evaluate("boolean(//wfs:FeatureCollection/gml:featureMember/gs:genericLines[@fid='line.3'][gs:name='line3'])", result), is("true"));
} }

@Test
public void testSchemaLeak() throws Exception {
String layer = getLayerId(MockData.FORESTS);
String request = "wms?version=1.3.0&bbox=-0.002,-0.002,0.002,0.002&styles=&format=jpeg&info_format=" + GML3FeatureInfoOutputFormat.FORMAT + "&request=GetFeatureInfo&layers="
+ layer + "&query_layers=" + layer + "&width=20&height=20&i=10&j=10";
// prime system, make sure everything is wired
getAsDOM(request);

// count how many imports in the OGC filter schema
XSDSchema schema = OGC.getInstance().getSchema();
int expectedImportCounts = schema.getReferencingDirectives().size();

// now check how many there are after anothe request, should not go up
getAsDOM(request);
int actualImportCounts = schema.getReferencingDirectives().size();
assertEquals(expectedImportCounts, actualImportCounts);
}

} }

0 comments on commit 1cf0910

Please sign in to comment.