Changeset 397

Show
Ignore:
Timestamp:
09/11/08 18:10:57 (4 months ago)
Author:
arneke
Message:

Adding proxy capability for WMS requests that are not GetMap?

Location:
trunk/geowebcache/src/main
Files:
1 added
3 modified

Legend:

Unmodified
Added
Removed
  • trunk/geowebcache/src/main/java/org/geowebcache/service/wms/WMSService.java

    r388 r397  
    1818package org.geowebcache.service.wms; 
    1919 
    20 import java.io.BufferedReader; 
    21 import java.io.IOException; 
    22 import java.io.InputStream; 
    23 import java.io.InputStreamReader; 
    24 import java.io.OutputStream; 
    25 import java.net.URL; 
    26 import java.net.URLConnection; 
    27 import java.util.Iterator; 
    28 import java.util.Map; 
    2920import java.util.List; 
    3021 
     
    3627import org.geowebcache.GeoWebCacheException; 
    3728import org.geowebcache.layer.SRS; 
    38 import org.geowebcache.layer.Grid; 
    3929import org.geowebcache.layer.TileLayer; 
    4030import org.geowebcache.layer.TileLayerDispatcher; 
    41 import org.geowebcache.layer.wms.WMSLayer; 
    4231import org.geowebcache.mime.MimeException; 
    4332import org.geowebcache.mime.MimeType; 
     
    5443    private static Log log = LogFactory.getLog(org.geowebcache.service.wms.WMSService.class); 
    5544 
    56     // The following two are only needed for the  
    57     // temporary getcapabilities code 
    58     private List<Configuration> getCapConfigs; 
    59  
    60     private String getCapsStr; 
    61  
     45    // Proxy requests that are not getmap ? 
     46    private boolean proxyRequests = false; 
     47     
     48    // Proxy requests that are not tiled=true? 
     49    private boolean proxyNonTiledRequests = false; 
     50     
    6251    public WMSService() { 
    6352        super(SERVICE_WMS); 
     
    6655    public Tile getTile(HttpServletRequest request, HttpServletResponse response) 
    6756            throws GeoWebCacheException { 
    68         String[] keys = { "layers", "request" }; 
     57        String[] keys = { "layers", "request", "tiled" }; 
    6958        String[] values = ServletUtils.selectedStringsFromMap( 
    7059                request.getParameterMap(), keys); 
    7160 
    72         // Look for getCapabilities 
     61        // Look for requests that are not getmap 
    7362        String req = values[1]; 
    74         if (req != null && req.equalsIgnoreCase("getcapabilities")) { 
     63        if (req != null && !req.equalsIgnoreCase("getmap")) { 
     64            // One more chance 
     65            if(values[0] == null || values[0].length() == 0) {     
     66                values[0] = ServletUtils.stringFromMap(request.getParameterMap(), "layer"); 
     67            } 
     68             
    7569            Tile tile = new Tile(values[0], request, response); 
    76             tile.setHint("getcapabilities"); 
     70            tile.setHint(req.toLowerCase()); 
     71            tile.setRequestHandler(Tile.RequestHandler.SERVICE); 
     72            return tile; 
     73        } 
     74 
     75        // Check whether this request is missing tiled=true 
     76        if (proxyNonTiledRequests 
     77                && (values[2] == null || !values[2].equalsIgnoreCase("true"))) { 
     78            Tile tile = new Tile(values[0], request, response); 
     79            tile.setHint(req); 
    7780            tile.setRequestHandler(Tile.RequestHandler.SERVICE); 
    7881            return tile; 
     
    148151            throws GeoWebCacheException { 
    149152 
    150         if (tile.hint != null && tile.hint.equalsIgnoreCase("getcapabilities")) { 
    151             handleGetCapabilities(tLD, tile.servletResp); 
     153        if (tile.hint != null) { 
     154            if(tile.hint.equalsIgnoreCase("getcapabilities")) { 
     155                WMSRequests.handleGetCapabilities(tLD, tile.servletResp); 
     156            } else { 
     157                WMSRequests.handleProxy(tLD, tile); 
     158            } 
    152159        } else { 
    153160            throw new GeoWebCacheException( 
    154                     "The WMS Service would love to help," 
    155                             + " but has no idea what you're trying to do?" 
    156                             + "Please include request URL in your "); 
     161                    "The WMS Service would love to help, " 
     162                  + "but has no idea what you're trying to do?" 
     163                  + "Please include request URL if you file a bug report."); 
    157164        } 
    158165    } 
    159  
    160     /** 
    161      * Creates getCapabilities response by looping over tilelayers 
    162      *  
    163      * @param tLD 
    164      * @param response 
    165      * @throws GeoWebCacheException 
    166      */ 
    167     private void handleGetCapabilities(TileLayerDispatcher tLD, 
    168             HttpServletResponse response) throws GeoWebCacheException { 
    169         Map<String, TileLayer> layerMap = tLD.getLayers(); 
    170         Iterator<TileLayer> iter = layerMap.values().iterator(); 
    171  
    172         StringBuffer buf = new StringBuffer(); 
    173         buf.append(getCapabilitiesHeader()); 
    174  
    175         while (iter.hasNext()) { 
    176             TileLayer tl = iter.next(); 
    177             if (!tl.isInitialized()) { 
    178                 // ooops ? (Always returns true :) ) 
    179             } 
    180             buf.append(getTileSets(tl)); 
     166     
     167    public void setConfig(List<Configuration> getCapConfigs) { 
     168        WMSRequests.getCapConfigs = getCapConfigs; 
     169        log.info("Got passed " + getCapConfigs.size() + " configuration objects for getCapabilities."); 
     170    } 
     171     
     172    public void setProxyRequests(String trueFalse) { 
     173        this.proxyRequests = Boolean.parseBoolean(trueFalse); 
     174        if(this.proxyRequests) { 
     175            log.info("Will proxy requests to backend that are not getmap or getcapabilities."); 
     176        } else { 
     177            log.info("Will NOT proxy non-getMap requests to backend."); 
    181178        } 
    182  
    183         buf.append(getCapabilitiesFooter()); 
    184  
    185         try { 
    186             writeData(response, buf.toString().getBytes()); 
    187         } catch (IOException ioe) { 
    188             throw new GeoWebCacheException("Error doing getCapabilities: " 
    189                     + ioe.getMessage()); 
    190         } 
    191  
    192179    } 
    193  
    194     private String getCapabilitiesHeader() throws GeoWebCacheException { 
    195         String wms = fetchOrigionalWMSCapabilitiesDocument(); 
    196  
    197         if (wms == null) { 
    198             throw new GeoWebCacheException( 
    199                     "Unable to retrieve original WMS Capabilities document"); 
    200         } 
    201  
    202         int split = wms.indexOf("<VendorSpecificCapabilities/>"); 
    203         if (split != -1) { 
    204             // we have an empty VendorSpecificCapabilities to fill in... 
    205             String header = wms.substring(0, split); 
    206             return header + "\n<VendorSpecificCapabilities>"; 
    207         } 
    208         split = wms.indexOf("</VendorSpecificCapabilities>"); 
    209          
    210         // Was never read anyway 
    211         //if (split != -1) { 
    212             // we have an existing VendorSpecificCapabilities to add to 
    213         //    String header = wms.substring(0, split); 
    214         //} 
    215          
    216         // look for <UserDefinedSymbolization .. VendorSpecificCapabilities goes 
    217         // before this element 
    218         split = wms.indexOf("<UserDefinedSymbolization"); 
    219         if (split == -1) { 
    220             // look for <Layer> ... VendorSpecificParameters goes before this 
    221             // element 
    222             split = wms.indexOf("<Layer"); 
    223         } 
    224         String header = wms.substring(0, split); 
    225  
    226         return header + "\n<VendorSpecificCapabilities>"; 
    227     } 
    228  
    229     private String getCapabilitiesFooter() throws GeoWebCacheException { 
    230         // return "\n</VendorSpecificCapabilities>" + 
    231         // "\n</WMT_MS_Capabilities>"; 
    232         String wms = fetchOrigionalWMSCapabilitiesDocument(); 
    233         int split = wms.indexOf("<VendorSpecificCapabilities/>"); 
    234         if (split != -1) { 
    235             // we have an empty VendorSpecificCapabilities to fill in... 
    236             String footer = wms.substring(split + 29); 
    237             return "\n</VendorSpecificCapabilities>" + footer; 
    238         } 
    239         split = wms.indexOf("<VendorSpecificCapabilities/>"); 
    240         if (split != -1) { 
    241             // we have an existing VendorSpecificCapabilities to add to 
    242             String footer = wms.substring(split + 28); 
    243             return "\n</VendorSpecificCapabilities>" + footer; 
    244         } 
    245         // look for <UserDefinedSymbolization .. VendorSpecificCapabilities goes 
    246         // before this element 
    247         split = wms.indexOf("<UserDefinedSymbolization"); 
    248         if (split == -1) { 
    249             // look for <Layer> ... VendorSpecificParameters goes before this 
    250             // element 
    251             split = wms.indexOf("<Layer"); 
    252         } 
    253         String footer = wms.substring(split); 
    254         return "\n</VendorSpecificCapabilities>" + footer; 
    255     } 
    256  
    257     /** 
    258      * Fetch the original WMS capabilities document (we will add our vendor 
    259      * specific parameters here). 
    260      * <p> 
    261      * Currently this is returned as a String; in the future we can make use of 
    262      * the GeoTools WMSCapabilities data structure (and strip out any layers 
    263      * that are not mentioned explicitly). 
    264      *  
    265      * @return The original WMS capabilities document prior to processing 
    266      * @throws GeoWebCacheException  
    267      */ 
    268     synchronized String fetchOrigionalWMSCapabilitiesDocument() throws GeoWebCacheException { 
    269         if (getCapsStr != null) { 
    270             return getCapsStr; 
    271         } 
    272         StringBuffer buf = new StringBuffer(); 
    273          
    274         if (getCapConfigs == null) { 
    275             throw new GeoWebCacheException("No configuration object available" + 
    276                         " to use for WMS Capabilities"); 
    277         } 
    278         Iterator<Configuration> configIter = getCapConfigs.iterator(); 
    279         CONFIG: while (configIter.hasNext()) { 
    280             Map<String, TileLayer> configLayers = null; 
    281             Configuration config = configIter.next(); 
    282             try { 
    283                 configLayers = config.getTileLayers(); 
    284             } catch (GeoWebCacheException gwce) { 
    285                 log.error(gwce.getMessage()); 
    286                 log.error("Failed to add layers from "+ config.getIdentifier()); 
    287             } 
    288             if (configLayers != null && configLayers.size() > 0) { 
    289                 for (TileLayer layer : configLayers.values()) { 
    290                     if (!(layer instanceof WMSLayer)) { 
    291                         continue; // skip! 
    292                     } 
    293                     WMSLayer wmsLayer = (WMSLayer) layer; 
    294                     for (String url : wmsLayer.getWMSurl()) { 
    295                         try { 
    296                             URL capabilitiesURL = new URL( 
    297                                     url+ "?REQUEST=GetCapabilities&SERVICE=WMS&VESION=1.1.0"); 
    298                             URLConnection connection = capabilitiesURL.openConnection(); 
    299                             InputStream input = connection.getInputStream(); 
    300                             InputStreamReader reader = new InputStreamReader(input); 
    301                             BufferedReader process = new BufferedReader(reader); 
    302  
    303                             buf = new StringBuffer(); 
    304                             String line; 
    305                             while ((line = process.readLine()) != null) { 
    306                                 buf.append(line); 
    307                                 buf.append("\n"); 
    308                             } 
    309                             if (buf.length() != 0) { 
    310                                 break CONFIG; // we managed to read a 
    311                                               // capabilities into buf 
    312                             } 
    313                             /* 
    314                              * // TODO only use the parts of the capabilities 
    315                              * file that // are mentioned in our configuration! 
    316                              *  
    317                              * WebMapServer wms = new 
    318                              * WebMapServer(capabilitiesURL); WMSCapabilities 
    319                              * capabilities = wms.getCapabilities(); 
    320                              */ 
    321                         } catch (Throwable notConnected) { 
    322                             // continue WMSURL 
    323                         } 
    324                     } 
    325                 } 
    326             } else { 
    327                 log.error("Configuration " + config.getIdentifier() 
    328                         + " contained no layers."); 
    329             } 
    330         } 
    331         getCapsStr = buf.toString(); 
    332         return getCapsStr; 
    333     } 
    334  
    335     public void setConfig(List<Configuration> configs) { 
    336         this.getCapConfigs = configs; 
    337     } 
    338  
    339     /** 
    340      *  
    341      * @param tl 
    342      * @return 
    343      */ 
    344     private String getTileSets(TileLayer tl) throws GeoWebCacheException { 
    345         String ret = ""; 
    346  
    347         List<MimeType> mimeList = tl.getMimeTypes(); 
    348         String strStyles = tl.getStyles(); 
    349         if (strStyles == null) { 
    350             strStyles = ""; 
    351         } 
    352  
    353         Iterator<Grid> iter = tl.getGrids().values().iterator(); 
    354         while (iter.hasNext()) { 
    355             Grid grid = iter.next(); 
    356  
    357             // These should be adjusted bounds! 
    358             String[] strBounds = doublesToStrings(grid.getBounds().coords); 
    359             String strResolutions = getResolutionString(grid.getResolutions()); 
    360             String strName = tl.getName(); 
    361  
    362             for (MimeType mime : mimeList) { 
    363                 String strFormat = mime.getFormat(); 
    364                 ret += getTileSet(strName, grid.getSRS().toString(), strBounds, 
    365                         strStyles, strResolutions, strFormat); 
    366             } 
    367         } 
    368  
    369         return ret; 
    370     } 
    371  
    372     private String getTileSet(String strName, String strSRS, 
    373             String[] strBounds, String strStyles, String strResolutions, 
    374             String strFormat) { 
    375         return "\n<TileSet>"  
    376             + "<SRS>" + strSRS + "</SRS>" 
    377             + "<BoundingBox srs=\"" + strSRS + "\"" + " minx=\"" 
    378             + strBounds[0] + "\"" + " miny=\"" + strBounds[1] + "\"" 
    379             + " maxx=\"" + strBounds[2] + "\"" + " maxy=\"" + strBounds[3] 
    380             + "\" />"  
    381             + "<Resolutions>" + strResolutions + "</Resolutions>" 
    382             + "<Width>256</Width>"  
    383             + "<Height>256</Height>"  
    384             + "<Format>" + strFormat + "</Format>"  
    385             + "<Layers>" + strName + "</Layers>" 
    386             + "<Styles>" + strStyles + "</Styles>"  
    387             + "</TileSet>"; 
    388     } 
    389  
    390     private String[] doublesToStrings(double[] doubles) { 
    391         String[] ret = new String[doubles.length]; 
    392         for (int i = 0; i < doubles.length; i++) { 
    393             ret[i] = Double.toString(doubles[i]); 
    394         } 
    395         return ret; 
    396     } 
    397  
    398     private String getResolutionString(double[] resolutions) { 
    399         String ret = ""; 
    400         for (int i = 0; i < resolutions.length; i++) { 
    401             ret += Double.toString(resolutions[i]) + " "; 
    402         } 
    403         return ret; 
    404     } 
    405  
    406     /** 
    407      * Should only be used for getCapabilities 
    408      *  
    409      * @param response 
    410      * @param data 
    411      * @throws IOException 
    412      */ 
    413     private void writeData(HttpServletResponse response, byte[] data) 
    414             throws IOException { 
    415  
    416         // Did we get anything? 
    417         if (data == null || data.length == 0) { 
    418             log.trace("sendData() had nothing to return"); 
    419             response.setStatus(HttpServletResponse.SC_NO_CONTENT); 
    420             return; 
    421         } 
    422  
    423         log.trace("sendData() Sending data."); 
    424         response.setStatus(HttpServletResponse.SC_OK); 
    425         response.setContentType("application/vnd.ogc.wms_xml"); 
    426         response.setContentLength(data.length); 
    427         try { 
    428             OutputStream os = response.getOutputStream(); 
    429             os.write(data); 
    430             os.flush(); 
    431         } catch (IOException ioe) { 
    432             log.debug("Caught IOException" + ioe.getMessage()); 
     180     
     181    public void setProxyNonTiledRequests(String trueFalse) { 
     182        this.proxyNonTiledRequests = Boolean.parseBoolean(trueFalse); 
     183        if(this.proxyNonTiledRequests) { 
     184            log.info("Will proxy requests that miss tiled=true to backend."); 
     185        } else { 
     186            log.info("Will NOT proxy requests that miss tiled=true to backend."); 
    433187        } 
    434188    } 
  • trunk/geowebcache/src/main/java/org/geowebcache/util/ServletUtils.java

    r353 r397  
    129129                if(key.equalsIgnoreCase(keys[i])) { 
    130130                    retAr[i] = entry.getValue()[0]; 
    131                     continue; 
     131                    break; 
    132132                } 
    133133            } 
  • trunk/geowebcache/src/main/webapp/WEB-INF/geowebcache-servlet.xml

    r384 r397  
    5454  <!-- Services, make sure you name the bean the same as the path --> 
    5555  <bean id="gwcServiceWMS"  
    56         class="org.geowebcache.service.wms.WMSService"/> 
     56        class="org.geowebcache.service.wms.WMSService"> 
     57        <property name="proxyRequests"><value>TRUE</value></property> 
     58  </bean> 
    5759  <bean id="gwcServiceGMaps" 
    5860        class="org.geowebcache.service.gmaps.GMapsConverter"/>