Package com.bbn.openmap.image.wms

Source Code of com.bbn.openmap.image.wms.WmsRequestHandler

/*
* $Header: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/image/wms/WmsRequestHandler.java,v 1.1.2.8 2008/10/16 03:30:57 dietrick Exp $
*
* Copyright 2001-2005 OBR Centrum Techniki Morskiej, All rights reserved.
*
*/
package com.bbn.openmap.image.wms;

import java.awt.Paint;
import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Pattern;

import com.bbn.openmap.LatLonPoint;
import com.bbn.openmap.Layer;
import com.bbn.openmap.event.ProjectionEvent;
import com.bbn.openmap.image.ImageFormatter;
import com.bbn.openmap.image.ImageServer;
import com.bbn.openmap.image.ImageServerConstants;
import com.bbn.openmap.image.ImageServerUtils;
import com.bbn.openmap.image.MapRequestFormatException;
import com.bbn.openmap.layer.util.http.HttpConnection;
import com.bbn.openmap.layer.util.http.IHttpResponse;
import com.bbn.openmap.omGraphics.OMColor;
import com.bbn.openmap.proj.AspectRatioProjection;
import com.bbn.openmap.proj.Proj;
import com.bbn.openmap.proj.ProjectionFactory;
import com.bbn.openmap.proj.coords.CoordinateReferenceSystem;
import com.bbn.openmap.util.Debug;
import com.bbn.openmap.util.PropUtils;

/**
* @version $Header:
*          /cvs/CVS_LEBA/external/openmap/openmap/src/openmap/com/bbn/openmap/wms/WmsRequestHandler.java,v
*          1.2 2006/03/27 10:51:13 tomrak Exp $
* @author Adam Dawidowski
* @author wachu
* @author pitek
*/
public class WmsRequestHandler extends ImageServer implements ImageServerConstants {

    /**
     */
    private CapabilitiesSupport capabilities;

    private Map wmsLayerByName = new HashMap();
   
    private List wmsLayers = new ArrayList();

    private WmsLayerFactory wmsLayerFactory;
   
    private Map imageFormatterByContentType = new HashMap();

    /**
     * Creates a new WmsRequestHandler object.
     *
     * @param port
     * @param props Properties from openmap.properties
     * @param mapLayerHandler
     * @param wmsLayersMap
     * @throws IOException
     */
    public WmsRequestHandler(String wmsScheme, String wmsHostName, int wmsPort, String wmsUrlPath,
            Properties props) throws IOException, WMSException {

        super(props);
        setProperties(null, props);
       
        // separate antialias property for wms.
        boolean antialias = PropUtils.booleanFromProperties(props, "openmap.wms."
                + AntiAliasingProperty, false);
        setDoAntiAliasing(antialias);

        // for each Openmap Layer created by ImageServer (defined in properties)
        // create corresponding IWmsLayer which contains all neccesary
        // information required by
        // WMS (e.g getCapabilities method)
        wmsLayerFactory = new WmsLayerFactory(props);
        createWmsLayers();
       
        // create a Map of all formatters by their contentType
        for (Iterator it = getFormatters().values().iterator(); it.hasNext();) {
            ImageFormatter formatter = (ImageFormatter) it.next();
            imageFormatterByContentType.put(formatter.getContentType(), formatter);
        }
       
        // read from configuration fixed part of Capabilities Document returned
        // in getCapabilities method
        capabilities = new CapabilitiesSupport(props, wmsScheme, wmsHostName, wmsPort, wmsUrlPath);
        List formatsList = new ArrayList(imageFormatterByContentType.keySet());
        capabilities.setFormats(CapabilitiesSupport.FMT_GETMAP, formatsList);
    }

    /**
     * For each layer managed by ImageServer create corresponding IWmsLayer
     * which contains additional information for WMS service about given openmap
     * layer.
     *
     * For Layers that already implement IWmsLayer, the instances will be the same.
     */
    protected void createWmsLayers() {
        wmsLayerByName.clear();
        wmsLayers.clear();
        for (int i = 0; i < layers.length; i++) {
            Layer layer = layers[i];
            createWmsLayers(wmsLayerFactory.createWmsLayer(layer));
        }
    }
   
    private void createWmsLayers(IWmsLayer layer) {
        wmsLayerByName.put(layer.getWmsName(), layer);
        wmsLayers.add(layer);
        if (layer instanceof IWmsNestedLayer) {
            IWmsNestedLayer n = (IWmsNestedLayer) layer;
            if (n.getNestedLayers() != null) {
                for (int i = 0; i < n.getNestedLayers().length; i++) {
                    createWmsLayers(n.getNestedLayers()[i]);
                }
            }
        }
    }
   
    /**
     * Set the request parameters on all the layers
     *
     * @see IWmsLayer#setRequestParameters(Properties)
     * @param requestProperties
     */
    protected void setRequestParametersOnLayers(Properties requestProperties) {
        // use a Set to make sure we only set it once for each layer
        Set handledNames = new HashSet();
        for (Iterator it = wmsLayers.iterator(); it.hasNext();) {
            IWmsLayer wmsLayer = (IWmsLayer) it.next();
            if (!handledNames.contains(wmsLayer.getWmsName())) {
                wmsLayer.setRequestParameters(requestProperties);
                handledNames.add(wmsLayer.getWmsName());
            }
            if (wmsLayer instanceof IWmsNestedLayer) {
                IWmsNestedLayer nestedLayer = (IWmsNestedLayer) wmsLayer;
                // make sure the top layer also get info about the request parameters
                if (!handledNames.contains(nestedLayer.getTopLayer().getWmsName())) {
                    nestedLayer.getTopLayer().setRequestParameters(requestProperties);
                    handledNames.add(nestedLayer.getTopLayer().getWmsName());
                }
            }
        }
    }
   
    protected IWmsLayer getLayerByName(String wmsName) {
        return (IWmsLayer) wmsLayerByName.get(wmsName);
    }

    /**
     * Return the top OpenMap {@link Layer} for the given wms layer name.
     *
     * @param name
     * @return
     */
    protected Layer getTopLayerByName(String wmsName) {
        IWmsLayer layer = getLayerByName(wmsName);
        if (layer == null) {
            return null;
        }
        if (layer instanceof IWmsNestedLayer) {
            layer = ((IWmsNestedLayer) layer).getTopLayer();
        }
        if (layer instanceof DefaultLayerAdapter) {
            return ((DefaultLayerAdapter) layer).layer;
        }
        if (layer instanceof Layer) {
            return (Layer) layer;
        }
        throw new IllegalStateException("Top layer must be a OpenMap Layer, not " + layer.getClass());
    }
   
    /**
     * @param request
     * @param out
     * @throws IOException
     * @throws MapRequestFormatException
     */
    public void handleRequest(Properties requestProperties, IHttpResponse httpResponse)
            throws IOException, MapRequestFormatException {
        try {
            String requestType = requestProperties.getProperty(REQUEST);
            checkRequest(requestProperties);
            if (requestType == null) {
                throw new WMSException("Missing REQUEST type parameter");
            }
            setRequestParametersOnLayers(requestProperties);
            if (requestType.equalsIgnoreCase(GETMAP)) {
                Debug.message("ms", "OGCMRH: GetMap request...");
                handleGetMapRequest(requestProperties, httpResponse);
            } else if (requestType.equals(GETCAPABILITIES)) {
                Debug.message("ms", "OGCMRH: GetCapabilities request...");
                handleGetCapabilitiesRequest(requestProperties, httpResponse);
            } else if (requestType.equalsIgnoreCase(GETFEATUREINFO)) {
                Debug.message("ms", "OGCMRH: GetFeatureInfo request...");
                handleGetFeatureInfoRequest(requestProperties, httpResponse);
            } else {
                throw new WMSException("Invalid REQUEST parameter: " + requestType,
                        WMSException.OPERATIONNOTSUPPORTED);
            }
        } catch (WMSException e) {
            Debug.output("WMSException(" + e.getCode() + "): " + e.getMessage());
            httpResponse.writeHttpResponse("application/vnd.ogc.se_xml", e.getXML());
        }
    }

    /**
     * @param requestProperties
     * @param out
     * @throws IOException
     * @throws MapRequestFormatException
     * @throws WMSException
     */
    public void handleGetMapRequest(Properties requestProperties, IHttpResponse httpResponse)
            throws IOException, MapRequestFormatException, WMSException {
        byte[] image = handleGetMapRequest(requestProperties);
        if (Debug.debugging("imageserver")) {
            Debug.output("OGCMRH: have completed image, size " + image.length);
        }
        String contentType = getFormatter().getContentType();
        if (contentType == null) {
            contentType = HttpConnection.CONTENT_PLAIN;
        }
        httpResponse.writeHttpResponse(contentType, image);
    }

    /**
     * @param requestProperties
     * @return
     * @throws IOException
     * @throws MapRequestFormatException
     * @throws WMSException
     */
    public byte[] handleGetMapRequest(Properties requestProperties) throws IOException,
            MapRequestFormatException, WMSException {
        GetMapRequestParameters parameters = new GetMapRequestParameters();

        checkFormat(requestProperties, parameters);
        setFormatter(parameters.formatter);

        checkBackground(requestProperties, parameters);
        Paint bgPaint = parameters.background;

        checkProjectionType(requestProperties, parameters);
        checkBoundingBox(requestProperties, parameters);
        Proj projection = createProjection(requestProperties, parameters);
       
        checkLayersAndStyles(requestProperties, parameters);

        Debug.message("ms", "handleGetMapRequest: createImage layers:" + parameters.topLayerNames.toString());
        return createImage(projection, parameters.width, parameters.height, parameters.topLayerNames, bgPaint);
    }

    /**
     * @param requestProperties
     * @param out
     * @throws IOException
     * @throws MapRequestFormatException
     * @throws WMSException
     */
    public void handleGetCapabilitiesRequest(Properties requestProperties,
            IHttpResponse httpResponse) throws IOException, MapRequestFormatException, WMSException {
        String response = handleGetCapabilitiesRequest(requestProperties);
        httpResponse.writeHttpResponse(HttpConnection.CONTENT_XML, response.getBytes("UTF-8"));
    }

    /**
     * @param requestProperties
     * @return
     * @throws IOException
     * @throws MapRequestFormatException
     * @throws WMSException
     */
    public String handleGetCapabilitiesRequest(Properties requestProperties) throws IOException,
            MapRequestFormatException, WMSException {

        String format = requestProperties.getProperty(FORMAT);
        if (format != null && !format.equals("application/vnd.ogc.wms_xml")) {
            throw new WMSException("Invalid FORMAT parameter.", WMSException.INVALIDFORMAT);
        }

        Layer[] layers = getLayers();
        for (int i = 0; i < layers.length; i++) {
            if (layers[i].getPropertyPrefix() != null) {
                capabilities.addLayer(wmsLayerFactory.createWmsLayer(layers[i]));
            }
        }
       
        try {
            return capabilities.generateXMLString();
        } catch (Exception e) {
            e.printStackTrace();
            // nie ma takiego kodu b��du, ale s�dz�, �e powinien by�
            throw new WMSException("Unable to compile a response due to server misconfiguration.",
                    WMSException.INTERNALERROR);
        }
    }

    /**
     * @param requestProperties
     * @param out
     * @throws IOException
     * @throws MapRequestFormatException
     * @throws WMSException
     */
    public void handleGetFeatureInfoRequest(Properties requestProperties, IHttpResponse httpResponse)
            throws IOException, MapRequestFormatException, WMSException {
       
        String contentType = requestProperties.getProperty(INFO_FORMAT);
        String content = handleGetFeatureInfoRequest(requestProperties);
       
        byte[] contentBytes = content.getBytes("UTF-8");
       
        httpResponse.writeHttpResponse(contentType, contentBytes);
    }

    /**
     * <ul>
     * <li>VERSION - checked
     * <li>REQUEST - checked
     * <li>EXCEPTIONS - checked
     * <li>all from <code>GetMap</code> except VERSION and REQUEST
     * <li>QUERY_LAYERS - specific
     * <li>INFO_FORMAT - specific
     * <li>FEATURE_COUNT - specific
     * <li>I,J - specific
     * </ul>
     *
     * @param requestProperties
     * @return
     * @throws IOException
     * @throws MapRequestFormatException
     * @throws WMSException
     */
    public String handleGetFeatureInfoRequest(Properties requestProperties) throws IOException,
            MapRequestFormatException, WMSException {
       
        GetFeatureInfoRequestParameters parameters = new GetFeatureInfoRequestParameters();
       
        checkFormat(requestProperties, parameters);
        setFormatter(parameters.formatter);
        checkBackground(requestProperties, parameters);
        checkProjectionType(requestProperties, parameters);
        checkBoundingBox(requestProperties, parameters);
        checkFeatureInfoPoint(requestProperties, parameters);
       
        checkLayersAndStyles(requestProperties, parameters);
        checkQueryLayers(requestProperties, parameters);
        checkInfoFormat(requestProperties, parameters);

        Proj projection = createProjection(requestProperties, parameters);
       
        // TODO: get a user defined FeatureInfoResponse
        FeatureInfoResponse featureInfoResponse = null;
        if (featureInfoResponse == null) {
            // TODO: log that user defined was not found
            featureInfoResponse = new DefaultFeatureInfoResponse();
        }
       
        for(Iterator it = parameters.queryLayerNames.iterator(); it.hasNext();){
            String queryLayerName = (String)it.next();
           
            IWmsLayer wmslayer = (IWmsLayer) wmsLayerByName.get(queryLayerName);
            Layer layer = getTopLayerByName(queryLayerName);
           
            layer.setProjection(new ProjectionEvent(this, projection));
           
            LayerFeatureInfoResponse layerResponse = wmslayer.query(parameters.x, parameters.y);
            featureInfoResponse.add(layerResponse);
        }
       
        StringBuffer out = new StringBuffer();
        featureInfoResponse.output(parameters.infoFormat, out);
        return out.toString();
    }

    /**
     * @todo ta metoda pokrywa odpowiednik z klasy bazowej i zwraca rysunek,
     *       kt�ry nie jest przeskalowywany. To mo�e by� problem. Przeskalowanie
     *       zosta�o zablokowane, poniewa� tworzy�o rysunek bez kana�u alfa, a
     *       przynajmniej na to wygl�da�o.
     * @param formatter
     * @param scaledWidth
     * @param scaledHeight
     * @return
     */
    protected byte[] getFormattedImage(ImageFormatter formatter, int scaledWidth, int scaledHeight) {
        Debug.message("imageserver", "ImageServer: using full scale image (unscaled).");
        byte[] formattedImage = formatter.getImageBytes();
        return formattedImage;
    }

    /**
     * @param requestProperties
     * @throws WMSException
     */
    private void checkRequest(Properties requestProperties) throws WMSException {
        String version = requestProperties.getProperty(VERSION);
        String service = requestProperties.getProperty(SERVICE);
        String requestType = requestProperties.getProperty(REQUEST);

        boolean getcaps = ((requestType != null) && requestType.equals(GETCAPABILITIES));
        if (!getcaps) {
            // check version string - use a default for clients that does not
            // specify
            if (version == null) {
                version = "1.1.1";
                Debug.message("wms", "missing version string. use " + version);
            }
            // TODO: handle other versions?
            if (!version.equals("1.1.1")) {
                throw new WMSException("Unsupported protocol version: " + version);
            }
            String ex = requestProperties.getProperty(EXCEPTIONS);
            // if ((ex != null) && !ex.equals("application/vnd.ogc.se_xml")) {
            // Poprawka wacha
            // poni�szy warunek roszszerzy�em o application/vnd.ogc.se_inimage
            // gdy� WMSplugin wymaga tego formatu exception'�w , kt�ry jest
            // formatem opcjonalnym dla WMS
            if ((ex != null)
                    && (!ex.equals("application/vnd.ogc.se_inimage") && !ex
                            .equals("application/vnd.ogc.se_xml"))) {
                throw new WMSException("Invalid EXCEPTIONS value: " + ex);
            }
        } else {
            if ((service == null) || !service.equals("WMS")) {
                throw new WMSException("Unsupported service name: " + service);
            }
        }
    }

    /**
     * @param requestProperties
     * @param parameters
     * @throws WMSException
     */
    private void checkProjectionType(Properties requestProperties,
            GetMapRequestParameters parameters) throws WMSException {
        String strSRS = requestProperties.getProperty(SRS);
        if (strSRS == null) {
            // wms 1.3.0 uses CRS parameter instead of SRS
            strSRS = requestProperties.getProperty(CRS);
        }
        if (strSRS == null) {
            throw new WMSException("Missing SRS parameter.");
        }
       
        System.out.println("crs: " + strSRS);
        CoordinateReferenceSystem crs = CoordinateReferenceSystem.getForCode(strSRS);
        if (crs == null) {
            throw new WMSException("Invalid SRS/CRS parameter: " + strSRS, WMSException.INVALIDSRS);
        }
        parameters.crs = crs;
    }

    /**
     * To w og�lno�ci powinno zale�e� od typu porojekcji.
     *
     * @param requestProperties
     * @param parameters
     * @throws WMSException
     */
    private void checkBoundingBox(Properties requestProperties, GetMapRequestParameters parameters)
            throws WMSException {
        String strWidth = requestProperties.getProperty(WIDTH);
        if (strWidth == null) {
            throw new WMSException("Missing WIDTH parameter.", WMSException.MISSINGDIMENSIONVALUE);
        }
        String strHeight = requestProperties.getProperty(HEIGHT);
        if (strHeight == null) {
            throw new WMSException("Missing HEIGHT parameter.", WMSException.MISSINGDIMENSIONVALUE);
        }
        String strBBox = requestProperties.getProperty(BBOX);
        if (strBBox == null) {
            throw new WMSException("Missing BBOX parameter.", WMSException.MISSINGDIMENSIONVALUE);
        }
        String[] arrayBBox = strBBox.split(",");
        if (arrayBBox.length != 4) {
            throw new WMSException(
                    "Invalid BBOX parameter. BBOX must contain exactly 4 values separated with comas.",
                    WMSException.INVALIDDIMENSIONVALUE);
        }

        try {
            // BBOX is minx, miny, maxx, maxy
            double minX = Double.parseDouble(arrayBBox[0]);
            double minY = Double.parseDouble(arrayBBox[1]);
            double maxX = Double.parseDouble(arrayBBox[2]);
            double maxY = Double.parseDouble(arrayBBox[3]);
            double medX = ((maxX - minX) / 2d) + minX;
            double medY = ((maxY - minY) / 2d) + minY;

            // use CRS to convert BBOX to latlon values
            CoordinateReferenceSystem crs = parameters.crs;
            parameters.bboxLatLonMinXY = crs.inverse(minX, minY);
            parameters.bboxLatLonMaxXY = crs.inverse(maxX, maxY);
            parameters.bboxLatLonCenter = crs.inverse(medX, medY);

            // TODO: use CRS to check value validity?
        } catch (NumberFormatException e) {
            throw new WMSException(
                    "Invalid BBOX parameter. BBOX parameter must be in the form of minx, miny, maxx, maxy"
                            + " confirming to the selected SRS/CRS.",
                    WMSException.INVALIDDIMENSIONVALUE);
        }
        parameters.width = 0;
        try {
            parameters.width = Integer.parseInt(strWidth);
            if (parameters.width <= 0) {
                throw new WMSException("Invalid values encountered while parsing WIDTH parameter.");
            }
            // Debug.output("intWidth = " + intWidth);
        } catch (NumberFormatException e) {
            throw new WMSException("Invalid values encountered while parsing WIDTH parameter.");
        }
        parameters.height = 0;
        try {
            parameters.height = Integer.parseInt(strHeight);
            if (parameters.height <= 0) {
                throw new WMSException("Invalid value encountered while parsing HEIGHT parameter.");
            }
            // Debug.output("intHeight = " + intHeight);
        } catch (NumberFormatException e) {
            throw new WMSException("Invalid value encountered while parsing HEIGHT parameter.");
        }
    }
   
    private void checkLayersAndStyles(Properties requestProperties, GetMapRequestParameters parameters)
            throws WMSException {
        String strLayers = requestProperties.getProperty(LAYERS);
        if (strLayers == null) {
            throw new WMSException("LAYERS not specified.", WMSException.LAYERNOTDEFINED);
        }
        if (Debug.debugging("imageserver")) {
            Debug.output("OGCMRH.checkLayersAndStyles: requested layers >> " + strLayers);
        }
        String[] layers_in = strLayers.replace('\"', '\0').split(",", -1);
        // ... i style
        String strStyles = requestProperties.getProperty(STYLES);
        String[] styles_in = null;
        if (strStyles != null) {
            styles_in = strStyles.replace('\"', '\0').split(",", -1);
           
            // wms-1.1.1 7.2.3.4. "If all layers are
            // to be shown using the default style, either the form "STYLES=" or
            // "STYLES=,,," is valid."
            if (strStyles.equals("")) {
                styles_in = new String[layers_in.length];
                Arrays.fill(styles_in, "");
            }
           
            if (styles_in.length != layers_in.length) {
                throw new WMSException(
                        "Number of specified styles does not match the number of specified layers.");
            }
        }
       
        parameters.topLayerNames.clear();
        parameters.layerNames.clear();
       
        // odwr�ci� kolejno�� warstw, bo WMS powinien renderowa� pierwsz�
        // warstw� na samym dole, drug� wy�ej itd
        // imageserver renderuje w odwrotnej kolejno�ci
        // przy okazji sprawdzi�, czy podane warstwy istniej�
        for (int i = layers_in.length - 1; i >= 0; i--) {
            String layerName = layers_in[i];
           
            IWmsLayer wmsLayer = (IWmsLayer) wmsLayerByName.get(layerName);
            if (wmsLayer == null) {
                throw new WMSException("Unknown layer specified (" + layerName + ").",
                        WMSException.LAYERNOTDEFINED);
            }
           
            if (wmsLayer instanceof IWmsNestedLayer) {
                IWmsNestedLayer nestedLayer = (IWmsNestedLayer) wmsLayer;
                String topLayerName = nestedLayer.getTopLayer().getWmsName();
                if (!parameters.topLayerNames.contains(topLayerName)) {
                    parameters.topLayerNames.add(topLayerName);
                }
                nestedLayer.setIsActive(true);
            } else {
                if (!parameters.topLayerNames.contains(layerName)) {
                    parameters.topLayerNames.add(layerName);
                }
            }
           
            // apply style to layer
            if (styles_in == null) {
                wmsLayer.setDefaultStyle();
            } else {
                String styleName = styles_in[i];
                if (styleName.equals("")) {
                    wmsLayer.setDefaultStyle();
                } else if (wmsLayer.isStyleSupported(styleName)) {
                    wmsLayer.setStyle(styleName);
                } else {
                    throw new WMSException("Unknown style specified (" + styleName + ").",
                            WMSException.STYLENOTDEFINED);
                }
            }

            parameters.layerNames.add(layerName);
        }
        if (parameters.layerNames.isEmpty()) {
            throw new WMSException("LAYERS not specified.", WMSException.LAYERNOTDEFINED);
        }
    }
   
    private void checkQueryLayers(Properties requestProperties,
            GetFeatureInfoRequestParameters parameters) throws WMSException {

        String strLayers = requestProperties.getProperty(QUERY_LAYERS);
        if (strLayers == null) {
            throw new WMSException("QUERY_LAYERS not specified.", WMSException.LAYERNOTDEFINED);
        }
        if (Debug.debugging("imageserver")) {
            Debug.output("OGCMRH.checkQueryLayers: requested layers >> " + strLayers);
        }
        String[] layers_in = strLayers.replace('\"', '\0').split(",", -1);

        parameters.queryLayerNames.clear();

        for (int i = 0; i < layers_in.length; i++) {
            String layerName = layers_in[i];
           
            if(!parameters.layerNames.contains(layerName)){
                throw new WMSException("Layers missing Query Layer " + layerName + ".",
                        WMSException.LAYERNOTDEFINED);
            }

            IWmsLayer layer = (IWmsLayer)wmsLayerByName.get(layerName);
            if(layer == null){
                throw new WMSException("Could not find layer " + layerName);
            }
           
            if(!layer.isQueryable()){
                throw new WMSException("Layer " + layerName + " is not queryable");
            }
           
            parameters.queryLayerNames.add(layerName);
        }

    }
   

    /**
     * Create and return a Projection object based on the wms request parameters.
     *
     * @param requestProperties
     * @param parameters
     * @return
     * @throws WMSException
     */
    private Proj createProjection(Properties requestProperties, GetMapRequestParameters parameters)
            throws WMSException {
       
        Properties projProps = new Properties();
        projProps.put(ProjectionFactory.CENTER, new LatLonPoint(0f, 0f));
        projProps.setProperty(ProjectionFactory.WIDTH, Integer.toString(parameters.width));
        projProps.setProperty(ProjectionFactory.HEIGHT, Integer.toString(parameters.height));
       
        Proj projection = parameters.crs.createProjection(projProps);
        parameters.crs.prepareProjection(projection);
        projection.setScale(projection.getMinScale());

        LatLonPoint llp1 = parameters.bboxLatLonMinXY;
        LatLonPoint llp2 = parameters.bboxLatLonMaxXY;
        System.out.println("bbox toLatLon: 1: " + llp1 + ", 2: " + llp2 + ", center: " + parameters.bboxLatLonCenter);
       
        // guess a center value
        // TODO: calculate this from bbox values instead of after latlon converting?
        //float centerLat = ((llp2.getLatitude() - llp1.getLatitude()) / 2) + llp1.getLatitude();
        //float centerLon = ((llp2.getLongitude() - llp1.getLongitude()) / 2) + llp1.getLongitude();
        //projection.setCenter(centerLat, centerLon);
        projection.setCenter(parameters.bboxLatLonCenter);
       
        // Debug.output("L1: " + llp1.toString()+", L2: " + llp2.toString();
        // TODO: need to set projection.center before using the projection

        int intnewwidth = parameters.width;
        int intnewheight = parameters.height;
       
        float newscale = projection.getScale(llp1, llp2, new Point(0, 0), new Point(intnewwidth,
                intnewheight));
        projection.setScale(newscale);

        // OGC 01-068r3 (wms 1.1.1) 7.2.3.8. "In the case where the aspect ratio
        // of the BBOX and the ratio width/height are different, the WMS shall
        // stretch the returned map so that the resulting
        // pixels could themselves be rendered in the aspect ratio of the BBOX"
        Point xyp1 = projection.forward(llp1);
        Point xyp2 = projection.forward(llp2);
        int w = xyp2.x - xyp1.x;
        int h = xyp1.y - xyp2.y;
        if (Math.abs(w - parameters.width) > 2 || Math.abs(h - parameters.height) > 2) {
            Debug.output("use aspect ratio fix");
            projection.setWidth(w);
            projection.setHeight(h);
            projection.setCenter(parameters.bboxLatLonCenter);
            float underlyingScale = projection.getScale(llp1, llp2, new Point(0, 0),
                    new Point(w, h));
            projection.setScale(underlyingScale);
            AspectRatioProjection p = new AspectRatioProjection(projection, parameters.width,
                    parameters.height);
            projection = p;
        }
       
        return projection;
    }

    /**
     * @param requestProperties
     * @param parameters
     * @throws WMSException
     */
    private void checkFormat(Properties requestProperties, GetMapRequestParameters parameters)
            throws WMSException {
        String format = requestProperties.getProperty(FORMAT);

        // hack to handle WMS clients like ArcGIS 9.2 that are issuing
        // GetFeatureInfo without FORMAT parameter
        if ((format == null) && (parameters instanceof GetFeatureInfoRequestParameters)) {
            parameters.formatter = (ImageFormatter) getFormatters().values().iterator().next();
            format = parameters.formatter.getContentType();
        }
       
        // tu zbada� podany format i ewentualnie rzuci� WMSException
        if (format == null) {
            throw new WMSException("Missing FORMAT parameter.", WMSException.INVALIDFORMAT);
        }
       
        parameters.formatter = (ImageFormatter) imageFormatterByContentType.get(format);
        if (parameters.formatter == null) {
            throw new WMSException("Invalid FORMAT parameter: " + format,
                    WMSException.INVALIDFORMAT);
        }
    }
   
    private void checkFeatureInfoPoint(Properties requestProperties,
            GetFeatureInfoRequestParameters parameters) throws WMSException {

        parameters.x = -1;
        parameters.y = -1;
       
        try {
            parameters.x = Integer.parseInt(requestProperties.getProperty(X));
        } catch (NumberFormatException e) {
            throw new WMSException("Invalid X parameter: " + requestProperties.getProperty(X),
                    WMSException.INVALIDPOINT);
        }

        try {
            parameters.y = Integer.parseInt(requestProperties.getProperty(Y));
        } catch (NumberFormatException e) {
            throw new WMSException("Invalid Y parameter: " + requestProperties.getProperty(Y),
                    WMSException.INVALIDPOINT);
        }
    }
   
    private void checkInfoFormat(Properties requestProperties,
            GetFeatureInfoRequestParameters parameters) throws WMSException {
       
       
        Collection okFormats = Arrays.asList(new String[] { HttpConnection.CONTENT_PLAIN,
                HttpConnection.CONTENT_HTML });
       
        String format = requestProperties.getProperty(INFO_FORMAT);
        if (!okFormats.contains(format)) {
            // TODO: use correct message!
            throw new WMSException("Invalid value for " + INFO_FORMAT + ": "
                    + requestProperties.getProperty(INFO_FORMAT));
        }
       
        parameters.infoFormat = format;
    }

    /**
     * @param requestProperties
     * @param parameters
     * @throws WMSException
     */
    private void checkBackground(Properties requestProperties, GetMapRequestParameters parameters)
            throws WMSException {
        String test = requestProperties.getProperty(TRANSPARENT);
        if ((test != null)
                && (test.equals("0") && test.equals("1") && test.equalsIgnoreCase("TRUE") && test
                        .equalsIgnoreCase("FALSE"))) {
            throw new WMSException(
                    "Invalid TRANSPARENT format. Please specify a boolean value (0,1,FALSE,TRUE)");
        }
        test = requestProperties.getProperty(BGCOLOR);
        if ((test != null) && !Pattern.matches("0x[0-9a-fA-F]{6}", test)) {
            throw new WMSException("Invalid BGCOLOR format. Please specify an hexadecimal"
                    + " number in the form 0xXXXXXX, where X is a hexadecimal digit (0..9,A-F)");
        }
        parameters.background = ImageServerUtils.getBackground(requestProperties, OMColor.clear);
    }

}
TOP

Related Classes of com.bbn.openmap.image.wms.WmsRequestHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.