⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 getmapkvpreader.java

📁 电子地图服务器,搭建自己的地图服务
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
			// - }
			// - if (errors.size() != 0)
			// - {
			// - in = new StringBufferInputStream(sldBody);
			// - throw new
			// WmsException(SLDValidator.getErrorMessage(in,errors));
			// - }
		}

		// - InputStream in = new StringBufferInputStream(sldBody);
		// - SLDParser parser = new SLDParser(styleFactory, in);
		Reader reader = getReaderFromString(sldBody);
		SLDParser parser = new SLDParser(styleFactory, reader);
		StyledLayerDescriptor sld = parser.parseSLD();
		parseStyledLayerDescriptor(request, sld);
	}

	/**
	 * Create a reader of the given String. This reader will be used in the
	 * InputSource for the sld parser. The advantage with a reader over a input
	 * stream is that we don't have to consider encoding. The xml declaration
	 * with encoding is ignored using a Reader in parser. The encoding of the
	 * string has been appropiate handled by the servlet when streaming in.
	 * 
	 * @param sldBody
	 *            the sldbody to create a reader of.
	 * @return The created reader
	 * @see Reader
	 */
	private Reader getReaderFromString(String sldBody) {
		return new StringReader(sldBody);
	}

	/**
	 * Gets a sequence of url encoded filters and parses them into Filter
	 * objects that will be set into the request object
	 * 
	 * @param request
	 * @throws WmsException
	 */
	protected void parseFilterParam(GetMapRequest request) throws WmsException {
		String rawFilter = getValue("FILTER");
		String rawCqlFilter = getValue("CQL_FILTER");
		String rawIdFilter = getValue("FEATUREID");

		// in case of a mixed request, get with sld in post body, layers
		// are not parsed, so we can't parse filters neither...
		if (request.getLayers() == null) {
			return;
		}

		int numLayers = request.getLayers().length;

		if (numLayers == 0) {
			throw new RuntimeException(
					"parseFilterParam must be called after the layer list has been built!");
		}

		List filters = null;

		// if no filter, no need to proceed
		if ((rawFilter != null) && !rawFilter.equals("")) {
			try {
				filters = readOGCFilter(rawFilter);
			} catch (ServiceException e) {
				throw new WmsException(e);
			}
		}

		if ((rawIdFilter != null) && !rawIdFilter.equals("")) {
			if (filters != null) {
				throw new WmsException("GetMap KVP request contained "
						+ "conflicting filters.  Filter: " + rawFilter
						+ ", fid: " + rawFilter);
			}

			filters = readFidFilters(rawIdFilter);
		}

		if ((rawCqlFilter != null) && !rawCqlFilter.equals("")) {
			if (filters != null) {
				throw new WmsException("GetMap KVP request contained "
						+ "conflicting filters.  Filter: " + rawFilter
						+ ", fid: " + rawFilter + ", cql: " + rawCqlFilter);
			}

			try {
				filters = readCQLFilter(rawCqlFilter);
			} catch (ServiceException e) {
				throw new WmsException(e);
			}
		}

		if (filters == null) {
			return;
		}

		if (numLayers != filters.size()) {
			// as in wfs getFeatures, perform lenient parsing, if just one
			// filter, it gets
			// applied to all layers
			if (filters.size() == 1) {
				Filter f = (Filter) filters.get(0);
				filters = new ArrayList(numLayers);

				for (int i = 0; i < numLayers; i++) {
					filters.add(f);
				}
			} else {
				String msg = numLayers
						+ " layers requested, but found "
						+ filters.size()
						+ " filters specified. "
						+ "When you specify the FILTER parameter, you must provide just one, \n"
						+ " that will be applied to all layers, or exactly one for each requested layer";
				throw new WmsException(msg, getClass().getName());
			}
		}

		request.setFilters(filters);
	}

	/**
	 * DOCUMENT ME!
	 * 
	 * @param request
	 *            DOCUMENT ME!
	 * 
	 * @throws WmsException
	 *             DOCUMENT ME!
	 */
	protected void parseSldParam(GetMapRequest request) throws WmsException {
		String urlValue = getValue("SLD");

		if (LOGGER.isLoggable(Level.FINE)) {
			LOGGER
					.fine(new StringBuffer(
							"about to load remote SLD document: '").append(
							urlValue).append("'").toString());
		}

		URL sldUrl;

		try {
			sldUrl = new URL(fixURL(urlValue));
		} catch (MalformedURLException e) {
			String msg = new StringBuffer("Creating remote SLD url: ").append(
					e.getMessage()).toString();

			if (LOGGER.isLoggable(Level.WARNING)) {
				LOGGER.log(Level.WARNING, msg, e);
			}

			throw new WmsException(e, msg, "parseSldParam");
		}

		if (getValue("VALIDATESCHEMA") != null) {
			// user requested to validate the schema.
			SLDValidator validator = new SLDValidator();
			List errors = null;

			try {
				// JD: GEOS-420, Wrap the sldUrl in getINputStream method in
				// order
				// to do compression
				InputStream in = getInputStream(sldUrl);
				errors = validator.validateSLD(in, request
						.getHttpServletRequest().getSession()
						.getServletContext());
				in.close();

				if (errors.size() != 0) {
					throw new WmsException(SLDValidator.getErrorMessage(sldUrl
							.openStream(), errors));
				}
			} catch (IOException e) {
				String msg = new StringBuffer("Creating remote SLD url: ")
						.append(e.getMessage()).toString();

				if (LOGGER.isLoggable(Level.WARNING)) {
					LOGGER.log(Level.WARNING, msg, e);
				}

				throw new WmsException(e, msg, "parseSldParam");
			}
		}

		SLDParser parser;

		try {
			// JD: GEOS-420, Wrap the sldUrl in getINputStream method in order
			// to do compression
			parser = new SLDParser(styleFactory, getInputStream(sldUrl));
		} catch (IOException e) {
			String msg = new StringBuffer("Creating remote SLD url: ").append(
					e.getMessage()).toString();

			if (LOGGER.isLoggable(Level.WARNING)) {
				LOGGER.log(Level.WARNING, msg, e);
			}

			throw new WmsException(e, msg, "parseSldParam");
		}

		StyledLayerDescriptor sld = parser.parseSLD();
		parseStyledLayerDescriptor(request, sld);
	}

	/**
	 * URLEncoder.encode does not respect the RFC 2396, so we rolled our own
	 * little encoder. It's not complete, but should work in most cases
	 * 
	 * @param url
	 * @return
	 */
	static String fixURL(String url) {
		StringBuffer sb = new StringBuffer();

		for (int i = 0; i < url.length(); i++) {
			char c = url.charAt(i);

			// From RFC, "Only alphanumerics [0-9a-zA-Z], the special
			// characters "$-_.+!*'(),", and reserved characters used
			// for their reserved purposes may be used unencoded within a URL
			// Here we keep all the good ones, and remove the few uneeded in
			// their
			// ascii range. We also keep / and : to make sure basic URL elements
			// don't get encoded
			if ((c > ' ') && (c < '{') && ("\"\\<>%^[]`+$,".indexOf(c) == -1)) {
				sb.append(c);
			} else {
				sb.append("%").append(Integer.toHexString(c));
			}
		}

		return sb.toString();
	}

	/**
	 * Looks in <code>sld</code> for the layers and styles to use in the map
	 * composition and sets them to the <code>request</code>
	 * 
	 * <p>
	 * If <code>sld</code> is used in "library" mode, that is, the LAYERS
	 * param is also present, saying what layers must be taken in count, then
	 * only the layers from the LAYERS parameter are used and <code>sld</code>
	 * is used as a style library, which means that for each layer requested
	 * through LAYERS=..., if a style if found in it for that layer it is used,
	 * and if not, the layers default is used.
	 * </p>
	 * 
	 * <p>
	 * By the other hand, if the LAYERS parameter is not present all the layers
	 * found in <code>sld</code> are setted to <code>request</code>.
	 * </p>
	 * 
	 * @param request
	 *            the GetMap request to which to set the layers and styles
	 * @param sld
	 *            a SLD document to take layers and styles from, following the
	 *            "literal" or "library" rule.
	 * 
	 * @throws WmsException
	 *             if anything goes wrong
	 * @throws RuntimeException
	 *             DOCUMENT ME!
	 */
	private void parseStyledLayerDescriptor(final GetMapRequest request,
			final StyledLayerDescriptor sld) throws WmsException {
		MapLayerInfo[] libraryModeLayers = null;

		if (null != getValue("LAYERS")) {
			if (LOGGER.isLoggable(Level.INFO)) {
				LOGGER.info("request comes in \"library\" mode");
			}

			libraryModeLayers = parseLayersParam(request);
		}

		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 = null;
		Style currStyle = null;

		if (null != libraryModeLayers) {
			int lCount = libraryModeLayers.length;

			for (int i = 0; i < lCount; i++) {
				currLayer = libraryModeLayers[i];

				if (currLayer.getType() == MapLayerInfo.TYPE_VECTOR) {
					currStyle = findStyleOf(request, currLayer.getFeature(),
							styledLayers);
				} else if (currLayer.getType() == MapLayerInfo.TYPE_RASTER) {
					try {
						currStyle = findStyleOf(request,
								currLayer.getFeature(), styledLayers);
					} catch (WmsException wm) {
						currStyle = findStyleOf(request,
								currLayer.getFeature(), styledLayers);
						if (currStyle == null) {
							// nope, there's no default raster style. Give up.
							throw new WmsException(
									wm.getMessage()
											+ "  Also tried to use "
											+ "the generic raster style 'raster', but it wasn't available.");
						}
					}
				}

				layers.add(currLayer);
				styles.add(currStyle);
			}
		} else {
			StyledLayer sl = null;
			String layerName;
			UserLayer ul;

			for (int i = 0; i < slCount; i++) {
				sl = styledLayers[i];
				layerName = sl.getName();

				if (null == layerName) {
					throw new WmsException(
							"A UserLayer without layer name was passed");
				}

				currLayer = new MapLayerInfo();

				// handle the InLineFeature stuff
				// TODO: add support for remote WFS here
				if ((sl instanceof UserLayer)
						&& ((((UserLayer) sl)).getInlineFeatureDatastore() != null)) {
					// SPECIAL CASE - we make the temporary version
					ul = ((UserLayer) sl);

					try {
						initializeInlineFeatureLayer(request, ul, currLayer);
					} catch (Exception e) {
						throw new WmsException(e);
					}
				} else {
					try {
						currLayer.setFeature(GetMapKvpReader.findFeatureLayer(
								request, layerName));
					} catch (WmsException e) {
						currLayer.setCoverage(GetMapKvpReader
								.findCoverageLayer(request, layerName));
					}
				}

				if (currLayer.getType() == MapLayerInfo.TYPE_VECTOR) {
					// currStyle = findStyleOf(request, currLayer,
					// styledLayers); // DJB: this looks like a bug, we should
					// get the style from styledLayers[i]

					// the correct thing to do its grab the style from
					// styledLayers[i]
					// inside the styledLayers[i] will either be :
					// a) nothing - in which case grab the layer's default style
					// b) a set of:
					// i) NameStyle -- grab it from the pre-loaded styles
					// ii)UserStyle -- grab it from the sld the user uploaded
					//
					// NOTE: we're going to get a set of layer->style pairs for
					// (b).
					addStyles(request, currLayer, styledLayers[i], layers,
							styles);
				} else if (currLayer.getType() == MapLayerInfo.TYPE_RASTER) {
					try {
						addStyles(request, currLayer, styledLayers[i], layers,
								styles);
					} catch (WmsException wm) {
						// hmm, well, the style they specified in the wms
						// request
						// wasn't found. Let's try the default raster style
						// named 'raster'
						currStyle = findStyle(request, "raster");
						if (currStyle == null) {
							// nope, there's no default raster style. Give up.
							throw new WmsException(
									wm.getMessage()
											+ "  Also tried to use "
											+ "the generic raster style 'raster', but it wasn't available.");
						}
						layers.add(currLayer);
						styles.add(currStyle);
					}
				}
			}
		}

		request.setLayers((MapLayerInfo[]) layers
				.toArray(new MapLayerInfo[layers.size()]));
		request.setStyles(styles);
	}

	/**
	 * the correct thing to do its grab the style from styledLayers[i] inside
	 * the styledLayers[i] will either be : a) nothing - in which case grab the
	 * layer's default style b) a set of: i) NameStyle -- grab it from the
	 * pre-loaded styles ii)UserStyle -- grab it from the sld the user uploaded
	 * 
	 * NOTE: we're going to get a set of layer->style pairs for (b). these are
	 * added to layers,styles
	 * 
	 * NOTE: we also handle some featuretypeconstraints
	 * 
	 * @param request
	 * @param currLayer
	 * @param layer
	 * @param layers
	 * @param styles
	 */
	public static void addStyles(GetMapRequest request, MapLayerInfo currLayer,
			StyledLayer layer, List layers, List styles) throws WmsException {
		if (currLayer == null) {
			return; // protection
		}

		Style[] layerStyles = null;
		FeatureTypeConstraint[] ftcs = null;

		if (layer instanceof NamedLayer) {
			ftcs = ((NamedLayer) layer).getLayerFeatureConstraints();
			layerStyles = ((NamedLayer) layer).getStyles();
		} else if (layer instanceof UserLayer) {
			ftcs = ((UserLayer) layer).getLayerFeatureConstraints();
			layerStyles = ((UserLayer) layer).getUserStyles();
		}

		// DJB: TODO: this needs to do the whole thing, not just names
		if (ftcs != null) {
			FeatureTypeConstraint ftc;
			final int length = ftcs.length;

			for (int t = 0; t < length; t++) {
				ftc = ftcs[t];

				if (ftc.getFeatureTypeName() != null) {
					String ftc_name = ftc.getFeatureTypeName();

					// taken from lite renderer
					boolean matches;

					try {
						matches = currLayer.getFeature().getFeatureType()
								.isDescendedFrom(null, ftc_name)
								|| currLayer.getFeature().getFeatureType()
										.getTypeName().equalsIgnoreCase(
												ftc_name);
					} catch (Exception e) {
						matches = false; // bad news

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -