001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/tools/wms/MapServer2DeegreeWMS.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 037 package org.deegree.tools.wms; 038 039 import static java.lang.Double.MAX_VALUE; 040 import static java.lang.Double.parseDouble; 041 import static org.deegree.framework.log.LoggerFactory.getLogger; 042 import static org.deegree.framework.xml.XMLTools.appendElement; 043 import static org.deegree.framework.xml.XMLTools.getElement; 044 import static org.deegree.model.spatialschema.GeometryFactory.createEnvelope; 045 import static org.deegree.ogcbase.CommonNamespaces.DEEGREEWMS; 046 import static org.deegree.ogcbase.CommonNamespaces.DGJDBC; 047 import static org.deegree.ogcbase.CommonNamespaces.XLNNS; 048 049 import java.io.BufferedReader; 050 import java.io.File; 051 import java.io.FileReader; 052 import java.io.FileWriter; 053 import java.io.IOException; 054 import java.security.InvalidParameterException; 055 import java.util.LinkedList; 056 057 import javax.xml.transform.TransformerException; 058 059 import org.deegree.framework.log.ILogger; 060 import org.deegree.framework.xml.XMLFragment; 061 import org.deegree.framework.xml.XMLParsingException; 062 import org.deegree.model.crs.CRSFactory; 063 import org.deegree.model.crs.CRSTransformationException; 064 import org.deegree.model.crs.GeoTransformer; 065 import org.deegree.model.crs.UnknownCRSException; 066 import org.deegree.model.spatialschema.Envelope; 067 import org.w3c.dom.Element; 068 import org.xml.sax.SAXException; 069 070 /** 071 * <code>MapServer2DeegreeWMS</code> 072 * 073 * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a> 074 * @author last edited by: $Author: rbezema $ 075 * 076 * @version $Revision: 20031 $, $Date: 2009-10-07 13:57:33 +0200 (Mi, 07 Okt 2009) $ 077 */ 078 public class MapServer2DeegreeWMS { 079 080 private static final ILogger LOG = getLogger( MapServer2DeegreeWMS.class ); 081 082 private File mapFile; 083 084 private Layer root = new Layer(); 085 086 private boolean featureTypes; 087 088 private MapServer2DeegreeWMS( String name, boolean featureTypes ) { 089 this.featureTypes = featureTypes; 090 mapFile = new File( name ); 091 if ( !mapFile.exists() ) { 092 LOG.logInfo( "The input file does not exist!" ); 093 return; 094 } 095 } 096 097 private String arg( String line, String name ) { 098 if ( line.trim().toLowerCase().startsWith( name.toLowerCase() ) ) { 099 String arg = line.trim().substring( name.length() ).trim(); 100 return arg.startsWith( "\"" ) ? arg.substring( 1, arg.length() - 1 ) : arg; 101 } 102 return null; 103 } 104 105 private void readTree() 106 throws IOException { 107 BufferedReader in = new BufferedReader( new FileReader( mapFile ) ); 108 109 boolean rootRead = false; 110 Layer current = root; 111 String currentConn = null; 112 113 String s; 114 while ( ( s = in.readLine() ) != null ) { 115 116 if ( s.trim().equalsIgnoreCase( "layer" ) ) { 117 rootRead = true; 118 current = new Layer(); 119 } 120 121 if ( current.name == null ) { 122 current.name = arg( s, "name" ); 123 } 124 if ( current.title == null ) { 125 current.title = arg( s, "\"wms_title\"" ); 126 } 127 128 if ( rootRead ) { 129 String cat = arg( s, "\"wms_layer_group\"" ); 130 if ( cat != null ) { 131 Layer parent = root; 132 String[] cats = cat.substring( 1 ).split( "/" ); 133 outer: for ( String c : cats ) { 134 for ( Layer l : parent.children ) { 135 if ( l.title.equals( c ) ) { 136 parent = l; 137 continue outer; 138 } 139 } 140 Layer l = new Layer(); 141 l.title = c; 142 parent.children.add( l ); 143 parent = l; 144 } 145 146 parent.children.add( current ); 147 } 148 149 String conn = arg( s, "connection " ); 150 if ( conn != null ) { 151 currentConn = conn; 152 } 153 String connType = arg( s, "connectiontype" ); 154 if ( connType != null && connType.equalsIgnoreCase( "oraclespatial" ) ) { 155 current.oracleconn = currentConn; 156 } 157 if ( connType != null && connType.equalsIgnoreCase( "wms" ) ) { 158 current.remotewms = currentConn; 159 } 160 // TODO add more connection types 161 String data = arg( s, "data" ); 162 if ( data != null ) { 163 current.data = data; 164 } 165 String srs = arg( s, "\"wms_srs\"" ); 166 if ( srs != null ) { 167 current.srs = srs; 168 } 169 String minscale = arg( s, "minscale" ); 170 if ( minscale != null ) { 171 current.minscale = minscale; 172 } 173 String maxscale = arg( s, "maxscale" ); 174 if ( maxscale != null ) { 175 current.maxscale = maxscale; 176 } 177 String bbox = arg( s, "\"wms_extent\"" ); 178 if ( bbox != null ) { 179 current.bbox = bbox; 180 } 181 String wmsname = arg( s, "\"wms_name\"" ); 182 if ( wmsname != null ) { 183 current.wmsname = wmsname; 184 } 185 String wmsversion = arg( s, "\"wms_server_version\"" ); 186 if ( wmsversion != null ) { 187 current.wmsversion = wmsversion; 188 } 189 String wmsformat = arg( s, "\"wms_format\"" ); 190 if ( wmsformat != null ) { 191 current.wmsformat = wmsformat; 192 } 193 String type = arg( s, "type" ); 194 if ( type != null ) { 195 current.raster = type.equalsIgnoreCase( "raster" ); 196 } 197 } else { 198 String extent = arg( s, "extent" ); 199 if ( extent != null ) { 200 current.bbox = extent; 201 } 202 String proj = arg( s, "\"init=" ); 203 if ( proj != null ) { 204 current.srs = proj.substring( 0, proj.length() - 1 ); 205 } 206 } 207 208 } 209 root.print( 0 ); 210 } 211 212 private void appendLayer( Element root, Layer layer ) 213 throws InvalidParameterException, CRSTransformationException { 214 root = appendElement( root, null, layer.raster ? "RasterLayer" : "Layer" ); 215 216 root.setAttribute( "queryable", "1" ); 217 218 if ( layer.name != null ) { 219 appendElement( root, null, "Name", layer.name ); 220 } 221 if ( layer.title != null ) { 222 appendElement( root, null, "Title", layer.title ); 223 } 224 if ( layer.srs != null && !layer.srs.equalsIgnoreCase( this.root.srs ) ) { 225 appendElement( root, null, "SRS", this.root.srs.toUpperCase() ); 226 } 227 if ( layer.srs != null ) { 228 appendElement( root, null, "SRS", layer.srs.toUpperCase() ); 229 } 230 if ( layer.bbox != null && layer.srs != null ) { 231 String[] ss = layer.bbox.split( " " ); 232 double minx = Double.parseDouble( ss[0] ); 233 double miny = Double.parseDouble( ss[1] ); 234 double maxx = Double.parseDouble( ss[2] ); 235 double maxy = Double.parseDouble( ss[3] ); 236 try { 237 Envelope bbox = createEnvelope( minx, miny, maxx, maxy, CRSFactory.create( layer.srs ) ); 238 Envelope wgs84bbox = new GeoTransformer( "EPSG:4326" ).transform( bbox, layer.srs, true ); 239 Element elem = appendElement( root, null, "LatLonBoundingBox" ); 240 elem.setAttribute( "minx", "" + wgs84bbox.getMin().getX() ); 241 elem.setAttribute( "miny", "" + wgs84bbox.getMin().getY() ); 242 elem.setAttribute( "maxx", "" + wgs84bbox.getMax().getX() ); 243 elem.setAttribute( "maxy", "" + wgs84bbox.getMax().getY() ); 244 245 elem = appendElement( root, null, "BoundingBox" ); 246 elem.setAttribute( "SRS", layer.srs ); 247 elem.setAttribute( "minx", "" + minx ); 248 elem.setAttribute( "miny", "" + miny ); 249 elem.setAttribute( "maxx", "" + maxx ); 250 elem.setAttribute( "maxy", "" + maxy ); 251 } catch ( UnknownCRSException e ) { 252 LOG.logError( "Unknown error", e ); 253 } 254 } 255 256 Element sh = appendElement( root, null, "ScaleHint" ); 257 sh.setAttribute( "min", layer.minscale == null ? "0" 258 : Double.toString( ( parseDouble( layer.minscale ) / 0.00028 ) ) ); 259 sh.setAttribute( "max", layer.maxscale == null ? "" + MAX_VALUE 260 : Double.toString( ( parseDouble( layer.maxscale ) / 0.00028 ) ) ); 261 262 if ( layer.remotewms == null && layer != this.root && layer.name != null ) { // no style for remotewms layers 263 Element style = appendElement( root, null, "Style" ); 264 appendElement( style, null, "Name", "default" ); 265 appendElement( style, null, "Title", "default" ); 266 appendElement( style, DEEGREEWMS, "StyleResource", "styles/" + layer.name + ".sld" ); 267 } 268 269 if ( layer.name != null ) { 270 Element ds = appendElement( root, DEEGREEWMS, "DataSource" ); 271 ds.setAttribute( "failOnException", "0" ); 272 ds.setAttribute( "queryable", "1" ); 273 if ( layer.oracleconn != null ) { 274 String[] data = layer.data.split( " " ); 275 276 if ( featureTypes ) { 277 appendElement( ds, DEEGREEWMS, "Name", "app:" + data[2].trim().toUpperCase() ); 278 appendElement( ds, DEEGREEWMS, "GeometryProperty", "app:" + data[0].toLowerCase() ); 279 } else { 280 appendElement( ds, DEEGREEWMS, "Name", layer.name ); 281 appendElement( ds, DEEGREEWMS, "Type", "DATABASE" ); 282 Element elem = appendElement( ds, DGJDBC, "JDBCConnection" ); 283 appendElement( elem, DGJDBC, "Driver", "oracle.jdbc.driver.OracleDriver" ); 284 String user = layer.oracleconn.substring( 0, layer.oracleconn.indexOf( "/" ) ); 285 String pass = layer.oracleconn.substring( user.length() + 1, layer.oracleconn.indexOf( "@" ) ); 286 String url = layer.oracleconn.substring( user.length() + pass.length() + 1 ); // keep the @ 287 url = "jdbc:oracle:thin:" + url; 288 appendElement( elem, DGJDBC, "Url", url ); 289 appendElement( elem, DGJDBC, "User", user ); 290 appendElement( elem, DGJDBC, "Password", pass ); 291 appendElement( ds, DEEGREEWMS, "GeometryField", data[0] ); 292 appendElement( ds, DEEGREEWMS, "SQLTemplate", "select * " + layer.data.substring( data[0].length() ) 293 + " where " ); 294 appendElement( ds, DEEGREEWMS, "NativeCRS", layer.srs ); 295 } 296 } 297 if ( layer.remotewms != null ) { 298 appendElement( ds, DEEGREEWMS, "Name", layer.name ); 299 appendElement( ds, DEEGREEWMS, "Type", "REMOTEWMS" ); 300 Element elem = appendElement( ds, DEEGREEWMS, "OWSCapabilities" ); 301 elem = appendElement( elem, DEEGREEWMS, "OnlineResource" ); 302 elem.setAttributeNS( "http://www.w3.org/1999/xlink", "xlink:type", "simple" ); 303 elem.setAttributeNS( "http://www.w3.org/1999/xlink", "xlink:href", 304 layer.remotewms + "?request=GetCapabilities&service=WMS&version=" 305 + layer.wmsversion ); 306 elem = appendElement( ds, DEEGREEWMS, "FilterCondition" ); 307 appendElement( elem, DEEGREEWMS, "WMSRequest", "service=WMS&version=1.1.1&request=GetMap&format=" 308 + layer.wmsformat 309 + "&transparent=true&exceptions=application/vnd.ogc." 310 + "se_inimage&styles=&layers=" + layer.wmsname + "&srs=" 311 + layer.srs ); 312 } 313 if ( layer.raster ) { 314 appendElement( ds, DEEGREEWMS, "Name", layer.name ); 315 appendElement( ds, DEEGREEWMS, "Type", "LOCALWCS" ); 316 Element e = appendElement( ds, DEEGREEWMS, "OWSCapabilities" ); 317 e = appendElement( e, DEEGREEWMS, "OnlineResource" ); 318 e.setAttributeNS( XLNNS.toASCIIString(), "xlink:type", "simple" ); 319 e.setAttributeNS( XLNNS.toASCIIString(), "xlink:href", "LOCALWCS_configuration.xml" ); 320 e = appendElement( ds, DEEGREEWMS, "FilterCondition" ); 321 e = appendElement( e, DEEGREEWMS, "WCSRequest", 322 "VERSION=1.0.0&TRANSPARENT=TRUE&FORMAT=png&EXCEPTIONS=application/vnd.ogc.se_xml&coverage=" 323 + layer.name ); 324 } 325 } 326 327 for ( Layer l : layer.children ) { 328 appendLayer( root, l ); 329 } 330 } 331 332 private void produceWMSConfig() 333 throws IOException, SAXException, XMLParsingException, InvalidParameterException, 334 CRSTransformationException, TransformerException { 335 XMLFragment doc = new XMLFragment( MapServer2DeegreeWMS.class.getResource( "wms_configuration_template.xml" ) ); 336 Element capability = getElement( doc.getRootElement(), "/WMT_MS_Capabilities/Capability", null ); 337 appendLayer( capability, root ); 338 doc.prettyPrint( new FileWriter( "wms_configuration.xml" ) ); 339 } 340 341 /** 342 * @param args 343 * @throws IOException 344 * @throws CRSTransformationException 345 * @throws XMLParsingException 346 * @throws SAXException 347 * @throws InvalidParameterException 348 * @throws TransformerException 349 */ 350 public static void main( String[] args ) 351 throws IOException, InvalidParameterException, SAXException, XMLParsingException, 352 CRSTransformationException, TransformerException { 353 if ( args.length < 1 ) { 354 LOG.logInfo( "Usage:" ); 355 LOG.logInfo( "java -cp deegree2.jar org.deegree.tools.wms.MapServer2DeegreeWMS [options] <mapfile>" ); 356 LOG.logInfo( "Options:" ); 357 LOG.logInfo( " -f: generate feature type data sources instead of database data sources" ); 358 return; 359 } 360 361 if ( new File( "wms_configuration.xml" ).exists() ) { 362 LOG.logInfo( "wms_configuration.xml already exists. Please remove it and run the tool again." ); 363 return; 364 } 365 366 String file = args.length > 1 ? args[1] : args[0]; 367 MapServer2DeegreeWMS conv; 368 if ( args.length > 1 ) { 369 conv = new MapServer2DeegreeWMS( file, args[0].equals( "-f" ) ); 370 } else { 371 conv = new MapServer2DeegreeWMS( file, false ); 372 } 373 conv.readTree(); 374 conv.produceWMSConfig(); 375 } 376 377 static class Layer { 378 String name, title, oracleconn, remotewms, bbox, srs, wmsname, wmsformat, data, wmsversion, minscale, maxscale; 379 380 boolean raster; 381 382 LinkedList<Layer> children = new LinkedList<Layer>(); 383 384 static void maybePrint( int indent, String name, String val ) { 385 if ( val != null ) { 386 for ( int i = 0; i < indent; ++i ) { 387 System.out.print( ' ' ); 388 } 389 System.out.println( name + " " + val ); 390 } 391 } 392 393 void print( int indent ) { 394 maybePrint( indent, "NAME", name ); 395 maybePrint( indent, "TITLE", title ); 396 maybePrint( indent, "ORACLE CONNECTION", oracleconn ); 397 maybePrint( indent, "REMOTEWMS", remotewms ); 398 maybePrint( indent, "REMOTEWMS NAME", wmsname ); 399 maybePrint( indent, "REMOTEWMS FORMAT", wmsformat ); 400 maybePrint( indent, "SRS", srs ); 401 maybePrint( indent, "BBOX", bbox ); 402 for ( Layer l : children ) { 403 l.print( indent + 2 ); 404 } 405 } 406 } 407 408 }