📄 getmapxmlreader.java
字号:
/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.vfny.geoserver.wms.requests;
import com.vividsolutions.jts.geom.Coordinate;
import org.geotools.data.DefaultQuery;
import org.geotools.data.FeatureReader;
import org.geotools.data.Query;
import org.geotools.data.Transaction;
import org.geotools.data.crs.ForceCoordinateSystemFeatureReader;
import org.geotools.data.memory.MemoryDataStore;
import org.geotools.feature.FeatureType;
import org.geotools.filter.ExpressionDOMParser;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.styling.SLDParser;
import org.geotools.styling.StyleFactory;
import org.geotools.styling.StyleFactoryFinder;
import org.geotools.styling.StyledLayer;
import org.geotools.styling.StyledLayerDescriptor;
import org.geotools.styling.UserLayer;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.vfny.geoserver.Request;
import org.vfny.geoserver.global.MapLayerInfo;
import org.vfny.geoserver.global.TemporaryFeatureTypeInfo;
import org.vfny.geoserver.util.GETMAPValidator;
import org.vfny.geoserver.util.SLDValidator;
import org.vfny.geoserver.util.requests.readers.XmlRequestReader;
import org.vfny.geoserver.wms.WmsException;
import org.vfny.geoserver.wms.servlets.WMService;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;
import java.awt.Color;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.servlet.http.HttpServletRequest;
/**
* reads in a GetFeature XML WFS request from a XML stream
*
* @author Rob Hranac, TOPP
* @author Chris Holmes, TOPP
* @version $Id: GetMapXmlReader.java 7749 2007-11-13 20:52:54Z jdeolive $
*/
public class GetMapXmlReader extends XmlRequestReader {
private static final StyleFactory styleFactory = StyleFactoryFinder.createStyleFactory();
/**
* Creates a new GetMapXmlReader object.
* @param service this is the service that handles the request
*/
public GetMapXmlReader(WMService service) {
super(service);
}
/**
* Reads the GetMap XML request into a GetMap Request object.
*
* @param reader The plain POST text from the client.
* @param req DOCUMENT ME!
*
* @return The GetMap Request from the xml reader.
*
* @throws WmsException For any problems reading the request.
*/
public Request read(Reader reader, HttpServletRequest req)
throws WmsException {
GetMapRequest getMapRequest = new GetMapRequest((WMService) getServiceRef());
getMapRequest.setHttpServletRequest(req);
boolean validateSchema = wantToValidate(req);
try {
parseGetMapXML(reader, getMapRequest, validateSchema);
} catch (java.net.UnknownHostException unh) {
//J--
//http://www.oreilly.com/catalog/jenut2/chapter/ch19.html ---
// There is one complication to this example. Most web.xml files contain a <!DOCTYPE> tag that specifies
//the document type (or DTD). Despite the fact that Example 19.1 specifies that the parser should not
//validate the document, a conforming XML parser must still read the DTD for any document that has a
//<!DOCTYPE> declaration. Most web.xml have a declaration like this:
//..
//In order to read the DTD, the parser must be able to read the specified URL. If your system is not
//connected to the Internet when you run the example, it will hang.
//. Another workaround to this DTD problem is to simply remove (or comment out) the <!DOCTYPE> declaration from the web.xml file you process with ListServlets1./
//
//also see:
//http://doctypechanger.sourceforge.net/
//J+
throw new WmsException("unknown host - " + unh.getLocalizedMessage()
+ " - if its in a !DOCTYPE, remove the !DOCTYPE tag.");
} catch (SAXParseException se) {
throw new WmsException("line " + se.getLineNumber() + " column " + se.getColumnNumber()
+ " -- " + se.getLocalizedMessage());
} catch (Exception e) {
throw new WmsException(e);
}
return getMapRequest;
}
/**
* Actually read in the XML request and stick it in the request object. We
* do this using the DOM parser (because the SLD parser is DOM based and
* we can integrate). 1. parse into DOM 2. parse the SLD 3. grab the
* rest of the attribute 4. stuff #3 attributes in the request object 5.
* stuff the SLD info into the request object 6. return GetMap schema is
* at http://www.opengeospatial.org/docs/02-017r1.pdf (page 18) NOTE: see
* handlePostGet() for people who put the SLD in the POST and the
* parameters in the GET.
*
* @param xml
* @param getMapRequest
* @param validateSchema DOCUMENT ME!
*
* @throws Exception DOCUMENT ME!
*/
private void parseGetMapXML(Reader xml, GetMapRequest getMapRequest, boolean validateSchema)
throws Exception {
File temp = null;
if (validateSchema) //copy POST to a file
{
//make tempfile
temp = File.createTempFile("getMapPost", "xml");
temp.deleteOnExit();
FileOutputStream fos = new FileOutputStream(temp);
BufferedOutputStream out = new BufferedOutputStream(fos);
int c;
while (-1 != (c = xml.read())) {
out.write(c);
}
xml.close();
out.flush();
out.close();
xml = new BufferedReader(new FileReader(temp)); // pretend like nothing has happened
}
try {
javax.xml.parsers.DocumentBuilderFactory dbf = javax.xml.parsers.DocumentBuilderFactory
.newInstance();
dbf.setExpandEntityReferences(false);
dbf.setValidating(false);
dbf.setNamespaceAware(true);
javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder();
InputSource input = new InputSource(xml);
org.w3c.dom.Document dom = db.parse(input);
SLDParser sldParser = new SLDParser(styleFactory);
Node rootNode = dom.getDocumentElement();
// we have the SLD component, now we get all the GetMAp components
// step a -- attribute "version"
Node nodeGetMap = rootNode;
if (!(nodeNameEqual(nodeGetMap, "getmap"))) {
if (nodeNameEqual(nodeGetMap, "StyledLayerDescriptor")) //oopsy!! its a SLD POST with get parameters!
{
if (validateSchema) {
validateSchemaSLD(temp, getMapRequest);
}
handlePostGet(rootNode, sldParser, getMapRequest);
return;
}
throw new Exception(
"GetMap XML parser - start node isnt 'GetMap' or 'StyledLayerDescriptor' tag");
}
if (validateSchema) {
validateSchemaGETMAP(temp, getMapRequest);
}
NamedNodeMap atts = nodeGetMap.getAttributes();
Node wmsVersion = atts.getNamedItem("version");
if (wmsVersion == null) {
throw new Exception(
"GetMap XML parser - couldnt find attribute 'version' in GetMap tag");
}
getMapRequest.setVersion(wmsVersion.getNodeValue());
//ignore the OWSType since we know its supposed to be WMS
//step b -bounding box
parseBBox(getMapRequest, nodeGetMap);
// for SLD we already have it (from above) (which we'll handle as layers later)
StyledLayerDescriptor sld = sldParser.parseDescriptor(getNode(rootNode,
"StyledLayerDescriptor"));
processStyles(getMapRequest, sld);
//step c - "Output"
parseXMLOutput(nodeGetMap, getMapRequest); //make this function easier to read
//step d - "exceptions"
getMapRequest.setExceptions(getNodeValue(nodeGetMap, "Exceptions"));
//step e - "VendorType
// we dont actually do anything with this, so...
//step f - rebuild SLD info. Ie. fill in the Layer and Style information, just like SLD post-get
} finally {
if (temp != null) {
temp.delete();
}
}
}
/**
* This is the hybrid SLD POST way. Normal is the GetMap - with a built in
* SLD. The alternate, for stupid people, is the WMS parameters in the
* GET, and the SLD in the post. This handles that case.
*
* @param rootNode
* @param sldParser
* @param getMapRequest
*
* @throws Exception DOCUMENT ME!
*/
private void handlePostGet(Node rootNode, SLDParser sldParser, GetMapRequest getMapRequest)
throws Exception {
//get the GET parmeters
HttpServletRequest request = getMapRequest.getHttpServletRequest();
String qString = request.getQueryString();
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine(new StringBuffer("reading request: ").append(qString).toString());
}
//Map requestParams = KvpRequestReader.parseKvpSet(qString);
Map requestParams = new HashMap();
String paramName;
String paramValue;
for (Enumeration pnames = request.getParameterNames(); pnames.hasMoreElements();) {
paramName = (String) pnames.nextElement();
paramValue = request.getParameter(paramName);
requestParams.put(paramName.toUpperCase(), paramValue);
}
GetMapKvpReader kvpReader = new GetMapKvpReader(requestParams, (WMService) getServiceRef());
String version = kvpReader.getRequestVersion();
getMapRequest.setVersion(version);
kvpReader.parseMandatoryParameters(getMapRequest, false); //false means dont do styles/layers (see below)
kvpReader.parseOptionalParameters(getMapRequest);
//get styles/layers from the sld.
StyledLayerDescriptor sld = sldParser.parseDescriptor(rootNode); //root = <StyledLayerDescriptor>
processStyles(getMapRequest, sld);
}
/**
* taken from the kvp reader, with modifications
*
* @param getMapRequest
* @param sld
*
* @throws Exception DOCUMENT ME!
* @throws WmsException DOCUMENT ME!
*/
private void processStyles(GetMapRequest getMapRequest, StyledLayerDescriptor sld)
throws Exception {
final StyledLayer[] styledLayers = sld.getStyledLayers();
final int slCount = styledLayers.length;
if (slCount == 0) {
throw new WmsException("SLD document contains no layers");
}
final List layers = new ArrayList();
final List styles = new ArrayList();
MapLayerInfo currLayer;
StyledLayer sl = null;
for (int i = 0; i < slCount; i++) {
currLayer = new MapLayerInfo();
sl = styledLayers[i];
String layerName = sl.getName();
if (null == layerName) {
throw new WmsException("A UserLayer without layer name was passed");
}
// TODO: add support for remote WFS here
//handle the InLineFeature stuff
boolean isBaseMap = false;
if ((sl instanceof UserLayer)
&& ((((UserLayer) sl)).getInlineFeatureDatastore() != null)) {
//SPECIAL CASE - we make the temporary version
UserLayer ul = ((UserLayer) sl);
GetMapKvpReader.initializeInlineFeatureLayer(getMapRequest, ul, currLayer);
} else {
//look for a base map layer
String layerGroup = (String) getMapRequest.getWMS().getBaseMapLayers().get( layerName );
if ( layerGroup != null ) {
isBaseMap = true;
List layerGroupExpanded = GetMapKvpReader.parseLayerGroup(layerGroup);
for (Iterator it = layerGroupExpanded.iterator(); it.hasNext();) {
layerName = (String) it.next();
currLayer = new MapLayerInfo();
try {
currLayer.setFeature(GetMapKvpReader.findFeatureLayer(getMapRequest, layerName));
}
catch( Exception e ) {
currLayer.setCoverage(GetMapKvpReader.findCoverageLayer(getMapRequest, layerName));
}
GetMapKvpReader.addStyles(getMapRequest, currLayer, styledLayers[i], layers, styles);
}
}
else {
try {
currLayer.setFeature(GetMapKvpReader.findFeatureLayer(getMapRequest, layerName));
}
catch( Exception e ) {
currLayer.setCoverage(GetMapKvpReader.findCoverageLayer(getMapRequest, layerName));
}
}
}
if (!isBaseMap) {
GetMapKvpReader.addStyles(getMapRequest, currLayer, styledLayers[i], layers, styles);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -