mapproxy-java Mailing List for MapProxy for Java
Brought to you by:
pborissow
You can subscribe to this list here.
2010 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(5) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2011 |
Jan
(1) |
Feb
(8) |
Mar
(8) |
Apr
(4) |
May
(10) |
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
|
2012 |
Jan
(3) |
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <pbo...@us...> - 2012-03-29 15:10:19
|
Revision: 41 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=41&view=rev Author: pborissow Date: 2012-03-29 15:10:10 +0000 (Thu, 29 Mar 2012) Log Message: ----------- - Temporarily commented out logic in the mapproxy.core.Layer.getImage() method to check whether a requested bounding box falls outside of the max extents. In recent testing, the intersection test was returning incorrect values resulting in empty tiles. Something is not right! - Updated the HttpServlet to use the new javaxt-server library. - Added new class to track version number. - Commented out a couple debug print statements. - Added default values for "cache.max_tile_limit" and "image.resampling_method" in the Config class. Modified Paths: -------------- Main.java config/Config.java core/HttpServlet.java core/Layer.java core/ServiceResponse.java core/image/TiledImage.java core/request/BaseRequest.java wms/client/WMSClient.java Added Paths: ----------- core/Version.java Modified: Main.java =================================================================== --- Main.java 2012-01-11 12:13:48 UTC (rev 40) +++ Main.java 2012-03-29 15:10:10 UTC (rev 41) @@ -1,4 +1,5 @@ package mapproxy; +import mapproxy.core.HttpServlet; import mapproxy.wms.request.*; import mapproxy.wms.client.*; import mapproxy.core.grid.*; @@ -299,10 +300,11 @@ Config.load(getConfig(args)); int numThreads = Config.base_config().get("threads").toInteger(); int port = Config.base_config().get("port").toInteger(); + Service service = ((mapproxy.core.Service) Config.base_config().get("mapproxy").toObject()); //Start the server try { - javaxt.http.Server mapserver = new javaxt.http.Server(port, numThreads, new HttpServlet()); + javaxt.http.Server mapserver = new javaxt.http.Server(port, numThreads, new HttpServlet(service)); mapserver.start(); } catch (Exception e) { Modified: config/Config.java =================================================================== --- config/Config.java 2012-01-11 12:13:48 UTC (rev 40) +++ config/Config.java 2012-03-29 15:10:10 UTC (rev 41) @@ -18,7 +18,8 @@ public static Options base_config(){ if (options==null){ options = new Options(); - options.set("version", "1.0"); + options.set("cache.max_tile_limit", 500); + options.set("image.resampling_method", "bicubic"); } return options; } Modified: core/HttpServlet.java =================================================================== --- core/HttpServlet.java 2012-01-11 12:13:48 UTC (rev 40) +++ core/HttpServlet.java 2012-03-29 15:10:10 UTC (rev 41) @@ -11,18 +11,19 @@ * ******************************************************************************/ -public class HttpServlet implements javaxt.http.servlet.HttpServlet { +public class HttpServlet extends javaxt.http.servlet.HttpServlet { private static ConcurrentHashMap<String, String> httpCache; - private static String serverName; + private static String serverName = "MapProxy Server " + Version.ID; + private Service service; //************************************************************************** //** Constructor //************************************************************************** /** Creates a new instance of HttpServlet. */ - public HttpServlet() { - serverName = "MapProxy Server " + mapproxy.config.Config.base_config().get("version").toString(); + public HttpServlet(mapproxy.core.Service service) { + this.service = service; httpCache = new ConcurrentHashMap<String, String>(); } @@ -32,17 +33,18 @@ //************************************************************************** /** Used to process http get and post requests. */ - public void processRequest(HttpServletRequest request, HttpServletResponse response) { + public void processRequest(HttpServletRequest request, HttpServletResponse response) + throws java.io.IOException { //long startTime = new java.util.Date().getTime(); //long initResponse = 0; //long initCache = 0; try{ - Service service = ((mapproxy.core.Service) mapproxy.config.Config.base_config().get("mapproxy").toObject()); ServiceResponse map = service.getResponse(request.getURL().toString(), new String(request.getBody(), "UTF-8")); javaxt.utils.Date date = map.getDate(); String key = map.getID(); //initResponse = new java.util.Date().getTime()-startTime; boolean useCache = useCache(request, key); + //initCache = new java.util.Date().getTime()-(initResponse+startTime); if (useCache){ @@ -79,7 +81,7 @@ } } catch(Exception e){ - +e.printStackTrace(); //Return Error response.setStatus(500); response.setHeader("Server", serverName); Modified: core/Layer.java =================================================================== --- core/Layer.java 2012-01-11 12:13:48 UTC (rev 40) +++ core/Layer.java 2012-03-29 15:10:10 UTC (rev 41) @@ -313,7 +313,7 @@ * @param srs Spatial reference system associated with the bbox (e.g. EPSG:4326). */ public javaxt.io.Image getImage(int width, int height, String format, String bbox, String srs){ - + FileCache fileCache = (FileCache) this.getParam("cache"); TileGrid grid = (TileGrid) this.getParam("grid"); @@ -331,6 +331,8 @@ //Check whether we should use/create a map cache boolean useCache = (fileCache!=null); + //System.out.println(this.getBBox().intersects(new BBox(bbox, srs))); + /* if (useCache) { if (!this.getBBox().intersects(new BBox(bbox, srs))) { // return the blank tile, no need to call the WMS @@ -346,8 +348,8 @@ return image; } } +*/ - //if (format.equalsIgnoreCase("image/PNG24")) format = "jpeg"; //<-- This is crazy! If I return a 24 bit PNG, ArcMap doesn't display anything. If I return a JPEG, works like a champ if (!format.toLowerCase().startsWith("image/")) format = "image/" + format; if (format.equalsIgnoreCase("image/jpg")) format = "image/jpeg"; @@ -380,7 +382,7 @@ image = cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()); } catch (Exception e) { - + e.printStackTrace(); } return image; } Modified: core/ServiceResponse.java =================================================================== --- core/ServiceResponse.java 2012-01-11 12:13:48 UTC (rev 40) +++ core/ServiceResponse.java 2012-03-29 15:10:10 UTC (rev 41) @@ -58,7 +58,7 @@ } } - + this.url = new javaxt.utils.URL(url.toString()); if (requestBody!=null){ @@ -407,7 +407,7 @@ //Create unique key key = bbox + "|" + layers + "|" + contentType + "|" + width + "|" + height + "|" + srs; - + //Exit method as needed if (!getBytes) return; @@ -440,11 +440,6 @@ //Convert the image into a byte array if (format.toLowerCase().endsWith("png24")) format = "image/png"; rsp = image.getByteArray(format); - - - //rsp = new javaxt.io.File("/temp/ArcGIS/ExportImage.png").getBytes().toByteArray(); - //rsp = new javaxt.io.Image("/temp/ArcGIS/ExportImage.png").getByteArray("png"); - } Added: core/Version.java =================================================================== --- core/Version.java (rev 0) +++ core/Version.java 2012-03-29 15:10:10 UTC (rev 41) @@ -0,0 +1,13 @@ +package mapproxy.core; + +public class Version { + + + private Version(){} + + public static final String ID = "0.8.1 RC4"; + + + public String toString(){ return ID; } + +} Modified: core/image/TiledImage.java =================================================================== --- core/image/TiledImage.java 2012-01-11 12:13:48 UTC (rev 40) +++ core/image/TiledImage.java 2012-03-29 15:10:10 UTC (rev 41) @@ -1,6 +1,5 @@ package mapproxy.core.image; import mapproxy.core.SRS; -import mapproxy.core.Python; //****************************************************************************** //** TiledImage Class Modified: core/request/BaseRequest.java =================================================================== --- core/request/BaseRequest.java 2012-01-11 12:13:48 UTC (rev 40) +++ core/request/BaseRequest.java 2012-03-29 15:10:10 UTC (rev 41) @@ -84,7 +84,7 @@ if (this.url.contains("?")) delimiter = "&"; if (this.url.endsWith("?")) delimiter = ""; - System.out.println(this.url + delimiter + this.query_string()); + //System.out.println(this.url + delimiter + this.query_string()); return this.url + delimiter + this.query_string(); } Modified: wms/client/WMSClient.java =================================================================== --- wms/client/WMSClient.java 2012-01-11 12:13:48 UTC (rev 40) +++ wms/client/WMSClient.java 2012-03-29 15:10:10 UTC (rev 41) @@ -41,7 +41,7 @@ public javaxt.io.Image get_map(WMSRequest request){ - //return new javaxt.http.Request(_map_url(request)).getResponse().getImage(); + //System.out.println(_map_url(request)); javaxt.io.Image image = new javaxt.http.Request(_map_url(request)).getResponse().getImage(); if (image.getBufferedImage()!=null){ return image; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2012-01-11 12:13:59
|
Revision: 40 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=40&view=rev Author: pborissow Date: 2012-01-11 12:13:48 +0000 (Wed, 11 Jan 2012) Log Message: ----------- - Sync'd baseline with changes from GeoEye dated 11/16. Includes dateline fix in the TileSeeder and updates to the WMS Capabilities document. Modified Paths: -------------- core/Capabilities.java core/Layer.java core/Status.java core/TileSeeder.java Modified: core/Capabilities.java =================================================================== --- core/Capabilities.java 2012-01-10 11:43:40 UTC (rev 39) +++ core/Capabilities.java 2012-01-11 12:13:48 UTC (rev 40) @@ -72,9 +72,9 @@ StringBuffer xml = new StringBuffer(); xml.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\"?>"); - xml.append("<!DOCTYPE WMT_MS_Capabilities SYSTEM \"http://schemas.opengeospatial.net/wms/1.1.1/capabilities_1_1_1.dtd\" ["); - xml.append(" <!ELEMENT VendorSpecificCapabilities EMPTY>"); - xml.append(" ]>"); + //xml.append("<!DOCTYPE WMT_MS_Capabilities SYSTEM \"http://schemas.opengeospatial.net/wms/1.1.1/capabilities_1_1_1.dtd\" ["); + //xml.append(" <!ELEMENT VendorSpecificCapabilities EMPTY>"); + //xml.append(" ]>"); xml.append("<WMT_MS_Capabilities version=\"1.1.1\">"); xml.append("<Service>"); xml.append("<Name>" + service.getName() + "</Name>"); Modified: core/Layer.java =================================================================== --- core/Layer.java 2012-01-10 11:43:40 UTC (rev 39) +++ core/Layer.java 2012-01-11 12:13:48 UTC (rev 40) @@ -8,6 +8,7 @@ import mapproxy.arcgis.client.*; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javaxt.io.Directory; import javaxt.io.File; @@ -248,18 +249,38 @@ return name; } + @Override + //************************************************************************** + //** hashCode + //************************************************************************** + /** Returns the hashCode of the layer. + */ public int hashCode(){ return name.toUpperCase().hashCode(); + //return getID().toUpperCase().hashCode(); //<--Maybe we should use the autogenerated layer ID instead?? } //@Override + //************************************************************************** + //** compareTo + //************************************************************************** + /** Used to compare two layers. + */ public int compareTo(Object obj){ if (obj==null) return -1; + /* + if (obj instanceof Layer) { + return -((Layer) obj).getID().toUpperCase().compareTo(getID().toUpperCase()); + }*/ else return -obj.toString().compareTo(name.toUpperCase()); } + + //************************************************************************** + //** invalidateTile + //************************************************************************** public void invalidateTile(int[] tile, String format, String srs) { FileCache fileCache = (FileCache) this.getParam("cache"); @@ -279,16 +300,17 @@ } } } - + + //************************************************************************** //** getImage //************************************************************************** - /** Used to return an image for a given bbox. + /** Used to return an image of the layer. * @param width Image width * @param height Image height - * @param format Requested format - * @param bbox Bounding box - * @param srs Spatial reference system associated with the bbox. + * @param format Image format + * @param bbox String representing the requested bounding box (e.g. minx,miny,maxx,maxy) + * @param srs Spatial reference system associated with the bbox (e.g. EPSG:4326). */ public javaxt.io.Image getImage(int width, int height, String format, String bbox, String srs){ @@ -297,7 +319,6 @@ String host = (String) this.getParam("host"); if (!host.contains("?")) host += "?"; - //host += url.getQueryString(); WMSMapRequestParams param = new WMSMapRequestParams(); param.set("layers", (String) this.getParam("layers")); @@ -325,10 +346,8 @@ return image; } } - - //if (format.equalsIgnoreCase("image/PNG24")) format = "jpeg"; //<-- This is crazy! If I return a 24 bit PNG, ArcMap doesn't display anything. If I return a JPEG, works like a champ if (!format.toLowerCase().startsWith("image/")) format = "image/" + format; if (format.equalsIgnoreCase("image/jpg")) format = "image/jpeg"; @@ -339,6 +358,16 @@ String protocol = (String) this.getParam("protocol"); if (protocol.equalsIgnoreCase("WMS")){ + //Apply any additional params that may have been specified + Map<String, String> wmsParams = (Map<String, String>)this.getParam("wms_params"); + if (wmsParams != null) { + for ( Map.Entry<String, String> entry : wmsParams.entrySet () ) { + String key = entry.getKey(); + String value = entry.getValue(); + req.params.set(key, value); + } + } + if (!useCache){ return new WMSClient(req).get_map(req); } @@ -395,11 +424,33 @@ } - + //************************************************************************** + //** getImage + //************************************************************************** + /** Used to return an image of the layer. + * @param width Image width + * @param height Image height + * @param format Image format + * @param bbox Array representing the requested bounding box (e.g. minx,miny,maxx,maxy) + * @param srs Spatial reference system associated with the bbox (e.g. EPSG:4326). + */ public javaxt.io.Image getImage(int width, int height, String format, double[] bbox, String srs){ return this.getImage(width, height, format, bbox[0] + "," + bbox[1] + "," + bbox[2] + "," + bbox[3], srs); } + + //************************************************************************** + //** seed + //************************************************************************** + /** Used to pre-generate a tile cache for the current layer. You can stop + * the seed task by calling stopSeedCache() + * @param numThreads Number of threads used to generate the cache. + * @param bbox Bounding box. Spatial extents of the cache. + * @param srs Spatial reference system associated with the bbox. + * @param startLevel + * @return Returns a HashMap with status information. Keys include + * "Total Files", "Total Processed", and "Is Complete". + */ public Status seed(int numThreads, double[] bbox, String srs, int startLevel, int endLevel, TileConsumer tileProcessor) { @@ -412,21 +463,28 @@ return tileseeder.execute(this, numThreads, bbox, startLevel, endLevel, false, tileProcessor); } + //************************************************************************** - //** seedLayers + //** seed //************************************************************************** - /** Used to seed the current layer at a given point - * - * @param bbox Bounding box + /** Used to pre-generate a tile cache for the current layer. You can stop + * the seed task by calling stopSeedCache() + * @param numThreads Number of threads used to generate the cache. + * @param bbox Bounding box. Spatial extents of the cache. * @param srs Spatial reference system associated with the bbox. - * @param levels Number of resolution levels - * @return Returns a HashMap with status information. Keys include - * "Total Files", "Total Processed", and "Is Complete". + * @param startLevel + * @return Returns a status object used to track progress. */ public Status seed(int numThreads, double[] bbox, String srs, int startLevel, int endLevel){ return seed(numThreads, bbox, srs, startLevel, endLevel, null); } - + + + //************************************************************************** + //** stopSeedCache + //************************************************************************** + /** Used to stop a seed task. See seed() + */ public boolean stopSeedCache() { boolean success= true; synchronized (ACTIVE_TASKS) { @@ -439,12 +497,21 @@ } return success; } - + + + //************************************************************************** + //** invalidate + //************************************************************************** public void invalidate(int numThreads, double[] bbox, String srs, int startLevel, int endLevel, TileConsumer tileProcessor){ new TileSeeder().execute(this, numThreads, bbox, -1, -1, true, tileProcessor); } - //returns the levels cached so far by looking at the cache directory + + //************************************************************************** + //** getCachedLevels + //************************************************************************** + /** Returns the levels cached so far by looking at the cache directory. + */ public List<Integer> getCachedLevels() { List<Integer> levels = new ArrayList<Integer>(); FileCache filecache = (FileCache)getParam("cache"); Modified: core/Status.java =================================================================== --- core/Status.java 2012-01-10 11:43:40 UTC (rev 39) +++ core/Status.java 2012-01-11 12:13:48 UTC (rev 40) @@ -4,8 +4,10 @@ //** Status Class //****************************************************************************** /** - * Enter class description here + * Object used to provide status information while seeding a layer. * + * Note that this class was not part of the original mapproxy baseline. + * ******************************************************************************/ public class Status { Modified: core/TileSeeder.java =================================================================== --- core/TileSeeder.java 2012-01-10 11:43:40 UTC (rev 39) +++ core/TileSeeder.java 2012-01-11 12:13:48 UTC (rev 40) @@ -34,9 +34,9 @@ //************************************************************************** - //** TileIterator Class + //** TileIterator //************************************************************************** - /** Class used to iterate through tiles and add them to the queue */ + /** Thread used to iterate through tiles and add them to the queue */ private static class TileIterator extends Thread { private Layer layer = null; @@ -63,6 +63,15 @@ public void run() { try { + + //dateline adjustment, turns out if the bbox crosses the dateline, the + //tiles are not generated by the TileIterator and hence building the + //map cache results in a failure. + if (bbox[0] > 0 && bbox[2] < 0) { + bbox[2] = bbox[2] + 360; + } + + tileSeeder.updateTotalTiles(-1); // System.err.println("In TileIterator"); int totalTiles = 0; @@ -223,11 +232,12 @@ return javaxt.utils.string.toInt(d); } - // ************************************************************************** - // ** execute - // ************************************************************************** - /** Used to add a layer for the TileSeeder to process. */ + //************************************************************************** + //** execute + //************************************************************************** + /** Used to add a layer for the TileSeeder to process. */ + public Status execute(Layer layer, int numThreads, double[] bbox, int startLevel, int endLevel, boolean invalidate, TileConsumer tileProcessor) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2012-01-10 11:43:52
|
Revision: 39 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=39&view=rev Author: pborissow Date: 2012-01-10 11:43:40 +0000 (Tue, 10 Jan 2012) Log Message: ----------- - Sync'd baseline with changes from GeoEye dated Oct 6. Changes are focused on improvements to the seeding capability. - Deprecated the "mapproxy.server" package. Functionality is replaced with the javaxt-server library and the new HttpServlet class. - Added unique IDs to Layers (required for seeding). Modified Paths: -------------- Main.java config/Config.java core/Layer.java core/ServiceResponse.java core/Status.java core/TileSeeder.java core/cache/Cache.java core/cache/_Tile.java Added Paths: ----------- core/HttpServlet.java core/InvalidTileException.java core/TileConsumer.java core/TileListener.java Modified: Main.java =================================================================== --- Main.java 2012-01-10 11:42:33 UTC (rev 38) +++ Main.java 2012-01-10 11:43:40 UTC (rev 39) @@ -6,11 +6,7 @@ import mapproxy.core.*; import mapproxy.wms.cache.WMSTileSource; import mapproxy.config.Config; -import mapproxy.server.HttpServer; -import java.util.concurrent.ConcurrentHashMap; - - //****************************************************************************** //** Main Application //****************************************************************************** @@ -61,7 +57,6 @@ //testCache(url); //testSRS(); - args = new String[]{"C:\\Documents and Settings\\peter.borissow\\My Documents\\Java\\Libraries\\mapproxy\\src\\mapproxy\\config.xml"}; startServer(args); //seedTest(args); //testWebServices(); @@ -252,11 +247,6 @@ String url = "http://services.arcgisonline.com/ArcGIS/services/USA_Topo_Maps/MapServer/?wsdl"; url = "http://sampleserver1.arcgisonline.com/arcgis/services/Specialty/ESRI_StateCityHighway_USA/MapServer?wsdl"; javaxt.webservices.WSDL wsdl = new javaxt.webservices.WSDL(new javaxt.http.Request(url).getResponse().getXML()); - javaxt.webservices.Soap soap = new javaxt.webservices.Soap(wsdl); - soap.setHeader("Accept", "*/*"); - soap.setHeader("Content-Type", "text/xml"); - soap.setHeader("User-Agent", "ArcGIS Client Using WinInet"); - //soap.setHeader("SOAPAction", "\"\""); //Flow: GetMessageVersion, GetFolders, GetServiceDescriptions @@ -281,8 +271,15 @@ parameters.setValue("MapName", "Layers"); - new javaxt.io.File("/temp/GetLegendInfo.xml").write(soap.execute(service, method, parameters).getText(), "UTF-8"); + + javaxt.webservices.SoapRequest request = new javaxt.webservices.SoapRequest(service, method, parameters); + request.setHeader("Accept", "*/*"); + request.setHeader("Content-Type", "text/xml"); + request.setHeader("User-Agent", "ArcGIS Client Using WinInet"); + //request.setHeader("SOAPAction", "\"\""); + new javaxt.io.File("/temp/GetLegendInfo.xml").write(request.getResponse().toString(), "UTF-8"); + } @@ -303,8 +300,17 @@ int numThreads = Config.base_config().get("threads").toInteger(); int port = Config.base_config().get("port").toInteger(); - HttpServer mapserver = new HttpServer(port, numThreads); - mapserver.start(); + //Start the server + try { + javaxt.http.Server mapserver = new javaxt.http.Server(port, numThreads, new HttpServlet()); + mapserver.start(); + } + catch (Exception e) { + System.out.println("Server could not start because of an " + + e.getClass()); + System.out.println(e); + return; + } } @@ -313,13 +319,18 @@ double[] bbox = new double[]{-180,-90,180,90}; String srs = "EPSG:4326"; - int startLevel = 1; - int endLevel = 12; + int startLevel = 6; + int endLevel = 6; Config.load(getConfig(args)); Service service = ((mapproxy.core.Service) mapproxy.config.Config.base_config().get("mapproxy").toObject()); + System.out.println("Num Layers: " + service.getLayers().length); Layer layer = service.getLayers()[0]; - Status status = layer.seed(2, bbox, srs, startLevel, endLevel); + System.out.println("Layer Name: " + layer.getName()); + System.out.println("Layer ID: " + layer.getID()); + //if (true) return; + //layer.setParam("id", 0); + Status status = layer.seed(2, bbox, srs, startLevel, endLevel, null); long lastUpdate = -1; @@ -360,6 +371,7 @@ private org.w3c.dom.Document getConfig(String[] args) throws Exception { if (args[args.length-1].toLowerCase().endsWith(".xml")){ javaxt.io.File file = new javaxt.io.File(args[args.length-1]); + if (!file.exists()) throw new Exception("Config file not found: " + file); else { return file.getXML(); @@ -407,7 +419,12 @@ CacheManager cacheManager = new CacheManager(fileCache, wms); Cache cache = new Cache(cacheManager, grid, true); - cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()).saveAs("/temp/ew_cache.png"); + try{ + cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()).saveAs("/temp/ew_cache.png"); + } + catch(Exception e){ + e.printStackTrace(); + } } Modified: config/Config.java =================================================================== --- config/Config.java 2012-01-10 11:42:33 UTC (rev 38) +++ config/Config.java 2012-01-10 11:43:40 UTC (rev 39) @@ -16,7 +16,10 @@ public static Options options; public static Options base_config(){ - if (options==null) options = new Options(); + if (options==null){ + options = new Options(); + options.set("version", "1.0"); + } return options; } @@ -203,7 +206,8 @@ if (service!=null){ java.util.ArrayList<mapproxy.core.Layer> arr = new java.util.ArrayList<mapproxy.core.Layer>(); for (String str : layers.split(",")){ - arr.add(service.getLayer(str)); + mapproxy.core.Layer lyr = service.getLayer(str); + if (lyr!=null) arr.add(service.getLayer(str)); } mapproxy.core.BBox bbox = service.getBBox(arr.toArray(new mapproxy.core.Layer[arr.size()])); layer.setBBox(bbox); Added: core/HttpServlet.java =================================================================== --- core/HttpServlet.java (rev 0) +++ core/HttpServlet.java 2012-01-10 11:43:40 UTC (rev 39) @@ -0,0 +1,171 @@ +package mapproxy.core; +import javaxt.http.servlet.*; +import java.util.concurrent.ConcurrentHashMap; + +//****************************************************************************** +//** HttpServlet Class +//****************************************************************************** +/** + * Implementation of an HttpServlet used to process HTTP requests and + * generate a response. + * + ******************************************************************************/ + +public class HttpServlet implements javaxt.http.servlet.HttpServlet { + + private static ConcurrentHashMap<String, String> httpCache; + private static String serverName; + + //************************************************************************** + //** Constructor + //************************************************************************** + /** Creates a new instance of HttpServlet. */ + + public HttpServlet() { + serverName = "MapProxy Server " + mapproxy.config.Config.base_config().get("version").toString(); + httpCache = new ConcurrentHashMap<String, String>(); + } + + + //************************************************************************** + //** processRequest + //************************************************************************** + /** Used to process http get and post requests. */ + + public void processRequest(HttpServletRequest request, HttpServletResponse response) { + //long startTime = new java.util.Date().getTime(); + //long initResponse = 0; + //long initCache = 0; + try{ + Service service = ((mapproxy.core.Service) mapproxy.config.Config.base_config().get("mapproxy").toObject()); + ServiceResponse map = service.getResponse(request.getURL().toString(), new String(request.getBody(), "UTF-8")); + javaxt.utils.Date date = map.getDate(); + String key = map.getID(); + //initResponse = new java.util.Date().getTime()-startTime; + boolean useCache = useCache(request, key); + //initCache = new java.util.Date().getTime()-(initResponse+startTime); + if (useCache){ + + //Return 304 Response Code + response.setStatus(304, "Not Modified"); + response.setHeader("Date", date.toString("EEE, dd MMM yyyy HH:mm:ss zzz")); + response.setHeader("Server", serverName); + + } + else{ + + byte[] rsp = map.getByteArray(); + String contentType = map.getContentType(); + String eTag = "W/\"" + rsp.length + "-" + date.getTime() + "\""; + + + //Set header + response.setHeader("Date", date.toString("EEE, dd MMM yyyy HH:mm:ss zzz")); + response.setHeader("Server", serverName); + response.setHeader("Content-Type", contentType); + response.setHeader("Content-Length", rsp.length+""); + response.setHeader("ETag", eTag); + response.setHeader("Last-Modified", date.toString("EEE, dd MMM yyyy HH:mm:ss zzz")); //Sat, 23 Oct 2010 13:04:28 GMT + //header.append("Cache-Control", "max-age=" + (365*24*60*60)); //vs "no-cache" + //header.append("Accept-Ranges", "bytes"); + + + //Write body + response.write(rsp); + + + //Update the http cache + this.updateCache(key, eTag); + } + } + catch(Exception e){ + + //Return Error + response.setStatus(500); + response.setHeader("Server", serverName); + response.write(e.getLocalizedMessage()); + } + + //long ttl = new java.util.Date().getTime()-startTime; + //System.out.println(ttl + "\t" + (double)initResponse/(double)ttl + "\t" + (double)initCache/(double)ttl); + } + + + + //************************************************************************** + //** useCache + //************************************************************************** + /** Used to check whether the request is in the http cache. If so, sends a + * 304 http response and returns true. Otherwise, nothing is sent back to + * the client and the method returns false. + */ + private boolean useCache(HttpServletRequest request, String key) { + + if (key==null) return false; + + + String cacheControl = request.getHeader("cache-control"); + if (cacheControl==null) cacheControl = ""; + if (cacheControl.equalsIgnoreCase("no-cache")==false){ + + //Find the eTag that corresponds to this request + String eTag = null; + synchronized (httpCache){ + eTag = httpCache.get(key); + } + + if (eTag!=null){ + + String matchTag = request.getHeader("if-none-match"); + if (matchTag==null) matchTag = ""; + if (matchTag.equals(eTag)){ + //System.out.println("if-none-match"); + return true; + } + else{ + //Internet Explorer 6 uses "if-modified-since" instead of "if-none-match" + matchTag = request.getHeader("if-modified-since"); + if (matchTag!=null){ + String time = eTag.substring(eTag.lastIndexOf("-")+1, eTag.length()-1); + try{ + + javaxt.utils.Date date = new javaxt.utils.Date(Long.parseLong(time)); + date.setTimeZone("GMT"); + String d = date.toString("EEE, dd MMM yyyy HH:mm:ss zzz"); + + for (String tag: matchTag.split(";")){ + if (tag.trim().equals(d)){ + //System.out.println("if-modified-since"); + return true; + } + } + } + catch(Exception e){ + } + + } + + } + + } + + } + + + return false; + } + + + //************************************************************************** + //** updateCache + //************************************************************************** + /** Used to update the http cache. + */ + private void updateCache(String key, String eTag){ + if (key==null || eTag==null) return; + synchronized (httpCache){ + httpCache.put(key, eTag); //<-- Need to make this smarter so we don't run out of memory... + } + } + +} \ No newline at end of file Added: core/InvalidTileException.java =================================================================== --- core/InvalidTileException.java (rev 0) +++ core/InvalidTileException.java 2012-01-10 11:43:40 UTC (rev 39) @@ -0,0 +1,24 @@ +package mapproxy.core; + +//****************************************************************************** +//** Service Exception +//****************************************************************************** +/** + * Used to represent a server exception. Not yet implemented or used. + * + * Note that this class was not part of the original mapproxy baseline. + * + ******************************************************************************/ + +public class InvalidTileException extends Exception { + + + //************************************************************************** + //** Constructor + //************************************************************************** + /** Creates a new instance of Exception. */ + + public InvalidTileException() { + + } +} \ No newline at end of file Modified: core/Layer.java =================================================================== --- core/Layer.java 2012-01-10 11:42:33 UTC (rev 38) +++ core/Layer.java 2012-01-10 11:43:40 UTC (rev 39) @@ -6,7 +6,11 @@ import mapproxy.wms.cache.WMSTileSource; import mapproxy.arcgis.cache.*; import mapproxy.arcgis.client.*; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; +import javaxt.io.Directory; +import javaxt.io.File; //****************************************************************************** //** Layer Class @@ -25,9 +29,19 @@ private BBox bbox; private java.util.HashSet<String> srs = new java.util.HashSet<String>(); private java.util.List<Layer> layers = new java.util.ArrayList<Layer>(); + private static java.util.List<String> layerIDs = new java.util.ArrayList<String>(); + private int parentID = -1; private java.util.HashMap<String, Object> params = new java.util.HashMap<String, Object>(); + private static final ConcurrentHashMap<String, TileSeeder> ACTIVE_TASKS = new ConcurrentHashMap<String, TileSeeder>(); + // blank images to return if bbox does not intersect any catalog items + private static javaxt.io.Image image512; // 512 x 512 + private static javaxt.io.Image image256; // 256 x 256 + static { + image512 = new javaxt.io.Image(512, 512); + image256 = new javaxt.io.Image(256, 256); + } //************************************************************************** //** Constructor @@ -35,16 +49,38 @@ /** Creates a new instance of Layer. */ public Layer(String name) { - this.name = name; + this(name, -1); } public Layer(String name, int parentID) { this.name = name; this.parentID = parentID; + + String id = generateKey(); + synchronized(layerIDs){ + while (layerIDs.contains(id)){ + id = generateKey(); + } + layerIDs.add(id); + layerIDs.notifyAll(); + } + params.put("id", id); } + + //************************************************************************** + //** getID + //************************************************************************** + /** Returns the layer ID. + */ + public String getID(){ + return params.get("id").toString(); + } + + + //************************************************************************** //** getParentID //************************************************************************** /** Returns the parent layer ID. The parent ID should be a positive integer. @@ -218,16 +254,32 @@ } - @Override + //@Override public int compareTo(Object obj){ if (obj==null) return -1; else return -obj.toString().compareTo(name.toUpperCase()); } + public void invalidateTile(int[] tile, String format, String srs) { + FileCache fileCache = (FileCache) this.getParam("cache"); - - - + //Check whether we should use/create a map cache + boolean useCache = (fileCache!=null); + if (useCache) { + _Tile _tile = new _Tile(tile); + String location = fileCache.tile_location(_tile, false); + if (location != null && location.length() != 0) { + File file = new File(location); + if (file.exists()) { + file.delete(); + // System.err.println("invalid png deleted" + location); + } else { + // System.err.println("invalid png" + location); + } + } + } + } + //************************************************************************** //** getImage //************************************************************************** @@ -258,8 +310,20 @@ //Check whether we should use/create a map cache boolean useCache = (fileCache!=null); - if (useCache){ - useCache = this.getBBox().intersects(new BBox(bbox, srs)); + if (useCache) { + if (!this.getBBox().intersects(new BBox(bbox, srs))) { + // return the blank tile, no need to call the WMS + javaxt.io.Image image = null; + + if (width == 512 && height == 512) { + image = image512; + } else if (width == 256 && height == 256) { + image = image256; + } else { + image = new javaxt.io.Image(width, height); + } + return image; + } } @@ -282,7 +346,14 @@ WMSTileSource wms = new WMSTileSource(grid, new WMSClient(req)); CacheManager cacheManager = new CacheManager(fileCache, wms); Cache cache = new Cache(cacheManager, grid, true); - return cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()); + javaxt.io.Image image = null; + try { + image = cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()); + } + catch (Exception e) { + + } + return image; } } else if (protocol.equalsIgnoreCase("MapServer")){ @@ -294,7 +365,14 @@ MapTileSource arcMapServer = new MapTileSource(grid, new MapClient(req)); CacheManager cacheManager = new CacheManager(fileCache, arcMapServer); Cache cache = new Cache(cacheManager, grid, true); - return cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()); + javaxt.io.Image image = null; + try { + image = cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()); + } + catch (Exception e) { + + } + return image; } @@ -322,8 +400,18 @@ return this.getImage(width, height, format, bbox[0] + "," + bbox[1] + "," + bbox[2] + "," + bbox[3], srs); } + public Status seed(int numThreads, double[] bbox, String srs, int startLevel, int endLevel, + TileConsumer tileProcessor) { + TileSeeder tileseeder = new TileSeeder(); + synchronized (ACTIVE_TASKS) { + ACTIVE_TASKS.put(getParam("id").toString(), tileseeder); + ACTIVE_TASKS.notifyAll(); + } + return tileseeder.execute(this, numThreads, bbox, startLevel, endLevel, false, tileProcessor); + } + //************************************************************************** //** seedLayers //************************************************************************** @@ -336,13 +424,73 @@ * "Total Files", "Total Processed", and "Is Complete". */ public Status seed(int numThreads, double[] bbox, String srs, int startLevel, int endLevel){ - if (numThreads<1) numThreads = 1; - for (int i=0; i<numThreads; i++){ - Thread t = new Thread(new TileSeeder()); - t.start(); + return seed(numThreads, bbox, srs, startLevel, endLevel, null); + } + + public boolean stopSeedCache() { + boolean success= true; + synchronized (ACTIVE_TASKS) { + TileSeeder tileSeeder = ACTIVE_TASKS.get(getParam("id").toString()); + if (tileSeeder != null) { + success = tileSeeder.stop(); + } + ACTIVE_TASKS.remove(getParam("id").toString()); + ACTIVE_TASKS.notifyAll(); } + return success; + } + + public void invalidate(int numThreads, double[] bbox, String srs, int startLevel, int endLevel, TileConsumer tileProcessor){ + new TileSeeder().execute(this, numThreads, bbox, -1, -1, true, tileProcessor); + } - return TileSeeder.addLayer(this, bbox, startLevel, endLevel); + //returns the levels cached so far by looking at the cache directory + public List<Integer> getCachedLevels() { + List<Integer> levels = new ArrayList<Integer>(); + FileCache filecache = (FileCache)getParam("cache"); + if (filecache != null) { + javaxt.io.Directory dir = new javaxt.io.Directory(filecache.cache_dir); + if (dir.exists()) { + Directory[] children = dir.getSubDirectories(); + if (children != null && children.length != 0) { + for (int i=0; i < children.length; i++) { + Directory subDir = children[i]; + try { + int n = Integer.parseInt(subDir.getName()); + levels.add(n); + } + catch(NumberFormatException n) { + + } + } + } + } + } + return levels; } + + //************************************************************************** + //** generateKey + //************************************************************************** + /** Used to generate a 36 character unique id */ + + private String generateKey(){ + return CreateGUID(8) + "-" + + CreateGUID(4) + "-" + + CreateGUID(4) + "-" + + CreateGUID(4) + "-" + + CreateGUID(12); + } + + + private String CreateGUID(int tmpLength){ + String tmpGUID = ""; + final String strValid = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + for (int i = 1; i<=tmpLength; i++){ + int x = new java.util.Random().nextInt(strValid.length()); + tmpGUID += strValid.substring(x,x+1); + } + return tmpGUID; + } } \ No newline at end of file Modified: core/ServiceResponse.java =================================================================== --- core/ServiceResponse.java 2012-01-10 11:42:33 UTC (rev 38) +++ core/ServiceResponse.java 2012-01-10 11:43:40 UTC (rev 39) @@ -88,7 +88,7 @@ * applications where a server may only need the key to implement http * cache control. */ - private void init(boolean getBytes){ + private void init(boolean getBytes) throws InvalidTileException { if (getBytes && this.rsp!=null) return; @@ -239,7 +239,7 @@ /** Returns a byte array containing the response. The byte array can be used * in the body of an http response. */ - public byte[] getByteArray(){ + public byte[] getByteArray() throws Exception{ this.init(true); //<-- Inititalize the byte array... return rsp; } @@ -308,7 +308,7 @@ //************************************************************************** /** Used to construct a response to a TMS Map request */ - private void getTile(boolean getBytes) { + private void getTile(boolean getBytes) throws InvalidTileException{ //Set local variables String url = this.url.toString(); @@ -340,6 +340,9 @@ //Update tile coordinate req.tile = new mapproxy.tms.TileServiceGrid(grid).internal_tile_coord(req.tile, true); + if (req.tile == null) { + throw new InvalidTileException(); + } //Get Image @@ -355,17 +358,20 @@ Cache cache = new Cache(cacheManager, grid, true); - try{ + try { - //Find the requested tile in the cache. Note that this will throw an error if the tile doesn't exist - javaxt.io.File file = new javaxt.io.File(cache.tile(req.tile).location); - if (file.exists() && file.getSize()>0){ - if (file.getExtension().equalsIgnoreCase(format)){ + // Find the requested tile in the cache. Note that this will + // throw an error if the tile doesn't exist + javaxt.io.File file = new javaxt.io.File( + cache.tile(req.tile).location); + if (file.exists() && file.getSize() > 0) { + if (file.getExtension().equalsIgnoreCase(format)) { rsp = file.getBytes().toByteArray(); - } - else{ + } else { rsp = file.getImage().getByteArray(format); } + } else { + throw new Exception("No Tile found"); } } catch(Exception e){ Modified: core/Status.java =================================================================== --- core/Status.java 2012-01-10 11:42:33 UTC (rev 38) +++ core/Status.java 2012-01-10 11:43:40 UTC (rev 39) @@ -10,10 +10,16 @@ public class Status { - private int numTiles = 0; + private int numTilesSuccess = 0; + private int numTilesFail = 0; private int totalTiles = -1; private long lastUpdate = -1; - + private String lastStatus = ""; + public static String RUNNING = "Running"; + public static String COMPLETED = "Completed"; + public static String STOPPED = "Stopped"; + public static String FAILED = "Failed"; + //************************************************************************** //** Constructor //************************************************************************** @@ -34,7 +40,7 @@ public double getPercentComplete(){ if (totalTiles>0){ - return (double)numTiles/(double)totalTiles; + return (double)(numTilesSuccess+numTilesFail)/(double)totalTiles; } else{ return 0; @@ -42,20 +48,34 @@ } public boolean isComplete(){ - return (numTiles==totalTiles); + return (numTilesSuccess==totalTiles); } - protected void updateTileCount(){ - numTiles++; + protected void updateTileCount(boolean success){ + if (success) { + numTilesSuccess++; + } + else { + numTilesFail++; + } lastUpdate = new java.util.Date().getTime(); } public int getNumTilesProcessed(){ - return this.numTiles; + return this.numTilesSuccess; } + public int getNumTilesFailed(){ + return this.numTilesFail; + } public int getTotalTiles(){ return this.totalTiles; } - + public String getLastStatus(){ + return this.lastStatus; + } + public void setLastStatus(String value){ + this.lastStatus = value; + } + } Added: core/TileConsumer.java =================================================================== --- core/TileConsumer.java (rev 0) +++ core/TileConsumer.java 2012-01-10 11:43:40 UTC (rev 39) @@ -0,0 +1,9 @@ +package mapproxy.core; + +public interface TileConsumer +{ + void init(int numThreads); + void noMoreTiles(); + void shutdown(); + void processTile(TileListener callback, Layer layer, int[] tile, boolean invalidate); +} \ No newline at end of file Added: core/TileListener.java =================================================================== --- core/TileListener.java (rev 0) +++ core/TileListener.java 2012-01-10 11:43:40 UTC (rev 39) @@ -0,0 +1,6 @@ +package mapproxy.core; + +public interface TileListener +{ + void doneProcessingTile(boolean success); +} \ No newline at end of file Modified: core/TileSeeder.java =================================================================== --- core/TileSeeder.java 2012-01-10 11:42:33 UTC (rev 38) +++ core/TileSeeder.java 2012-01-10 11:43:40 UTC (rev 39) @@ -1,291 +1,375 @@ package mapproxy.core; import mapproxy.core.cache.*; import mapproxy.core.grid.TileGrid; -import java.util.concurrent.ConcurrentHashMap; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; //****************************************************************************** //** TileSeeder Class //****************************************************************************** /** - * Thread used to generate a tile cache - * + * Thread used to generate a tile cache + * ******************************************************************************/ -public class TileSeeder implements Runnable { +public class TileSeeder implements TileListener { + ExecutorService _exec = null; + private static int MAX_TILES_IN_PROCESS = 25; + private Status status = null; + private Integer tilesInQueue = 0; + private TileIterator iterator = null; + private TileConsumer tileProcessor = null; + boolean isStopped=false; - private static java.util.List<Object[]> seeds = new java.util.LinkedList<Object[]>(); - private static ConcurrentHashMap<Integer, Layer> layers = new ConcurrentHashMap<Integer, Layer>(); + //************************************************************************** + //** Constructor + //************************************************************************** + /** Creates a new instance of TileSeeder. */ + public TileSeeder() { + } - private static ConcurrentHashMap<Integer, Status> stats = new ConcurrentHashMap<Integer, Status>(); - - //************************************************************************** - //** TileIterator + //** TileIterator Class //************************************************************************** - /** Class used to iterate through tiles and add them to the queue */ + /** Class used to iterate through tiles and add them to the queue */ - private static class TileIterator implements Runnable { - int layerID; + private static class TileIterator extends Thread { + private Layer layer = null; private double[] bbox; private int startLevel; private int endLevel; - private TileIterator(int layerID, double[] bbox, int startLevel, int endLevel){ - this.layerID = layerID; + private boolean invalidate; + private TileSeeder tileSeeder = null; + + private TileIterator(Layer layer, TileSeeder tileSeeder, + double[] bbox, int startLevel, int endLevel, boolean invalidate) { + this.layer = layer; + this.tileSeeder = tileSeeder; this.bbox = bbox; this.startLevel = startLevel; this.endLevel = endLevel; + this.invalidate = invalidate; } - public void run(){ + public void cancel() { + //System.err.println("TileIterator interrupted"); + this.interrupt(); + } + public void run() { + try { + tileSeeder.updateTotalTiles(-1); + // System.err.println("In TileIterator"); + int totalTiles = 0; + TileGrid grid = (TileGrid) layer.getParam("grid"); + if (Thread.currentThread().isInterrupted()) { + tileSeeder.noMoreTiles(); + return; + } - Layer layer; - synchronized (layers) { - layer = layers.get(layerID); - layers.notifyAll(); - } + List<Integer> levels = null; + if (startLevel == -1 && endLevel == -1) { + levels = layer.getCachedLevels(); + } else { + levels = new ArrayList<Integer>(); + for (int level = startLevel; level < endLevel + 1; level++) { + levels.add(level); + } + } + List<Generator<int[]>> generators = new ArrayList<Generator<int[]>>(); + for (int l = 0; l < levels.size(); l++) { + if (Thread.currentThread().isInterrupted()) { + tileSeeder.noMoreTiles(); + return; + } + int level = levels.get(l); + Object[] arr = _create_tile_iterator(grid, bbox, level); + int est_number_of_tiles = (Integer) arr[0]; + Generator<int[]> tiles = (Generator<int[]>) arr[1]; + generators.add(tiles); + totalTiles += est_number_of_tiles; + } + tileSeeder.updateTotalTiles(totalTiles); - TileGrid grid = (TileGrid) layer.getParam("grid"); - - - int numTiles = 0; - for (int level=startLevel; level<endLevel+1; level++){ - Object[] arr = _create_tile_iterator(grid, bbox, level); - //int est_number_of_tiles = (Integer) arr[0]; - Generator<int[]> tiles = (Generator<int[]>) arr[1]; - - - for (int[] tile : tiles){ - - synchronized (seeds) { - seeds.add(seeds.size(), new Object[]{layerID, tile}); - seeds.notifyAll(); + // System.err.println("total tiles " + totalTiles); + int addedCnt = 0; + for (int l = 0; l < generators.size(); l++) { + Generator<int[]> tiles = generators.get(l); + for (int[] tile : tiles) { + if (Thread.currentThread().isInterrupted()) { + tileSeeder.noMoreTiles(); + return; + } + boolean added = false; + while (tileSeeder.waitToAddTile()) { + try { + // System.err.println("waiting to add tile"); + Thread.sleep(1000); + } catch (InterruptedException e) { + // System.err.println("Leaving TileIterator - interrupted"); + tileSeeder.noMoreTiles(); + return; + } + } + tileSeeder.processTile(layer, tile, invalidate); } - - numTiles++; - } - + // System.err.println("TileIterator DONE total tiles " + + // totalTiles); + tileSeeder.noMoreTiles(); + } catch (Exception e) { + tileSeeder.noMoreTiles(); } + // System.err.println("Leaving TileIterator."); + } + } - //Update the stats for this layer - synchronized (stats){ - Status status = stats.get(layerID); - synchronized (status){ - status.setTotal(numTiles); - status.notifyAll(); - } - - //stats.get(layerID).setTotal(numTiles); - stats.notifyAll(); + public boolean waitToAddTile() { + synchronized (tilesInQueue) { + if (tilesInQueue >= MAX_TILES_IN_PROCESS) { + return true; } + } + return false; + } - - /* - //Add null tile to notify the threads that we are done - synchronized (seeds) { - seeds.add(seeds.size(), new Object[]{layerID, numTiles}); - seeds.notifyAll(); + public void doneProcessingTile(boolean success) { + synchronized (tilesInQueue) { + tilesInQueue--; + } + // System.err.println("before updating tile cnt"); + synchronized (status) { + status.updateTileCount(success); + if (status.getNumTilesProcessed() == status.getTotalTiles()) { + status.setLastStatus(Status.COMPLETED); + } else { + if (status.getNumTilesFailed() != 0) { + if (status.getNumTilesFailed() + status.getNumTilesProcessed() == status.getTotalTiles()) { + status.setLastStatus(Status.FAILED); + } + else { + status.setLastStatus(Status.RUNNING); + } } - */ + else { + status.setLastStatus(Status.RUNNING); + } + } + + // System.err.println("after updating tile cnt"); + status.notifyAll(); + } + } + public void noMoreTiles() { + tileProcessor.noMoreTiles(); + } + public void processTile(Layer layer, int[] tile, boolean invalidate) { + if (isStopped) { + return; } + synchronized (tilesInQueue) { + tilesInQueue++; + } + // System.err.println("before calling seedtask"); + tileProcessor.processTile(this, layer, tile, invalidate); } //************************************************************************** - //** Constructor + //** _create_tile_iterator //************************************************************************** - /** Creates a new instance of TileSeeder. */ + /** Return all tiles that intersect the `bbox` on `level`. + * @return estimated number of tiles, tile iterator + */ + private static Object[] _create_tile_iterator(TileGrid grid, double[] bbox, + int level) { - public TileSeeder(){ + double res = grid.resolution(level); + int[] pixelSize = bbox_pixel_size(bbox, res); + int w = pixelSize[0]; + int h = pixelSize[1]; + + Object[] affected_tiles = grid.get_affected_tiles(bbox, pixelSize, + null, false); + bbox = (double[]) affected_tiles[0]; + int[] extents = (int[]) affected_tiles[1]; + int est_number_of_tiles = extents[0] * extents[1]; + Generator<int[]> tiles = (Generator<int[]>) affected_tiles[2]; + return new Object[] { est_number_of_tiles, tiles }; } - //************************************************************************** - //** addLayer + //** bbox_pixel_size //************************************************************************** - /** Used to add a layer for the TileSeeder to process. */ + /** Return the size of the `bbox` in pixel at the given `res`. + */ + private static int[] bbox_pixel_size(double[] bbox, double res) { + double w = bbox[2] - bbox[0]; + double h = bbox[3] - bbox[1]; + return new int[] { cint(w / res), cint(h / res) }; + } - public static Status addLayer(Layer layer, double[] bbox, int startLevel, int endLevel){ + private static int cint(double d) { + return javaxt.utils.string.toInt(d); + } + // ************************************************************************** + // ** execute + // ************************************************************************** + /** Used to add a layer for the TileSeeder to process. */ + public Status execute(Layer layer, int numThreads, double[] bbox, + int startLevel, int endLevel, boolean invalidate, TileConsumer tileProcessor) { + FileCache cache = (FileCache) layer.getParam("cache"); TileGrid grid = (TileGrid) layer.getParam("grid"); - if (cache==null || grid==null) return null; + if (cache == null || grid == null) + return null; - - int layerID; - synchronized (layers) { - layerID = layers.size(); - layers.put(layerID, layer); - layers.notifyAll(); + status = new Status(); + synchronized (status) { + status.setTotal(0); + status.setLastStatus(Status.RUNNING); + status.notifyAll(); } + + if (tileProcessor != null) { + this.tileProcessor = tileProcessor; + } + else { + this.tileProcessor = new TileProcessor(this); + } + this.tileProcessor.init(numThreads); + + iterator = new TileIterator(layer, this, bbox, startLevel, endLevel, + invalidate); + iterator.start(); - - Status status = new Status(); - - synchronized (stats){ - stats.put(layerID, status); - stats.notifyAll(); - } - - new Thread(new TileIterator(layerID, bbox, startLevel, endLevel)).run(); - return status; + } + private void updateTotalTiles(int totalTiles) { + synchronized (status) { + status.setTotal(totalTiles); + status.notifyAll(); + } } - - /* - public static void stop(){ - synchronized (seeds) { - seeds.add(seeds.size(), null); - seeds.notifyAll(); + public boolean stop() { + isStopped = true; + try { + if (iterator != null) { + iterator.cancel(); + } + //System.err.println("TileProcessor shutdown"); + tileProcessor.shutdown(); + // System.err.println("TileSeeder Shutdown success ? : " + + synchronized (status) { + status.setLastStatus(Status.STOPPED); + status.notifyAll(); + } + } catch (Exception e) { + //System.err.println("TILESEEDER STOP EXCEPTION " + e.getMessage()); + return false; } + return true; } - */ //************************************************************************** - //** run + //** TileProcessor Class //************************************************************************** - /** Used to process tiles added to the queue. */ + /** Class used to iterate through tiles and add them to the queue */ - public void run(){ - while (true) { - - //Find request in pool - Object[] arr; - synchronized (seeds) { - while (seeds.isEmpty()) { - try { - seeds.wait(); - } - catch (InterruptedException e) { - e.printStackTrace(); - } + public class TileProcessor implements TileConsumer { + TileListener callback=null; + public TileProcessor (TileListener callback) { + this.callback = callback; + } + public void init(int numThreads) { + _exec = Executors.newFixedThreadPool(numThreads); + } + public void noMoreTiles() { + _exec.shutdown(); + boolean result = false; + try { + // System.out.println("Awaiting map cache task completion"); + result = _exec.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); + } catch (InterruptedException ie) { + // TODO: Log here + // System.out.println("InterruptedException"); } - arr = (Object[]) seeds.remove(0); - if (arr==null){ - seeds.add(null); - seeds.notifyAll(); - return; - } - } + // System.out.println("result = " + result); + // System.err.println("shutdown complete"); + } + public void shutdown() { + _exec.shutdownNow(); + } + public void processTile(TileListener callback, Layer layer, int[] tile, boolean invalidate) { + _exec.execute(new SeedTask(layer, callback, tile, invalidate)); + } + } + //************************************************************************** + //** SeedTask + //************************************************************************** + /** Class used to iterate through tiles and add them to the queue */ + public class SeedTask implements Runnable { + Layer layer; + TileListener tileListener; + int[] tile; + boolean invalidate; - Layer layer; - int layerID = (Integer) arr[0]; - synchronized (layers) { - layer = layers.get(layerID); - layers.notifyAll(); - } + public SeedTask(Layer layer, TileListener tileListener, int[] tile, + boolean invalidate) { + this.layer = layer; + this.tileListener = tileListener; + this.tile = tile; + this.invalidate = invalidate; + } - Object obj = arr[1]; - if (obj instanceof int[]){ - int[] tile = (int[]) obj; - FileCache cache = (FileCache) layer.getParam("cache"); - TileGrid grid = (TileGrid) layer.getParam("grid"); - try { - layer.getImage(grid.tile_size[0], grid.tile_size[1], cache.file_ext, grid.tile_bbox(tile[0],tile[1],tile[2]), grid.srs.toString()); - } - catch (Exception e) { - e.printStackTrace(); - } - /* - System.out.println(Python.cstr(tile)); - try{ - Thread.sleep(500); - } - catch(Exception e){} - */ - synchronized (stats){ - //Integer numTiles = (Integer) stats.get(layerID).get("Total Processed"); - //if (numTiles==null) numTiles = 0; - Status status = stats.get(layerID); - synchronized (status){ - status.updateTileCount(); - status.notifyAll(); - } - - stats.notifyAll(); - } - - - /* - synchronized (stats){ - Integer total = (Integer) stats.get(layerID).get("Total Files"); - if (total!=null){ - Integer numTiles = (Integer) stats.get(layerID).get("Total Processed"); - if (numTiles==null) numTiles = 0; - if (numTiles==total){ - stats.get(layerID).put("Is Complete", true); + /** Used to process tiles */ + public void run() { + boolean success = true; + //System.err.println("in seed cache task"); + if (tile != null) { + FileCache cache = (FileCache) layer.getParam("cache"); + TileGrid grid = (TileGrid) layer.getParam("grid"); + try { + if (!invalidate) { + //System.err.println("in layer image"); + javaxt.io.Image img = layer.getImage(grid.tile_size[0], + grid.tile_size[1], cache.file_ext, grid + .tile_bbox(tile[0], tile[1], tile[2]), + grid.srs.toString()); + if (img == null) { + success = false; } + } else { + // System.err.println("before tileseeder invalidate bbox"); + layer.invalidateTile(tile, cache.file_ext, grid.srs + .toString()); } - stats.notifyAll(); + } catch (Exception e) { + success = false; + e.printStackTrace(); } - */ - - - } - - - - - } // end while + // System.err.println("done processing tile " + tileid); + } + tileListener.doneProcessingTile(success); + } } - - - - - - //************************************************************************** - //** _create_tile_iterator - //************************************************************************** - /** Return all tiles that intersect the `bbox` on `level`. - * @return estimated number of tiles, tile iterator - */ - private static Object[] _create_tile_iterator(TileGrid grid, double[] bbox, int level){ - - double res = grid.resolution(level); - int[] pixelSize = bbox_pixel_size(bbox, res); - int w = pixelSize[0]; - int h = pixelSize[1]; - - Object[] affected_tiles = grid.get_affected_tiles(bbox, pixelSize, null, false); - bbox = (double[]) affected_tiles[0]; - //int[] _grid = (int[]) affected_tiles[1]; - Generator<int[]> tiles = (Generator<int[]>) affected_tiles[2]; - - int est_number_of_tiles = cint((w/grid.tile_size[0] * - h/grid.tile_size[1])); - return new Object[]{est_number_of_tiles, tiles}; - } - - - //************************************************************************** - //** bbox_pixel_size - //************************************************************************** - /** Return the size of the `bbox` in pixel at the given `res`. - */ - private static int[] bbox_pixel_size(double[] bbox, double res){ - double w = bbox[2] - bbox[0]; - double h = bbox[3] - bbox[1]; - return new int[]{cint(w/res), cint(h/res)}; - } - - private static int cint(double d){ - return javaxt.utils.string.toInt(d); - } - -} +} \ No newline at end of file Modified: core/cache/Cache.java =================================================================== --- core/cache/Cache.java 2012-01-10 11:42:33 UTC (rev 38) +++ core/cache/Cache.java 2012-01-10 11:43:40 UTC (rev 39) @@ -83,7 +83,7 @@ * @param out_size the target output size * @return 'ImageSource` */ - private TiledImage _tiled_image(double[] req_bbox, SRS req_srs, int[] out_size){ + private TiledImage _tiled_image(double[] req_bbox, SRS req_srs, int[] out_size) throws Exception { Object[] arr = this.grid.get_affected_tiles(req_bbox, out_size, req_srs, false); double[] src_bbox = (double[]) arr[0]; @@ -102,6 +102,9 @@ TileCollection tiles = this._tiles(affected_tile_coords); javaxt.io.Image[] tile_sources = new javaxt.io.Image[tiles.size()]; for (int i=0; i<tiles.size(); i++){ + if (tiles.get(i).is_missing()) { + throw new Exception("Tile is missing."); + } tile_sources[i] = tiles.get(i).source; } @@ -122,7 +125,7 @@ * @param out_size the output size * @return `ImageSource` */ - public javaxt.io.Image image(double[] req_bbox, SRS req_srs, int[] out_size){ + public javaxt.io.Image image(double[] req_bbox, SRS req_srs, int[] out_size) throws Exception{ if (!this.grid.srs.equals(req_srs)){ System.out.println("src_srs: " + this.grid.srs); System.out.println("req_srs: " + req_srs); @@ -130,7 +133,17 @@ TiledImage tiled_image = this._tiled_image(req_bbox, req_srs, out_size); return tiled_image.transform(req_bbox, req_srs, out_size); } + + public TileCollection getInvalidTiles(double[] req_bbox, SRS req_srs, int[] out_size) { + System.err.println("in cache invalidate bbox"); + Object[] arr = this.grid.get_affected_tiles(req_bbox, out_size, req_srs, false); + double[] src_bbox = (double[]) arr[0]; + int[] tile_grid = (int[]) arr[1]; + Generator<int[]> affected_tile_coords = (Generator<int[]>) arr[2]; + TileCollection tiles = new TileCollection(affected_tile_coords); + return tiles; + } //************************************************************************** Modified: core/cache/_Tile.java =================================================================== --- core/cache/_Tile.java 2012-01-10 11:42:33 UTC (rev 38) +++ core/cache/_Tile.java 2012-01-10 11:43:40 UTC (rev 39) @@ -102,6 +102,9 @@ if (other==null) return false; if (other instanceof _Tile){ _Tile tile = (_Tile) other; + if (tile.coord == null || this.coord == null || tile.source == null || this.source == null) { + return false; + } if ( tile.coord.equals(this.coord) && tile.source.equals(this.source)){ return true; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2012-01-10 11:42:44
|
Revision: 38 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=38&view=rev Author: pborissow Date: 2012-01-10 11:42:33 +0000 (Tue, 10 Jan 2012) Log Message: ----------- Deprecating the "mapproxy.server" package. See next commit for more information. Removed Paths: ------------- server/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rmk...@us...> - 2011-08-01 14:06:35
|
Revision: 37 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=37&view=rev Author: rmkazden Date: 2011-08-01 14:06:29 +0000 (Mon, 01 Aug 2011) Log Message: ----------- Add startLevel/endLevel for seeding Modified Paths: -------------- Main.java core/Layer.java core/TileSeeder.java Modified: Main.java =================================================================== --- Main.java 2011-05-25 11:13:52 UTC (rev 36) +++ Main.java 2011-08-01 14:06:29 UTC (rev 37) @@ -313,12 +313,13 @@ double[] bbox = new double[]{-180,-90,180,90}; String srs = "EPSG:4326"; - int levels = 12; + int startLevel = 1; + int endLevel = 12; Config.load(getConfig(args)); Service service = ((mapproxy.core.Service) mapproxy.config.Config.base_config().get("mapproxy").toObject()); Layer layer = service.getLayers()[0]; - Status status = layer.seed(2, bbox, srs, levels); + Status status = layer.seed(2, bbox, srs, startLevel, endLevel); long lastUpdate = -1; Modified: core/Layer.java =================================================================== --- core/Layer.java 2011-05-25 11:13:52 UTC (rev 36) +++ core/Layer.java 2011-08-01 14:06:29 UTC (rev 37) @@ -335,14 +335,14 @@ * @return Returns a HashMap with status information. Keys include * "Total Files", "Total Processed", and "Is Complete". */ - public Status seed(int numThreads, double[] bbox, String srs, int levels){ + public Status seed(int numThreads, double[] bbox, String srs, int startLevel, int endLevel){ if (numThreads<1) numThreads = 1; for (int i=0; i<numThreads; i++){ Thread t = new Thread(new TileSeeder()); t.start(); } - return TileSeeder.addLayer(this, bbox, levels); + return TileSeeder.addLayer(this, bbox, startLevel, endLevel); } } \ No newline at end of file Modified: core/TileSeeder.java =================================================================== --- core/TileSeeder.java 2011-05-25 11:13:52 UTC (rev 36) +++ core/TileSeeder.java 2011-08-01 14:06:29 UTC (rev 37) @@ -29,11 +29,13 @@ private static class TileIterator implements Runnable { int layerID; private double[] bbox; - private int levels; - private TileIterator(int layerID, double[] bbox, int levels){ + private int startLevel; + private int endLevel; + private TileIterator(int layerID, double[] bbox, int startLevel, int endLevel){ this.layerID = layerID; this.bbox = bbox; - this.levels = levels; + this.startLevel = startLevel; + this.endLevel = endLevel; } public void run(){ @@ -49,7 +51,7 @@ int numTiles = 0; - for (int level=0; level<levels; level++){ + for (int level=startLevel; level<endLevel+1; level++){ Object[] arr = _create_tile_iterator(grid, bbox, level); //int est_number_of_tiles = (Integer) arr[0]; Generator<int[]> tiles = (Generator<int[]>) arr[1]; @@ -111,7 +113,7 @@ //************************************************************************** /** Used to add a layer for the TileSeeder to process. */ - public static Status addLayer(Layer layer, double[] bbox, int levels){ + public static Status addLayer(Layer layer, double[] bbox, int startLevel, int endLevel){ FileCache cache = (FileCache) layer.getParam("cache"); @@ -134,7 +136,7 @@ stats.notifyAll(); } - new Thread(new TileIterator(layerID, bbox, levels)).run(); + new Thread(new TileIterator(layerID, bbox, startLevel, endLevel)).run(); return status; @@ -193,7 +195,12 @@ int[] tile = (int[]) obj; FileCache cache = (FileCache) layer.getParam("cache"); TileGrid grid = (TileGrid) layer.getParam("grid"); - layer.getImage(grid.tile_size[0], grid.tile_size[1], cache.file_ext, grid.tile_bbox(tile[0],tile[1],tile[2]), grid.srs.toString()); + try { + layer.getImage(grid.tile_size[0], grid.tile_size[1], cache.file_ext, grid.tile_bbox(tile[0],tile[1],tile[2]), grid.srs.toString()); + } + catch (Exception e) { + e.printStackTrace(); + } /* System.out.println(Python.cstr(tile)); try{ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-05-25 11:13:58
|
Revision: 36 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=36&view=rev Author: pborissow Date: 2011-05-25 11:13:52 +0000 (Wed, 25 May 2011) Log Message: ----------- Added check in the Layer.getImage() method to prevent clients from building map caches outside the layer extents Modified Paths: -------------- core/BBox.java core/Layer.java core/Service.java Modified: core/BBox.java =================================================================== --- core/BBox.java 2011-05-24 09:53:28 UTC (rev 35) +++ core/BBox.java 2011-05-25 11:13:52 UTC (rev 36) @@ -1,4 +1,6 @@ package mapproxy.core; +import org.geotools.geometry.jts.ReferencedEnvelope; +import org.opengis.referencing.crs.CoordinateReferenceSystem; //****************************************************************************** //** BBOX Class @@ -27,6 +29,8 @@ this.minY = minY; this.maxX = maxX; this.maxY = maxY; + + if (srs==null) srs = "EPSG:4326"; this.srs = srs; } @@ -40,7 +44,7 @@ //************************************************************************** /** "bbox" as a tuple (minx, miny, maxx, maxy). */ - public BBox(String bbox){ + public BBox(String bbox, String srs){ if (bbox==null) return; //Throw Exception? @@ -53,10 +57,17 @@ minY = box[1]; maxX = box[2]; maxY = box[3]; + + if (srs==null) srs = "EPSG:4326"; + this.srs = srs; } + public BBox(String bbox){ + this(bbox,null); + } + public double getMinX(){ return minX; } @@ -96,4 +107,28 @@ box[3] = maxY; return box; } + + + public boolean intersects(BBox bbox){ + try{ + ReferencedEnvelope envelope = this.getEnvelope(); + CoordinateReferenceSystem crs = envelope.getCoordinateReferenceSystem(); + return envelope.intersects(bbox.getEnvelope().toBounds(crs)); + } + catch(Exception e){ + return false; + } + } + + + private org.geotools.geometry.jts.ReferencedEnvelope envelope; + public org.geotools.geometry.jts.ReferencedEnvelope getEnvelope(){ + if (envelope==null){ + SRS srs = new SRS(this.getSRS()); + envelope = new org.geotools.geometry.jts.ReferencedEnvelope( srs.crs ); + envelope.include(this.getMinX(), this.getMinY()); + envelope.include(this.getMaxX(), this.getMaxY()); + } + return envelope; + } } \ No newline at end of file Modified: core/Layer.java =================================================================== --- core/Layer.java 2011-05-24 09:53:28 UTC (rev 35) +++ core/Layer.java 2011-05-25 11:13:52 UTC (rev 36) @@ -256,7 +256,15 @@ req.params.set("srs", srs); + //Check whether we should use/create a map cache + boolean useCache = (fileCache!=null); + if (useCache){ + useCache = this.getBBox().intersects(new BBox(bbox, srs)); + } + + + //if (format.equalsIgnoreCase("image/PNG24")) format = "jpeg"; //<-- This is crazy! If I return a 24 bit PNG, ArcMap doesn't display anything. If I return a JPEG, works like a champ if (!format.toLowerCase().startsWith("image/")) format = "image/" + format; if (format.equalsIgnoreCase("image/jpg")) format = "image/jpeg"; @@ -267,7 +275,7 @@ String protocol = (String) this.getParam("protocol"); if (protocol.equalsIgnoreCase("WMS")){ - if (fileCache==null){ + if (!useCache){ return new WMSClient(req).get_map(req); } else{ @@ -279,7 +287,7 @@ } else if (protocol.equalsIgnoreCase("MapServer")){ - if (fileCache==null){ + if (!useCache){ return new MapClient(req).get_map(req); } else{ @@ -292,7 +300,7 @@ } else if (protocol.equalsIgnoreCase("TMS")){ - if (fileCache==null){ + if (!useCache){ Object[] affected_tiles = grid.get_affected_tiles(new BBox(bbox).toArray(), new int[]{width, height}, new SRS(srs), false); double[] box = (double[]) affected_tiles[0]; @@ -334,8 +342,6 @@ t.start(); } - - return TileSeeder.addLayer(this, bbox, levels); } Modified: core/Service.java =================================================================== --- core/Service.java 2011-05-24 09:53:28 UTC (rev 35) +++ core/Service.java 2011-05-25 11:13:52 UTC (rev 36) @@ -260,25 +260,19 @@ private class BBoxCalculator{ org.geotools.geometry.jts.ReferencedEnvelope envelope; + org.opengis.referencing.crs.CoordinateReferenceSystem crs; public BBoxCalculator(Layer[] layers) throws Exception { - envelope = new org.geotools.geometry.jts.ReferencedEnvelope( org.geotools.referencing.CRS.decode("EPSG:4326", true) ); + crs = org.geotools.referencing.CRS.decode("EPSG:4326", true); + envelope = new org.geotools.geometry.jts.ReferencedEnvelope(crs); this.addLayers(layers); } private void addLayers(Layer[] layers) throws Exception { for (Layer layer : layers){ - - BBox bbox = layer.getBBox(); - SRS srs = new SRS(bbox.getSRS()); - + try{ - org.geotools.geometry.jts.ReferencedEnvelope - envelope = new org.geotools.geometry.jts.ReferencedEnvelope( srs.crs ); - - envelope.include(bbox.getMinX(), bbox.getMinY()); - envelope.include(bbox.getMaxX(), bbox.getMaxY()); - this.envelope.include(envelope.toBounds(this.envelope.getCoordinateReferenceSystem())); + this.envelope.include(layer.getBBox().getEnvelope().toBounds(crs)); } catch(Exception e){ e.printStackTrace(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-05-24 09:53:34
|
Revision: 35 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=35&view=rev Author: pborissow Date: 2011-05-24 09:53:28 +0000 (Tue, 24 May 2011) Log Message: ----------- - Added new method to calculate extents of all the layers in a service - Updated config parser to process capabilities URLs - Updated the KML Superoverlay to return bounding coordinates for each layer Modified Paths: -------------- config/Config.java config.xml core/Service.java kml/server/KMLServer.java Modified: config/Config.java =================================================================== --- config/Config.java 2011-05-17 01:56:15 UTC (rev 34) +++ config/Config.java 2011-05-24 09:53:28 UTC (rev 35) @@ -1,6 +1,7 @@ package mapproxy.config; import mapproxy.core.cache.FileCache; import mapproxy.core.grid.TileGrid; +import mapproxy.core.Service; //****************************************************************************** //** Config Class @@ -77,7 +78,9 @@ mapproxy.core.Service mapproxy = new mapproxy.core.Service(name, "http://localhost:" + port); mapproxy.setDescription(description); + java.util.HashMap<String, Service> services = new java.util.HashMap<String, Service>(); + //Parse layer info and create service layers for (int i=0; i<layerNodes.getLength(); i++){ org.w3c.dom.Node layerNode = layerNodes.item(i); @@ -91,7 +94,9 @@ String protocol = "WMS"; int[] tile_size = new int[]{256,256}; + Service service = null; + org.w3c.dom.NodeList params = layerNode.getChildNodes(); for (int j=0; j<params.getLength(); j++){ org.w3c.dom.Node param = params.item(j); @@ -124,6 +129,16 @@ protocol = javaxt.xml.DOM.getAttributeValue(node.getAttributes(), "protocol"); } + if (node.getNodeName().equalsIgnoreCase("Capabilities")){ + String capabilities = node.getTextContent(); + service = services.get(capabilities); + if (service==null){ + service = new Service(capabilities); + services.put(capabilities, service); + } + host = service.getURL(); + protocol = service.getProtocol(); + } if (node.getNodeName().equalsIgnoreCase("layers")){ layers = node.getTextContent(); if (layers==null || layers.trim().length()==0){ @@ -179,11 +194,27 @@ mapproxy.core.Layer layer = new mapproxy.core.Layer(layerName); layer.addSRS("EPSG:4326"); - layer.setBBox(new mapproxy.core.BBox(-180,-90,180,90,"EPSG:4326")); layer.setParam("host", host); layer.setParam("layers", layers); layer.setParam("protocol", protocol); + + //Calculate BBox using service metadata + if (service!=null){ + java.util.ArrayList<mapproxy.core.Layer> arr = new java.util.ArrayList<mapproxy.core.Layer>(); + for (String str : layers.split(",")){ + arr.add(service.getLayer(str)); + } + mapproxy.core.BBox bbox = service.getBBox(arr.toArray(new mapproxy.core.Layer[arr.size()])); + layer.setBBox(bbox); + } + else{ + layer.setBBox(new mapproxy.core.BBox(-180,-90,180,90,"EPSG:4326")); + } + + + + if (cacheDir!=null){ layer.setParam("cache", new FileCache(cacheDir, cacheFormat)); layer.setParam("grid", new TileGrid(4326, tile_size)); Modified: config.xml =================================================================== --- config.xml 2011-05-17 01:56:15 UTC (rev 34) +++ config.xml 2011-05-24 09:53:28 UTC (rev 35) @@ -31,6 +31,19 @@ </Layer> <Layer> + <Name>Cities</Name> + <Host> + <Capabilities> + <![CDATA[ + http://localhost:6277/cgi-bin/mapserv.exe?map=/data/world.map&service=wms&request=GetCapabilities&version=1.1.1 + ]]> + </Capabilities> + <Layers>uscities_rank2</Layers> + </Host> + </Layer> + + + <Layer> <Name>Country Labels</Name> <Host> <BaseRequest protocol="WMS"> Modified: core/Service.java =================================================================== --- core/Service.java 2011-05-17 01:56:15 UTC (rev 34) +++ core/Service.java 2011-05-24 09:53:28 UTC (rev 35) @@ -87,6 +87,7 @@ } else{ System.out.println("Media: " + media); + //System.out.println(response.getText()); } } @@ -238,6 +239,73 @@ //************************************************************************** + //** getBBox + //************************************************************************** + /** Returns the bbox for this service. The bbox is computed by interating + * through all the layers associated with this service. + */ + public BBox getBBox(){ + return getBBox(getLayers()); + } + + public BBox getBBox(Layer[] layers){ + try{ + return new BBoxCalculator(layers).getBBox(); + } + catch(Exception e){ + return new BBox(-180, -90, 180, 90); + } + } + + private class BBoxCalculator{ + + org.geotools.geometry.jts.ReferencedEnvelope envelope; + + public BBoxCalculator(Layer[] layers) throws Exception { + envelope = new org.geotools.geometry.jts.ReferencedEnvelope( org.geotools.referencing.CRS.decode("EPSG:4326", true) ); + this.addLayers(layers); + } + + private void addLayers(Layer[] layers) throws Exception { + for (Layer layer : layers){ + + BBox bbox = layer.getBBox(); + SRS srs = new SRS(bbox.getSRS()); + + try{ + org.geotools.geometry.jts.ReferencedEnvelope + envelope = new org.geotools.geometry.jts.ReferencedEnvelope( srs.crs ); + + envelope.include(bbox.getMinX(), bbox.getMinY()); + envelope.include(bbox.getMaxX(), bbox.getMaxY()); + this.envelope.include(envelope.toBounds(this.envelope.getCoordinateReferenceSystem())); + } + catch(Exception e){ + e.printStackTrace(); + } + + if (layer.hasLayers()){ + this.addLayers(layer.getLayers()); + } + } + } + + public BBox getBBox() throws Exception { + + org.geotools.metadata.iso.extent.GeographicBoundingBoxImpl bbox = + new org.geotools.metadata.iso.extent.GeographicBoundingBoxImpl(envelope); + + double minX = bbox.getWestBoundLongitude(); + double minY = bbox.getSouthBoundLatitude(); + double maxX = bbox.getEastBoundLongitude(); + double maxY = bbox.getNorthBoundLatitude(); + + return new BBox(minX, minY, maxX, maxY); + } + } + + + //************************************************************************** //** getResponse //************************************************************************** /** Used to generate a response to a service request. The response might @@ -653,7 +721,7 @@ boxSRS = attr.getNodeValue(); } } - bbox = new BBox(minX, minY, maxX, maxY, boxSRS); + bbox = new BBox(minX, minY, maxX, maxY, boxSRS); } } @@ -675,7 +743,7 @@ else{ this.addLayer(layer); } - + for (int i=0; i<layerNodes.size(); i++){ getLayers(layerNodes.get(i), layer); } Modified: kml/server/KMLServer.java =================================================================== --- kml/server/KMLServer.java 2011-05-17 01:56:15 UTC (rev 34) +++ kml/server/KMLServer.java 2011-05-24 09:53:28 UTC (rev 35) @@ -43,6 +43,19 @@ kml.append("<description>" + service.getDescription() + "</description>"); kml.append("<open>1</open>"); +/* + <LookAt id="superoverlay"> +<longitude>0.0</longitude> +<latitude>0.0</latitude> +<altitude>0</altitude> +<heading>0</heading> +<tilt>0</tilt> +<range>1.2742E7</range> +<altitudeMode>clampToGround</altitudeMode> +</LookAt> + + */ + kml.append("<Style id=\"checkHideChildrenExample\">"); kml.append("<ListStyle>"); kml.append("<listItemType>checkHideChildren</listItemType>"); @@ -72,6 +85,18 @@ kml.append("<GroundOverlay>"); kml.append("<name>" + layer.getName() + "</name>"); + + kml.append("<Region>"); + kml.append("<LatLonAltBox>"); + kml.append("<north>" + bbox[3] + "</north>"); + kml.append("<south>" + bbox[1] + "</south>"); + kml.append("<east>" + bbox[2] + "</east>"); + kml.append("<west>" + bbox[0] + "</west>"); + kml.append("<minAltitude>0</minAltitude>"); + kml.append("<maxAltitude>0</maxAltitude>"); + kml.append("</LatLonAltBox>"); + kml.append("</Region>"); + kml.append("</GroundOverlay>"); kml.append("</Folder>"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-05-17 01:56:22
|
Revision: 34 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=34&view=rev Author: pborissow Date: 2011-05-17 01:56:15 +0000 (Tue, 17 May 2011) Log Message: ----------- Fixed null pointer exceptions Modified Paths: -------------- core/cache/_Tile.java core/image/TileSplitter.java Modified: core/cache/_Tile.java =================================================================== --- core/cache/_Tile.java 2011-05-16 15:05:54 UTC (rev 33) +++ core/cache/_Tile.java 2011-05-17 01:56:15 UTC (rev 34) @@ -99,6 +99,7 @@ */ public boolean equals(Object other){ //In python, this is called __eq__ + if (other==null) return false; if (other instanceof _Tile){ _Tile tile = (_Tile) other; if ( tile.coord.equals(this.coord) && tile.source.equals(this.source)){ Modified: core/image/TileSplitter.java =================================================================== --- core/image/TileSplitter.java 2011-05-16 15:05:54 UTC (rev 33) +++ core/image/TileSplitter.java 2011-05-17 01:56:15 UTC (rev 34) @@ -54,17 +54,19 @@ //System.out.println("get_tile: " + minx + "," + miny + " " + tile_size[0] + "," + tile_size[1]); //this.meta_img.saveAs("/temp/meta_img_" + new java.util.Date().getTime() + ".png"); - javaxt.io.Image meta_img = new javaxt.io.Image(this.meta_img.getBufferedImage()); + try{ + javaxt.io.Image meta_img = new javaxt.io.Image(this.meta_img.getBufferedImage()); meta_img.crop(minx, miny, tile_size[0], tile_size[1]); + return meta_img; } catch(Exception e){ - e.printStackTrace(); - meta_img = null; //new javaxt.io.Image(tile_size[0], tile_size[1]); + //e.printStackTrace(); + return null; //new javaxt.io.Image(tile_size[0], tile_size[1]); } - return meta_img; + //crop = this.meta_img.crop((minx, miny, maxx, maxy)) //return ImageSource(crop, this.format); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-05-16 15:06:00
|
Revision: 33 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=33&view=rev Author: pborissow Date: 2011-05-16 15:05:54 +0000 (Mon, 16 May 2011) Log Message: ----------- Minor refactoring in the ServiceResponse getTile() method. Modified Paths: -------------- core/ServiceResponse.java kml/server/KMLServer.java Modified: core/ServiceResponse.java =================================================================== --- core/ServiceResponse.java 2011-05-16 14:25:43 UTC (rev 32) +++ core/ServiceResponse.java 2011-05-16 15:05:54 UTC (rev 33) @@ -312,42 +312,49 @@ //Set local variables String url = this.url.toString(); -//System.out.println(url); + //Check whether this request is in the http cache mapproxy.tms.TileRequest req = new mapproxy.tms.TileRequest(url); key = req.id(); if (!getBytes) return; - //Set format and + //Set format and content type String format = req.format; contentType = "image/"+format; + //Update content type for jpeg if (format.equalsIgnoreCase("jpg")) contentType = "image/jpeg"; - //Find requested layer in the mapproxy service definition Layer layer = service.getLayer(req.layer); FileCache fileCache = (FileCache) layer.getParam("cache"); + //Get tile grid + TileGrid grid = (TileGrid) layer.getParam("grid"); + if (grid==null) grid = new TileGrid(4326, new int[]{256,256}); + + + //Update tile coordinate + req.tile = new mapproxy.tms.TileServiceGrid(grid).internal_tile_coord(req.tile, true); + + + //Get Image if (fileCache==null){ - TileGrid grid = new TileGrid(4326, new int[]{256,256}); //<--Maybe there's a way to encode these parameters in the URL? Need to check the TMS spec... - double[] bbox = grid.tile_bbox(req.tile[0], req.tile[1], req.tile[2]+1); //<--Note the the z value is incremented by 1 + double[] bbox = grid.tile_bbox(req.tile[0], req.tile[1], req.tile[2]); rsp = layer.getImage(grid.tile_size[0], grid.tile_size[1], format, bbox, grid.srs.toString()).getByteArray(format); } else{ - //Instantiate the TMS cache - TileGrid grid = (TileGrid) layer.getParam("grid"); + //Instantiate the TMS cache mapproxy.tms.cache.TMSTileSource tms = new mapproxy.tms.cache.TMSTileSource(grid, url); CacheManager cacheManager = new CacheManager(fileCache, tms); Cache cache = new Cache(cacheManager, grid, true); - req.tile = new mapproxy.tms.TileServiceGrid(grid).internal_tile_coord(req.tile, true); + - try{ //Find the requested tile in the cache. Note that this will throw an error if the tile doesn't exist Modified: kml/server/KMLServer.java =================================================================== --- kml/server/KMLServer.java 2011-05-16 14:25:43 UTC (rev 32) +++ kml/server/KMLServer.java 2011-05-16 15:05:54 UTC (rev 33) @@ -94,7 +94,7 @@ /** Returns a KML Superoverlay */ public String getKML(javaxt.utils.URL url){ - System.out.println(url); + //System.out.println(url); TileRequest request = new TileRequest(url.getPath()); Layer layer = service.getLayer(request.layer); @@ -103,6 +103,8 @@ tile_coord[2] = tile_coord[2]+1; //<-- Note the the z value is incremented by 1 //The z value for the tile_coord and the subtile coord is then updated in the kml + //Maybe we should do this instead: + //request.tile = new mapproxy.tms.TileServiceGrid(grid).internal_tile_coord(request.tile, true); TileGrid grid = (TileGrid) layer.getParam("grid"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-05-16 14:25:52
|
Revision: 32 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=32&view=rev Author: pborissow Date: 2011-05-16 14:25:43 +0000 (Mon, 16 May 2011) Log Message: ----------- Fixed bug in the ServiceResponse getTile() method for non-cached tile sources Modified Paths: -------------- core/ServiceResponse.java kml/server/KMLServer.java tms/TileServer.java Modified: core/ServiceResponse.java =================================================================== --- core/ServiceResponse.java 2011-05-16 11:59:14 UTC (rev 31) +++ core/ServiceResponse.java 2011-05-16 14:25:43 UTC (rev 32) @@ -312,7 +312,7 @@ //Set local variables String url = this.url.toString(); - +//System.out.println(url); //Check whether this request is in the http cache mapproxy.tms.TileRequest req = new mapproxy.tms.TileRequest(url); key = req.id(); @@ -335,9 +335,8 @@ if (fileCache==null){ TileGrid grid = new TileGrid(4326, new int[]{256,256}); //<--Maybe there's a way to encode these parameters in the URL? Need to check the TMS spec... - double[] bbox = grid.tile_bbox(req.tile[0], req.tile[1], req.tile[2]); + double[] bbox = grid.tile_bbox(req.tile[0], req.tile[1], req.tile[2]+1); //<--Note the the z value is incremented by 1 rsp = layer.getImage(grid.tile_size[0], grid.tile_size[1], format, bbox, grid.srs.toString()).getByteArray(format); - //rsp = getImage(layer, grid.tile_size[0], grid.tile_size[1], format, bbox, grid.srs.toString()).getByteArray(format); } else{ @@ -367,7 +366,6 @@ //Create image and update cache double[] bbox = grid.tile_bbox(req.tile[0], req.tile[1], req.tile[2]); rsp = layer.getImage(grid.tile_size[0], grid.tile_size[1], fileCache.file_ext, bbox, grid.srs.toString()).getByteArray(format); - //rsp = getImage(layer, grid.tile_size[0], grid.tile_size[1], fileCache.file_ext, bbox, grid.srs.toString()).getByteArray(format); } } Modified: kml/server/KMLServer.java =================================================================== --- kml/server/KMLServer.java 2011-05-16 11:59:14 UTC (rev 31) +++ kml/server/KMLServer.java 2011-05-16 14:25:43 UTC (rev 32) @@ -101,8 +101,8 @@ int[] tile_coord = request.tile; - tile_coord[2] = tile_coord[2]+1; //<-- This wasn't in the original mapproxy code. - //Note that this tile_coord and the subtile coord is later updated in the kml + tile_coord[2] = tile_coord[2]+1; //<-- Note the the z value is incremented by 1 + //The z value for the tile_coord and the subtile coord is then updated in the kml TileGrid grid = (TileGrid) layer.getParam("grid"); Modified: tms/TileServer.java =================================================================== --- tms/TileServer.java 2011-05-16 11:59:14 UTC (rev 31) +++ tms/TileServer.java 2011-05-16 14:25:43 UTC (rev 32) @@ -80,6 +80,8 @@ TileGrid grid = (TileGrid) layer.getParam("grid"); if (grid!=null){ grid = new TileGrid(4326, new double[]{-180,-90,180,90}, new int[]{256,256}, null, true, 21); + //SRS srs = new SRS(layer.getSRS()[0]); + //grid = new TileGrid(srs.get_epsg_num(srs), layer.getBBox().toArray(), new int[]{256,256}, null, srs.isGeographic(), 21); } int[] tileSize = grid.tile_size; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-05-16 11:59:20
|
Revision: 31 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=31&view=rev Author: pborissow Date: 2011-05-16 11:59:14 +0000 (Mon, 16 May 2011) Log Message: ----------- - Fixed bug in Layer when format was jpg - Added TileServer class - Updated Capabilities and ServiceResponse classes to use the new TileServer class Modified Paths: -------------- core/Capabilities.java core/Layer.java core/ServiceResponse.java kml/server/KMLServer.java Added Paths: ----------- tms/TileServer.java Modified: core/Capabilities.java =================================================================== --- core/Capabilities.java 2011-05-15 16:25:34 UTC (rev 30) +++ core/Capabilities.java 2011-05-16 11:59:14 UTC (rev 31) @@ -178,26 +178,7 @@ /** Returns an XML document suitable for a TileMapService request. */ private String TMS(){ - - String url = service.getURL(); - - StringBuffer xml = new StringBuffer(); - xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); - xml.append("<TileMapService version=\"1.0.0\">"); - xml.append("<Title>" + service.getTitle() + "</Title>"); - xml.append("<Abstract>" + service.getDescription() + "</Abstract>"); - xml.append("<TileMaps>"); - for (Layer layer : service.getLayers()){ - - xml.append( - "<TileMap title=\"" + layer.getName() + "\" " + - "srs=\"" + layer.getSRS()[0] + "\" " + - "profile=\"global-geodetic\" " + - "href=\"" + url + layer.getName() + "/\"/>"); - } - xml.append("</TileMaps>"); - xml.append("</TileMapService>"); - return xml.toString(); + return new mapproxy.tms.TileServer(service).getCapabilities(); } Modified: core/Layer.java =================================================================== --- core/Layer.java 2011-05-15 16:25:34 UTC (rev 30) +++ core/Layer.java 2011-05-16 11:59:14 UTC (rev 31) @@ -259,6 +259,7 @@ //if (format.equalsIgnoreCase("image/PNG24")) format = "jpeg"; //<-- This is crazy! If I return a 24 bit PNG, ArcMap doesn't display anything. If I return a JPEG, works like a champ if (!format.toLowerCase().startsWith("image/")) format = "image/" + format; + if (format.equalsIgnoreCase("image/jpg")) format = "image/jpeg"; if (format.equalsIgnoreCase("image/PNG24") && fileCache!=null) format = "image/png"; //format = "image/png"; req.params.set("format", format); Modified: core/ServiceResponse.java =================================================================== --- core/ServiceResponse.java 2011-05-15 16:25:34 UTC (rev 30) +++ core/ServiceResponse.java 2011-05-16 11:59:14 UTC (rev 31) @@ -312,7 +312,6 @@ //Set local variables String url = this.url.toString(); -System.out.println(url); //Check whether this request is in the http cache mapproxy.tms.TileRequest req = new mapproxy.tms.TileRequest(url); @@ -324,7 +323,11 @@ String format = req.format; contentType = "image/"+format; + //Update content type for jpeg + if (format.equalsIgnoreCase("jpg")) contentType = "image/jpeg"; + + //Find requested layer in the mapproxy service definition Layer layer = service.getLayer(req.layer); FileCache fileCache = (FileCache) layer.getParam("cache"); @@ -564,8 +567,8 @@ private void getKMLCapabilities(boolean getBytes) { key = "KML Capabilities"; - //contentType = "application/vnd.google-earth.kml+xml"; - contentType = "text/xml"; + contentType = "application/vnd.google-earth.kml+xml"; + //contentType = "text/xml"; if (!getBytes) return; @@ -580,8 +583,8 @@ private void getKML(boolean getBytes) { key = url.getPath(); - //contentType = "application/vnd.google-earth.kml+xml"; - contentType = "text/xml"; + contentType = "application/vnd.google-earth.kml+xml"; + //contentType = "text/xml"; if (!getBytes) return; @@ -629,69 +632,32 @@ if (!getBytes) return; + //Update Service URL String url = this.url.toString(); if (url.contains("?")) url = url.substring(0, url.indexOf("?")); if (!url.endsWith("/")) url += "/"; - - TileGrid grid = (TileGrid) layer.getParam("grid"); - if (grid!=null){ - grid = new TileGrid(4326, new int[]{256,256}); + String lyr = url.substring(url.substring(0, url.length()-1).lastIndexOf("/")+1); + if (lyr.endsWith("/")) lyr = lyr.substring(0, lyr.length()-1); + if (java.net.URLDecoder.decode(lyr).equalsIgnoreCase(layerName)){ + url = url.substring(0, url.lastIndexOf(lyr)); } - int[] tileSize = grid.tile_size; - int tileWidth = tileSize[0]; - int tileHeight = tileSize[1]; - String tileFormat = "png"; - FileCache fileCache = (FileCache) layer.getParam("cache"); - if (fileCache!=null){ - tileFormat = fileCache.file_ext; - } - - String mimeType = "image/"+tileFormat.toLowerCase(); - if (tileFormat.equalsIgnoreCase("jpg")) mimeType = "image/jpeg"; - - //Get Capabilities - StringBuffer xml = new StringBuffer(); - xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); - xml.append("<TileMap version=\"1.0.0\" tilemapservice=\"" + url + "1.0.0/\">"); - xml.append("<Title>" + layerName + "</Title>"); - xml.append("<Abstract>" + layer.getDescription() + "</Abstract>"); - xml.append("<SRS>EPSG:4326</SRS>"); - xml.append("<BoundingBox minx=\"-180.000000\" miny=\"-90.000000\" maxx=\"180.000000\" maxy=\"90.000000\" />"); - xml.append("<Origin x=\"-180.000000\" y=\"-90.000000\" />"); - xml.append("<TileFormat width=\"" + tileWidth + "\" height=\"" + tileHeight + "\" mime-type=\"" + mimeType + "\" extension=\"" + tileFormat + "\" />"); - xml.append("<TileSets>"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/0\" units-per-pixel=\"0.70312500000000000000\" order=\"0\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/1\" units-per-pixel=\"0.35156250000000000000\" order=\"1\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/2\" units-per-pixel=\"0.17578125000000000000\" order=\"2\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/3\" units-per-pixel=\"0.08789062500000000000\" order=\"3\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/4\" units-per-pixel=\"0.04394531250000000000\" order=\"4\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/5\" units-per-pixel=\"0.02197265625000000000\" order=\"5\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/6\" units-per-pixel=\"0.01098632812500000000\" order=\"6\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/7\" units-per-pixel=\"0.00549316406250000000\" order=\"7\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/8\" units-per-pixel=\"0.00274658203125000000\" order=\"8\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/9\" units-per-pixel=\"0.00137329101562500000\" order=\"9\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/10\" units-per-pixel=\"0.00068664550781250000\" order=\"10\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/11\" units-per-pixel=\"0.00034332275390625000\" order=\"11\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/12\" units-per-pixel=\"0.00017166137695312500\" order=\"12\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/13\" units-per-pixel=\"0.00008583068847656250\" order=\"13\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/14\" units-per-pixel=\"0.00004291534423828125\" order=\"14\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/15\" units-per-pixel=\"0.00002145767211914062\" order=\"15\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/16\" units-per-pixel=\"0.00001072883605957031\" order=\"16\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/17\" units-per-pixel=\"0.00000536441802978516\" order=\"17\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/18\" units-per-pixel=\"0.00000268220901489258\" order=\"18\" />"); - xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/19\" units-per-pixel=\"0.00000134110450744629\" order=\"19\" />"); - xml.append("</TileSets>"); - xml.append("</TileMap>"); + String orgURL = service.getURL(); + service.setURL(url); + rsp = getBytes(new mapproxy.tms.TileServer(service).getLayerInfo(layer)); + service.setURL(orgURL); + } + + private byte[] getBytes(String str){ try{ - rsp = xml.toString().getBytes("UTF-8"); + return str.getBytes("UTF-8"); } catch(Exception e){ - rsp = xml.toString().getBytes(); + return str.getBytes(); } } Modified: kml/server/KMLServer.java =================================================================== --- kml/server/KMLServer.java 2011-05-15 16:25:34 UTC (rev 30) +++ kml/server/KMLServer.java 2011-05-16 11:59:14 UTC (rev 31) @@ -104,15 +104,18 @@ tile_coord[2] = tile_coord[2]+1; //<-- This wasn't in the original mapproxy code. //Note that this tile_coord and the subtile coord is later updated in the kml + + TileGrid grid = (TileGrid) layer.getParam("grid"); + if (grid==null) grid = new TileGrid(4326, new int[]{256,256}); boolean initial_level = false; if (tile_coord[2] == 0) initial_level = true; - double[] bbox = _tile_bbox(tile_coord, (TileGrid) layer.getParam("grid")); + double[] bbox = _tile_bbox(tile_coord, grid); SubTile tile = new SubTile(tile_coord, bbox); - SubTile[] subtiles = _get_subtiles(tile_coord, layer); + SubTile[] subtiles = _get_subtiles(tile_coord, grid); String format = "jpg"; @@ -210,7 +213,7 @@ //************************************************************************** /* Create four `SubTile` for the next level of `tile`. */ - private SubTile[] _get_subtiles(int[] tile, Layer layer){ + private SubTile[] _get_subtiles(int[] tile, TileGrid grid){ //Layer layer //x, y, z = tile int x = tile[0]; @@ -220,7 +223,7 @@ java.util.ArrayList<SubTile> subtiles = new java.util.ArrayList<SubTile>(); for (int[] coord : new int[][]{new int[]{x*2, y*2, z+1}, new int[]{x*2+1, y*2, z+1}, new int[]{x*2+1, y*2+1, z+1}, new int[]{x*2, y*2+1, z+1}}){ - double[] bbox = _tile_bbox(coord, (TileGrid) layer.getParam("grid")); + double[] bbox = _tile_bbox(coord, grid); if (bbox != null) subtiles.add(new SubTile(coord, bbox)); } Added: tms/TileServer.java =================================================================== --- tms/TileServer.java (rev 0) +++ tms/TileServer.java 2011-05-16 11:59:14 UTC (rev 31) @@ -0,0 +1,187 @@ +package mapproxy.tms; +import mapproxy.core.*; +import mapproxy.core.cache.FileCache; +import mapproxy.core.grid.TileGrid; + +//****************************************************************************** +//** TileServer Class +//****************************************************************************** +/** + * A Tile Server. Supports strict TMS and non-TMS requests. The difference is + * the support for profiles. The our internal tile cache starts with one tile + * at the first level (like KML, etc.), but the global-geodetic and + * global-mercator start with two and four tiles. The ``tile_request`` should + * set ``use_profiles`` accordingly (eg. False if first level is one tile) + * + ******************************************************************************/ + +public class TileServer { + + private Service service; + + + //************************************************************************** + //** Constructor + //************************************************************************** + /** Creates a new instance of TileServer. */ + + public TileServer(Service service){ + this.service = service; + } + + //************************************************************************** + //** TMS Capabilities + //************************************************************************** + /** Returns an XML document suitable for a TileMapService request. */ + + public String getCapabilities(){ + + String url = service.getURL(); + + StringBuffer xml = new StringBuffer(); + xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); + xml.append("<TileMapService version=\"1.0.0\">"); + xml.append("<Title>" + service.getTitle() + "</Title>"); + xml.append("<Abstract>" + service.getDescription() + "</Abstract>"); + xml.append("<TileMaps>"); + for (Layer layer : service.getLayers()){ + + xml.append( + "<TileMap title=\"" + layer.getName() + "\" " + + "srs=\"" + layer.getSRS()[0] + "\" " + //layer.grid.srs_name + "profile=\"global-geodetic\" " + //layer.grid.profile + "href=\"" + url + layer.getName() + "/\"/>"); + } + xml.append("</TileMaps>"); + xml.append("</TileMapService>"); + return xml.toString(); + } + + + //************************************************************************** + //** getLayerInfo + //************************************************************************** + /** Used to construct a response to a TMS Capabilities request for a given + * layer. + */ + public String getLayerInfo(Layer layer) { + + String layerName = layer.getName(); + + + String url = service.getURL(); + if (url.contains("?")) url = url.substring(0, url.indexOf("?")); + if (!url.endsWith("/")) url += "/"; + + + url += layerName + "/"; + + + TileGrid grid = (TileGrid) layer.getParam("grid"); + if (grid!=null){ + grid = new TileGrid(4326, new double[]{-180,-90,180,90}, new int[]{256,256}, null, true, 21); + } + + int[] tileSize = grid.tile_size; + int tileWidth = tileSize[0]; + int tileHeight = tileSize[1]; + + String tileFormat = "png"; + FileCache fileCache = (FileCache) layer.getParam("cache"); + if (fileCache!=null){ + tileFormat = fileCache.file_ext; + } + + String mimeType = "image/"+tileFormat.toLowerCase(); + if (tileFormat.equalsIgnoreCase("jpg")) mimeType = "image/jpeg"; + + + //Get Capabilities + StringBuffer xml = new StringBuffer(); + xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); + xml.append("<TileMap version=\"1.0.0\" tilemapservice=\"" + url + "1.0.0/\">"); + xml.append("<Title>" + layerName + "</Title>"); + xml.append("<Abstract>" + layer.getDescription() + "</Abstract>"); + xml.append("<SRS>EPSG:4326</SRS>"); + xml.append("<BoundingBox minx=\"-180.000000\" miny=\"-90.000000\" maxx=\"180.000000\" maxy=\"90.000000\" />"); + xml.append("<Origin x=\"-180.000000\" y=\"-90.000000\" />"); + xml.append("<TileFormat width=\"" + tileWidth + "\" height=\"" + tileHeight + "\" mime-type=\"" + mimeType + "\" extension=\"" + tileFormat + "\" />"); + xml.append("<TileSets>"); + + for (int i=0; i<grid.levels; i++){ + if (i>0){ + int level = i-1; + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/" + level + "\" units-per-pixel=\"" + formatNum(grid.resolution(i)) + "\" order=\"" + level + "\" />"); + } + } + + /* + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/0\" units-per-pixel=\"0.70312500000000000000\" order=\"0\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/1\" units-per-pixel=\"0.35156250000000000000\" order=\"1\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/2\" units-per-pixel=\"0.17578125000000000000\" order=\"2\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/3\" units-per-pixel=\"0.08789062500000000000\" order=\"3\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/4\" units-per-pixel=\"0.04394531250000000000\" order=\"4\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/5\" units-per-pixel=\"0.02197265625000000000\" order=\"5\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/6\" units-per-pixel=\"0.01098632812500000000\" order=\"6\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/7\" units-per-pixel=\"0.00549316406250000000\" order=\"7\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/8\" units-per-pixel=\"0.00274658203125000000\" order=\"8\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/9\" units-per-pixel=\"0.00137329101562500000\" order=\"9\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/10\" units-per-pixel=\"0.00068664550781250000\" order=\"10\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/11\" units-per-pixel=\"0.00034332275390625000\" order=\"11\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/12\" units-per-pixel=\"0.00017166137695312500\" order=\"12\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/13\" units-per-pixel=\"0.00008583068847656250\" order=\"13\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/14\" units-per-pixel=\"0.00004291534423828125\" order=\"14\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/15\" units-per-pixel=\"0.00002145767211914062\" order=\"15\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/16\" units-per-pixel=\"0.00001072883605957031\" order=\"16\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/17\" units-per-pixel=\"0.00000536441802978516\" order=\"17\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/18\" units-per-pixel=\"0.00000268220901489258\" order=\"18\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/19\" units-per-pixel=\"0.00000134110450744629\" order=\"19\" />"); + + */ + xml.append("</TileSets>"); + xml.append("</TileMap>"); + + return xml.toString(); + + } + + + private static final int MAX_LENGTH = ("0.70312500000000000000".length()); + + private static String formatNum(double number) { + int digitsAvailable = MAX_LENGTH - 2; + if (Math.abs(number) < Math.pow(10, digitsAvailable) + && Math.abs(number) > Math.pow(10, -digitsAvailable)) { + String format = "0."; + double temp = number; + for (int i = 0; i < digitsAvailable; i++) { + if ((temp /= 10) < 1) { + format += "#"; + } + } + String r = new java.text.DecimalFormat(format).format(number); + while (r.length() < MAX_LENGTH){ + r+= "0"; + } + return r; + } + String format = "0."; + for (int i = 0; i < digitsAvailable; i++) { + format += "#"; + } + String r = new java.text.DecimalFormat(format + "E0").format(number); + int lastLength = r.length() + 1; + while (r.length() > MAX_LENGTH && lastLength > r.length()) { + lastLength = r.length(); + r = r.replaceAll("\\.?[0-9]E", "E"); + } + + while (r.length() < MAX_LENGTH){ + r+= "0"; + } + + return r; + } + + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-05-15 16:25:41
|
Revision: 30 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=30&view=rev Author: pborissow Date: 2011-05-15 16:25:34 +0000 (Sun, 15 May 2011) Log Message: ----------- Initial implementation of a KML Tile Server Modified Paths: -------------- core/ServiceResponse.java Added Paths: ----------- kml/ kml/server/ kml/server/KMLServer.java Modified: core/ServiceResponse.java =================================================================== --- core/ServiceResponse.java 2011-05-10 09:11:31 UTC (rev 29) +++ core/ServiceResponse.java 2011-05-15 16:25:34 UTC (rev 30) @@ -3,6 +3,7 @@ import mapproxy.core.cache.*; import org.w3c.dom.*; import javaxt.xml.DOM; +import mapproxy.kml.server.KMLServer; //****************************************************************************** //** ServiceResponse Class @@ -93,7 +94,10 @@ boolean responseSent = true; String path = url.getPath().toLowerCase(); - if (!path.endsWith("/")) path+="/"; + if (!path.contains(".") && !path.endsWith("/")) path+="/"; + + + //ArcGIS Server Response if (path.contains("/ImageServer/".toLowerCase()) || path.contains("/MapServer/".toLowerCase()) || path.contains("/ArcGIS/".toLowerCase())){ @@ -122,6 +126,8 @@ } } + + //WMS Server Response else if (path.contains("/wms/")){ String action = url.getParameter("request"); if (action.equalsIgnoreCase("GetMap")){ @@ -134,10 +140,10 @@ responseSent = false; } } + + //TMS Server Response else if (path.contains("/tms/")){ - - if (path.endsWith("/tms/")){ getTMSCapabilities(getBytes); } @@ -162,12 +168,37 @@ } } } + + //KML Server Response + else if (path.contains("/kml/")){ + + if (path.endsWith("/kml/")){ + getKMLCapabilities(getBytes); + } + else{ + + if (path.contains(".")){ + String format = path.substring(path.lastIndexOf(".")+1).toLowerCase(); + if (format.equals("jpg") || format.equals("png")){ + getTile(getBytes); + } + else if (format.equals("kml")){ + getKML(getBytes); + } + else{ + responseSent = false; + } + } + else{ + responseSent = false; + } + } + } else{ responseSent = false; } if (!responseSent) getLandingPage(getBytes); - } @@ -253,7 +284,8 @@ StringBuffer services = new StringBuffer(); services.append("<li><a href=\"/WMS/?service=WMS&request=GetCapabilities&version=1.1.1\">WMS</a></li>"); - services.append("<li><a href=\"/TMS/?\">TMS</a></li>"); + services.append("<li><a href=\"/TMS/\">TMS</a></li>"); + services.append("<li><a href=\"/KML/\">KML</a></li>"); services.append("<li><a href=\"/ArcGIS/?wsdl\">ArcGIS MapServer (SOAP)</a></li>"); services.append("<li><a href=\"/ArcGIS/?f=json\">ArcGIS MapServer (REST)</a></li>"); html = html.replace("@SERVICES", services.toString()); @@ -280,8 +312,8 @@ //Set local variables String url = this.url.toString(); +System.out.println(url); - //Check whether this request is in the http cache mapproxy.tms.TileRequest req = new mapproxy.tms.TileRequest(url); key = req.id(); @@ -525,6 +557,39 @@ //************************************************************************** + //** getKMLCapabilities + //************************************************************************** + /** Used to construct a response to a KML Capabilities request + */ + private void getKMLCapabilities(boolean getBytes) { + + key = "KML Capabilities"; + //contentType = "application/vnd.google-earth.kml+xml"; + contentType = "text/xml"; + + if (!getBytes) return; + + rsp = new KMLServer(service).getCapabilities().getBytes(); + } + + //************************************************************************** + //** getKML + //************************************************************************** + /** Used to construct a KML SuperOverlay + */ + private void getKML(boolean getBytes) { + + key = url.getPath(); + //contentType = "application/vnd.google-earth.kml+xml"; + contentType = "text/xml"; + + if (!getBytes) return; + + rsp = new KMLServer(service).getKML(url).getBytes(); + } + + + //************************************************************************** //** getTMSCapabilities //************************************************************************** /** Used to construct a response to a TMS GetCapabilities request Added: kml/server/KMLServer.java =================================================================== --- kml/server/KMLServer.java (rev 0) +++ kml/server/KMLServer.java 2011-05-15 16:25:34 UTC (rev 30) @@ -0,0 +1,273 @@ +package mapproxy.kml.server; +import mapproxy.tms.TileRequest; +import mapproxy.tms.TileServiceGrid; +import mapproxy.core.grid.TileGrid; +import mapproxy.core.cache.FileCache; +import mapproxy.core.*; + +//****************************************************************************** +//** KMLServer Class +//****************************************************************************** +/** + * OGC KML 2.2 Server + * + ******************************************************************************/ + +public class KMLServer { + + private Service service; + + + //************************************************************************** + //** Constructor + //************************************************************************** + /** Creates a new instance of KMLServer. */ + + public KMLServer(Service service){ + this.service = service; + } + + + //************************************************************************** + //** getCapabilities + //************************************************************************** + /** Returns a KML Document with links to individual layers in this service. + * Note that this method was not part of the original mapproxy baseline. + */ + public String getCapabilities(){ + StringBuffer kml = new StringBuffer(); + kml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); + kml.append("<kml xmlns=\"http://earth.google.com/kml/2.0\">"); + kml.append("<Document>"); + kml.append("<name>" + service.getName() + "</name>"); + kml.append("<description>" + service.getDescription() + "</description>"); + kml.append("<open>1</open>"); + + kml.append("<Style id=\"checkHideChildrenExample\">"); + kml.append("<ListStyle>"); + kml.append("<listItemType>checkHideChildren</listItemType>"); + kml.append("</ListStyle>"); + kml.append("</Style>"); + + for (Layer layer : service.getLayers()){ + kml.append("<Folder>"); + kml.append("<name>" + layer.getName() + "</name>"); + //kml.append("<description>" + layer.getDescription() + "</description>"); + kml.append("<open>0</open>"); + kml.append("<styleUrl>#checkHideChildrenExample</styleUrl>"); + + + double[] bbox = layer.getBBox().toArray(); + TileGrid grid = (TileGrid) layer.getParam("grid"); + if (grid==null) grid = new TileGrid(4326, new int[]{256,256}); + + Object[] affected_tiles = grid.get_affected_tiles(bbox, grid.tile_size, grid.srs, false); + Generator<int[]> tiles = (Generator<int[]>) affected_tiles[2]; + kml.append("<Folder>"); + + for (int[] tile_coord : tiles){ + double[] b = _tile_bbox(tile_coord, grid); + kml.append(this.getNetworkLink(layer, new SubTile(tile_coord, b))); + } + + kml.append("<GroundOverlay>"); + kml.append("<name>" + layer.getName() + "</name>"); + kml.append("</GroundOverlay>"); + + kml.append("</Folder>"); + + kml.append("</Folder>"); + + } + + kml.append("</Document>"); + kml.append("</kml>"); + return kml.toString(); + } + + + + + //************************************************************************** + //** getKML + //************************************************************************** + /** Returns a KML Superoverlay + */ + public String getKML(javaxt.utils.URL url){ + System.out.println(url); + + TileRequest request = new TileRequest(url.getPath()); + Layer layer = service.getLayer(request.layer); + int[] tile_coord = request.tile; + + + tile_coord[2] = tile_coord[2]+1; //<-- This wasn't in the original mapproxy code. + //Note that this tile_coord and the subtile coord is later updated in the kml + + + + boolean initial_level = false; + if (tile_coord[2] == 0) + initial_level = true; + + double[] bbox = _tile_bbox(tile_coord, (TileGrid) layer.getParam("grid")); + SubTile tile = new SubTile(tile_coord, bbox); + SubTile[] subtiles = _get_subtiles(tile_coord, layer); + + + String format = "jpg"; + FileCache cache = (FileCache) layer.getParam("cache"); + if (cache!=null) format = cache.file_ext; + + + + StringBuffer kml = new StringBuffer(); + kml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); + kml.append("<kml xmlns=\"http://www.opengis.net/kml/2.2\">"); + kml.append("<Document>"); + if (initial_level){ + kml.append("<name>" + layer.getName() + "</name>"); + } + else{ + kml.append("<name>" + layer.getName() + "-" + tile.coord + "</name>"); + } + kml.append("<Region>"); + kml.append("<LatLonAltBox>"); + kml.append("<north>" + tile.bbox[3] + "</north><south>" + tile.bbox[1] + "</south>"); + kml.append("<east>" + tile.bbox[2] + "</east><west>" + tile.bbox[0] + "</west>"); + kml.append("</LatLonAltBox>"); + kml.append("<Lod>"); + kml.append("<minLodPixels>100</minLodPixels>"); + if (initial_level){ + kml.append("<maxLodPixels>-1</maxLodPixels>"); + } + else{ + kml.append("<maxLodPixels>256</maxLodPixels>"); + } + + kml.append("<minFadeExtent>20</minFadeExtent>"); + kml.append("<maxFadeExtent>10</maxFadeExtent>"); + kml.append("</Lod>"); + kml.append("</Region>"); + + + for (SubTile subtile : subtiles){ + kml.append(this.getNetworkLink(layer, subtile)); + } + + kml.append("<GroundOverlay>"); + kml.append("<name>" + tile.coord + "</name>"); + kml.append("<drawOrder>" + tile.coord[2] + "</drawOrder>"); + kml.append("<Icon>"); + kml.append("<href>" + service.getURL() + "/kml/" + layer.getName() + "/" + (tile.coord[2]-1) + "/" + tile.coord[0] + "/" + tile.coord[1] + "." + format + "</href>"); + kml.append("</Icon>"); + kml.append("<LatLonBox>"); + kml.append("<north>" + tile.bbox[3] + "</north><south>" + tile.bbox[1] + "</south>"); + kml.append("<east>" + tile.bbox[2] + "</east><west>" + tile.bbox[0] + "</west>"); + kml.append("</LatLonBox>"); + kml.append("</GroundOverlay>"); + + + kml.append("</Document>"); + kml.append("</kml>"); + return kml.toString(); + } + + + private String getNetworkLink(Layer layer, SubTile subtile){ + + StringBuffer kml = new StringBuffer(); + + kml.append("<NetworkLink>"); + kml.append("<name>" + layer.getName() + "-" + subtile.coord + "</name>"); + kml.append("<Region>"); + kml.append("<LatLonAltBox>"); + kml.append("<north>" + subtile.bbox[3] + "</north><south>" + subtile.bbox[1] + "</south>"); + kml.append("<east>" + subtile.bbox[2] + "</east><west>" + subtile.bbox[0] + "</west>"); + kml.append("</LatLonAltBox>"); + kml.append("<Lod>"); + kml.append("<minLodPixels>128</minLodPixels>"); + kml.append("<maxLodPixels>-1</maxLodPixels>"); + kml.append("</Lod>"); + kml.append("</Region>"); + kml.append("<Link>"); + kml.append("<href>" + service.getURL() + "/kml/" + layer.getName() + "/" + (subtile.coord[2]-1) + "/" + subtile.coord[0] + "/" + subtile.coord[1] + ".kml</href>"); + kml.append("<viewRefreshMode>onRegion</viewRefreshMode>"); + kml.append("<viewFormat/>"); + kml.append("</Link>"); + kml.append("</NetworkLink>"); + + return kml.toString(); + + } + + + + + + //************************************************************************** + //** _get_subtiles + //************************************************************************** + /* Create four `SubTile` for the next level of `tile`. + */ + private SubTile[] _get_subtiles(int[] tile, Layer layer){ + + //x, y, z = tile + int x = tile[0]; + int y = tile[1]; + int z = tile[2]; + + java.util.ArrayList<SubTile> subtiles = new java.util.ArrayList<SubTile>(); + for (int[] coord : new int[][]{new int[]{x*2, y*2, z+1}, new int[]{x*2+1, y*2, z+1}, + new int[]{x*2+1, y*2+1, z+1}, new int[]{x*2, y*2+1, z+1}}){ + double[] bbox = _tile_bbox(coord, (TileGrid) layer.getParam("grid")); + if (bbox != null) + subtiles.add(new SubTile(coord, bbox)); + } + return subtiles.toArray(new SubTile[subtiles.size()]); + } + + + //************************************************************************** + //** _tile_bbox + //************************************************************************** + + private double[] _tile_bbox(int[] tile_coord, TileGrid grid){ + + //tile_coord = grid.internal_tile_coord(tile_coord, false); + tile_coord = new TileServiceGrid(grid).internal_tile_coord(tile_coord, false); + + + if (tile_coord == null) + return null; + + double[] src_bbox = grid.tile_bbox(tile_coord[0], tile_coord[1], tile_coord[2]); + double[] bbox = grid.srs.transform_bbox_to(new SRS(4326), src_bbox, 4); + if (grid.srs.equals(new SRS(900913))){ + //bbox = list(bbox) + if (Math.abs(src_bbox[1] - -20037508.342789244) < 0.1) + bbox[1] = -90.0; + if (Math.abs(src_bbox[3] - 20037508.342789244) < 0.1) + bbox[3] = 90.0; + } + + mapproxy.core.Python.cstr(src_bbox); + mapproxy.core.Python.cstr(bbox); + return bbox; + } + + + //************************************************************************** + //** SubTile Class + //************************************************************************** + /* Contains the "bbox" and "coord" of a sub tile. + */ + private class SubTile{ + public int[] coord; + public double[] bbox; + public SubTile(int[] coord, double[] bbox){ + this.coord = coord; + this.bbox = bbox; + } + } +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-05-10 09:11:38
|
Revision: 29 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=29&view=rev Author: pborissow Date: 2011-05-10 09:11:31 +0000 (Tue, 10 May 2011) Log Message: ----------- Added updated capabilities responses. Modified Paths: -------------- Main.java OpenLayers.htm core/Capabilities.java core/Service.java core/ServiceResponse.java Modified: Main.java =================================================================== --- Main.java 2011-05-09 20:32:24 UTC (rev 28) +++ Main.java 2011-05-10 09:11:31 UTC (rev 29) @@ -29,21 +29,12 @@ * @param args the command line arguments */ public static void main(String[] args) throws Exception { - //new Main(args); + new Main(args); + } - String url = "http://tilecache.osgeo.org/wms-c/Basic.py/1.0.0/"; - //url = "http://geoposer.com:443/server/services/osm.xml"; - Service service = new Service(url); - System.out.println("Name: " + service.getName() ); - System.out.println("Title: " + service.getTitle() ); - for (mapproxy.core.Layer layer : service.getLayers()){ - System.out.println(" - " + layer.getName()); - } - } - //************************************************************************** //** Constructor //************************************************************************** @@ -71,19 +62,32 @@ //testSRS(); args = new String[]{"C:\\Documents and Settings\\peter.borissow\\My Documents\\Java\\Libraries\\mapproxy\\src\\mapproxy\\config.xml"}; - //startServer(args); + startServer(args); //seedTest(args); //testWebServices(); //testArcWebServices(); //testTMS(); - testWebServices(); + //testWebServices(); } + private void testCapabilitiesParser(){ + String url = "http://tilecache.osgeo.org/wms-c/Basic.py/1.0.0/"; + url = "http://geoposer.com:443/server/services/osm.xml"; + url = "http://ewdev.spadac.com/earthwhere-api/cgi-bin/mapserv.exe?map=E:/EarthWhere/Data/BaseMap/world.map&service=WMS&request=getcapabilities"; + Service service = new Service(url); + System.out.println("Name: " + service.getName() ); + System.out.println("Title: " + service.getTitle() ); + System.out.println("URL: " + service.getURL() ); + for (mapproxy.core.Layer layer : service.getLayers()){ + System.out.println(" - " + layer.getName()); + } + } + private void testTMS(){ Modified: OpenLayers.htm =================================================================== --- OpenLayers.htm 2011-05-09 20:32:24 UTC (rev 28) +++ OpenLayers.htm 2011-05-10 09:11:31 UTC (rev 29) @@ -13,8 +13,8 @@ </style> <script src="http://www.openlayers.org/api/OpenLayers.js"></script> <script type="text/javascript"> - var lon = 5; - var lat = 40; + var lon = 0; + var lat = 0; var zoom = 2; var map, layer, tags; Modified: core/Capabilities.java =================================================================== --- core/Capabilities.java 2011-05-09 20:32:24 UTC (rev 28) +++ core/Capabilities.java 2011-05-10 09:11:31 UTC (rev 29) @@ -192,8 +192,8 @@ xml.append( "<TileMap title=\"" + layer.getName() + "\" " + "srs=\"" + layer.getSRS()[0] + "\" " + - "profile=\"{{layer.grid.profile}}\" " + - "href=\"" + url + layer.getName() + "\"/>"); + "profile=\"global-geodetic\" " + + "href=\"" + url + layer.getName() + "/\"/>"); } xml.append("</TileMaps>"); xml.append("</TileMapService>"); @@ -224,7 +224,7 @@ if (callback!=null) json.append(callback+"("); json.append("{\r\n"); - json.append(" \"serviceDescription\" : \"No Description.\", \r\n"); + json.append(" \"serviceDescription\" : \"" + service.getDescription() + "\", \r\n"); json.append(" \"mapName\" : \"Layers\", \r\n"); if (service.getDescription()!=null){ json.append(" \"description\" : \"" + service.getDescription() + "\", \r\n"); @@ -250,19 +250,19 @@ json.append(" }, \r\n"); json.append(" \"singleFusedMapCache\" : false, \r\n"); json.append(" \"initialExtent\" : {\r\n"); - json.append(" \"xmin\" : -127.997731612104, \r\n"); - json.append(" \"ymin\" : 5.39213971511016, \r\n"); - json.append(" \"xmax\" : -63.6599405477216, \r\n"); - json.append(" \"ymax\" : 70.5993603884707, \r\n"); + json.append(" \"xmin\" : -180.0, \r\n"); + json.append(" \"ymin\" : -90.0, \r\n"); + json.append(" \"xmax\" : 180.0, \r\n"); + json.append(" \"ymax\" : 90.0, \r\n"); json.append(" \"spatialReference\" : {\r\n"); json.append(" \"wkid\" : 4326\r\n"); json.append(" }\r\n"); json.append(" }, \r\n"); json.append(" \"fullExtent\" : {\r\n"); - json.append(" \"xmin\" : -183.780014728684, \r\n"); - json.append(" \"ymin\" : 16.3007091216188, \r\n"); - json.append(" \"xmax\" : -61.4068546696842, \r\n"); - json.append(" \"ymax\" : 74.0303080309689, \r\n"); + json.append(" \"xmin\" : -180.0, \r\n"); + json.append(" \"ymin\" : -90.0, \r\n"); + json.append(" \"xmax\" : 180.0, \r\n"); + json.append(" \"ymax\" : 90.0, \r\n"); json.append(" \"spatialReference\" : {\r\n"); json.append(" \"wkid\" : 4326\r\n"); json.append(" }\r\n"); @@ -280,8 +280,8 @@ json.append(" \"documentInfo\" : {\r\n"); - json.append(" \"Title\" : \"USA_Data\", \r\n"); - json.append(" \"Author\" : \"andy\", \r\n"); + json.append(" \"Title\" : \"" + service.getName() + "\", \r\n"); + json.append(" \"Author\" : \"\", \r\n"); json.append(" \"Comments\" : \"\", \r\n"); json.append(" \"Subject\" : \"\", \r\n"); json.append(" \"Category\" : \"\", \r\n"); Modified: core/Service.java =================================================================== --- core/Service.java 2011-05-09 20:32:24 UTC (rev 28) +++ core/Service.java 2011-05-10 09:11:31 UTC (rev 29) @@ -80,6 +80,8 @@ else if (media.equals("text/plain")){ String text = response.getText().trim(); if (text.startsWith("{") && text.endsWith("}")){ + this.url = url.toString(); + if (this.url.contains("?")) this.url = this.url.substring(0, this.url.indexOf("?")); parseArcGISCapabilities(text); } } @@ -507,6 +509,13 @@ } + + //************************************************************************** + //** getWMSFormats + //************************************************************************** + /** Used to extract a list of supported formats from a WMS Capabilities + * document. + */ private String[] getWMSFormats(NodeList GetMap){ java.util.ArrayList<String> formats = new java.util.ArrayList<String>(); for (int i=0; i<GetMap.getLength(); i++){ @@ -519,6 +528,12 @@ return formats.toArray(new String[formats.size()]); } + + //************************************************************************** + //** getMapURL + //************************************************************************** + /** Used to extract the url associated with a GetMap request. + */ private String getMapURL(NodeList GetMap){ for (int i=0; i<GetMap.getLength(); i++){ Modified: core/ServiceResponse.java =================================================================== --- core/ServiceResponse.java 2011-05-09 20:32:24 UTC (rev 28) +++ core/ServiceResponse.java 2011-05-10 09:11:31 UTC (rev 29) @@ -135,10 +135,32 @@ } } else if (path.contains("/tms/")){ - if (path.equals("/tms/")){ + + + + if (path.endsWith("/tms/")){ getTMSCapabilities(getBytes); } - else getTile(getBytes); + else{ + path = java.net.URLDecoder.decode(path); + boolean getLayerInfo = false; + Layer requestedLayer = null; + for (Layer layer : service.getLayers()){ + String layerName = layer.getName(); + if (path.toLowerCase().endsWith("/tms/" + layerName.toLowerCase() + "/")){ + requestedLayer = layer; + getLayerInfo = true; + break; + } + } + + if (getLayerInfo){ + getTMSLayerInfo(requestedLayer, getBytes); + } + else{ + getTile(getBytes); + } + } } else{ responseSent = false; @@ -528,6 +550,88 @@ //************************************************************************** + //** getTMSLayerInfo + //************************************************************************** + /** Used to construct a response to a TMS Capabilities request for a given + * layer. + */ + private void getTMSLayerInfo(Layer layer, boolean getBytes) { + + String layerName = layer.getName(); + + key = "TMS Capabilities - " + layerName; + contentType = "text/xml"; + + if (!getBytes) return; + + String url = this.url.toString(); + if (url.contains("?")) url = url.substring(0, url.indexOf("?")); + if (!url.endsWith("/")) url += "/"; + + + TileGrid grid = (TileGrid) layer.getParam("grid"); + if (grid!=null){ + grid = new TileGrid(4326, new int[]{256,256}); + } + + int[] tileSize = grid.tile_size; + int tileWidth = tileSize[0]; + int tileHeight = tileSize[1]; + + String tileFormat = "png"; + FileCache fileCache = (FileCache) layer.getParam("cache"); + if (fileCache!=null){ + tileFormat = fileCache.file_ext; + } + + String mimeType = "image/"+tileFormat.toLowerCase(); + if (tileFormat.equalsIgnoreCase("jpg")) mimeType = "image/jpeg"; + + + //Get Capabilities + StringBuffer xml = new StringBuffer(); + xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); + xml.append("<TileMap version=\"1.0.0\" tilemapservice=\"" + url + "1.0.0/\">"); + xml.append("<Title>" + layerName + "</Title>"); + xml.append("<Abstract>" + layer.getDescription() + "</Abstract>"); + xml.append("<SRS>EPSG:4326</SRS>"); + xml.append("<BoundingBox minx=\"-180.000000\" miny=\"-90.000000\" maxx=\"180.000000\" maxy=\"90.000000\" />"); + xml.append("<Origin x=\"-180.000000\" y=\"-90.000000\" />"); + xml.append("<TileFormat width=\"" + tileWidth + "\" height=\"" + tileHeight + "\" mime-type=\"" + mimeType + "\" extension=\"" + tileFormat + "\" />"); + xml.append("<TileSets>"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/0\" units-per-pixel=\"0.70312500000000000000\" order=\"0\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/1\" units-per-pixel=\"0.35156250000000000000\" order=\"1\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/2\" units-per-pixel=\"0.17578125000000000000\" order=\"2\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/3\" units-per-pixel=\"0.08789062500000000000\" order=\"3\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/4\" units-per-pixel=\"0.04394531250000000000\" order=\"4\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/5\" units-per-pixel=\"0.02197265625000000000\" order=\"5\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/6\" units-per-pixel=\"0.01098632812500000000\" order=\"6\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/7\" units-per-pixel=\"0.00549316406250000000\" order=\"7\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/8\" units-per-pixel=\"0.00274658203125000000\" order=\"8\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/9\" units-per-pixel=\"0.00137329101562500000\" order=\"9\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/10\" units-per-pixel=\"0.00068664550781250000\" order=\"10\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/11\" units-per-pixel=\"0.00034332275390625000\" order=\"11\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/12\" units-per-pixel=\"0.00017166137695312500\" order=\"12\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/13\" units-per-pixel=\"0.00008583068847656250\" order=\"13\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/14\" units-per-pixel=\"0.00004291534423828125\" order=\"14\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/15\" units-per-pixel=\"0.00002145767211914062\" order=\"15\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/16\" units-per-pixel=\"0.00001072883605957031\" order=\"16\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/17\" units-per-pixel=\"0.00000536441802978516\" order=\"17\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/18\" units-per-pixel=\"0.00000268220901489258\" order=\"18\" />"); + xml.append("<TileSet href=\"" + url + "1.0.0/" + layerName + "/19\" units-per-pixel=\"0.00000134110450744629\" order=\"19\" />"); + xml.append("</TileSets>"); + xml.append("</TileMap>"); + + try{ + rsp = xml.toString().getBytes("UTF-8"); + } + catch(Exception e){ + rsp = xml.toString().getBytes(); + } + } + + + //************************************************************************** //** getArcMapCapabilities //************************************************************************** /** Used to construct a response to an ArcMap REST Capabilities request @@ -646,7 +750,7 @@ } else if (msg.contains("ExportMapImage")){ System.out.println("ExportMapImage"); -new javaxt.io.File("/temp/ExportImage.xml").write(body, "UTF-8"); +//new javaxt.io.File("/temp/ExportImage.xml").write(body, "UTF-8"); String returnType = getNodeValue("ImageReturnType", xml); String width = getNodeValue("ImageWidth", xml); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-05-09 20:32:30
|
Revision: 28 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=28&view=rev Author: pborissow Date: 2011-05-09 20:32:24 +0000 (Mon, 09 May 2011) Log Message: ----------- Fixed bug extracting base url from WMS capabilities document. Modified Paths: -------------- core/Service.java Modified: core/Service.java =================================================================== --- core/Service.java 2011-05-09 08:13:52 UTC (rev 27) +++ core/Service.java 2011-05-09 20:32:24 UTC (rev 28) @@ -472,29 +472,34 @@ if (nodeName.equalsIgnoreCase("Abstract")){ description = getNodeValue(node); } - if (nodeName.equalsIgnoreCase("OnlineResource")){ - NamedNodeMap map = node.getAttributes(); - for (int j=0; j<map.getLength(); j++){ - Node attr = map.item(j); - String attrName = attr.getNodeName(); - if (attrName.contains(":")) attrName = attrName.substring(attrName.indexOf(":")+1); - if (attrName.equalsIgnoreCase("href")){ - this.url = attr.getNodeValue(); - break; - } - } - } - } } + + //Parse capabilities if (capabilities!=null){ for (int i=0; i<capabilities.getLength(); i++){ Node node = capabilities.item(i); String nodeName = getNodeName(node); - if (nodeName.equalsIgnoreCase("Layer")){ + + //Get Methods + if (nodeName.equalsIgnoreCase("Request")){ + NodeList methods = node.getChildNodes(); + for (int j=0; j<methods.getLength(); j++){ + Node method = methods.item(j); + String methodName = getNodeName(method); + if (methodName.equalsIgnoreCase("GetMap")){ + this.url = getMapURL(method.getChildNodes()); + this.formats = this.getWMSFormats(method.getChildNodes()); + break; + } + } + } + + //Get Layers + else if (nodeName.equalsIgnoreCase("Layer")){ getLayers(node, null); } } @@ -502,7 +507,56 @@ } + private String[] getWMSFormats(NodeList GetMap){ + java.util.ArrayList<String> formats = new java.util.ArrayList<String>(); + for (int i=0; i<GetMap.getLength(); i++){ + Node node = GetMap.item(i); + String nodeName = getNodeName(node); + if (nodeName.equalsIgnoreCase("Format")){ + formats.add(getNodeValue(node)); + } + } + return formats.toArray(new String[formats.size()]); + } + private String getMapURL(NodeList GetMap){ + + for (int i=0; i<GetMap.getLength(); i++){ + Node node = GetMap.item(i); + if (getNodeName(node).equalsIgnoreCase("DCPType")){ + NodeList protocols = node.getChildNodes(); + for (int j=0; j<protocols.getLength(); j++){ + Node protocol = protocols.item(j); + if (getNodeName(protocol).equalsIgnoreCase("HTTP")){ + NodeList methods = protocol.getChildNodes(); + for (int k=0; k<methods.getLength(); k++){ + Node method = methods.item(k); + if (getNodeName(method).equalsIgnoreCase("GET")){ + NodeList resources = method.getChildNodes(); + for (int l=0; l<resources.getLength(); l++){ + Node resource = resources.item(l); + if (getNodeName(resource).equalsIgnoreCase("OnlineResource")){ + NamedNodeMap map = resource.getAttributes(); + for (int m=0; m<map.getLength(); m++){ + Node attr = map.item(m); + String attrName = attr.getNodeName(); + if (attrName.contains(":")) attrName = attrName.substring(attrName.indexOf(":")+1); + if (attrName.equalsIgnoreCase("href")){ + return attr.getNodeValue(); + } + } + } + } + } + } + } + } + } + } + return null; + } + + //************************************************************************** //** getLayers //************************************************************************** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-05-09 08:13:59
|
Revision: 27 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=27&view=rev Author: pborissow Date: 2011-05-09 08:13:52 +0000 (Mon, 09 May 2011) Log Message: ----------- Added parser for TMS Capabilities. Modified Paths: -------------- Main.java core/BBox.java core/Layer.java core/SRS.java core/Service.java core/grid/TileGrid.java core/request/RequestParams.java Modified: Main.java =================================================================== --- Main.java 2011-04-14 00:55:30 UTC (rev 26) +++ Main.java 2011-05-09 08:13:52 UTC (rev 27) @@ -29,7 +29,18 @@ * @param args the command line arguments */ public static void main(String[] args) throws Exception { - new Main(args); + //new Main(args); + + String url = "http://tilecache.osgeo.org/wms-c/Basic.py/1.0.0/"; + //url = "http://geoposer.com:443/server/services/osm.xml"; + + Service service = new Service(url); + System.out.println("Name: " + service.getName() ); + System.out.println("Title: " + service.getTitle() ); + for (mapproxy.core.Layer layer : service.getLayers()){ + System.out.println(" - " + layer.getName()); + } + } @@ -61,12 +72,14 @@ args = new String[]{"C:\\Documents and Settings\\peter.borissow\\My Documents\\Java\\Libraries\\mapproxy\\src\\mapproxy\\config.xml"}; //startServer(args); - seedTest(args); + //seedTest(args); //testWebServices(); //testArcWebServices(); //testTMS(); + testWebServices(); + } @@ -88,6 +101,8 @@ int[] tile_size = new int[]{256,256}; TileGrid grid = new TileGrid(4326, tile_size); + + String url = "http://localhost:9080/tms/Default%20Basemap/2/9/13.png"; mapproxy.tms.TileRequest req = new mapproxy.tms.TileRequest(url); @@ -187,8 +202,8 @@ private void testWebServices() throws Exception { - String url = "http://localhost:9080/ArcGIS/"; - //String url = "http://services.arcgisonline.com/ArcGIS/services/USA_Topo_Maps/MapServer"; + //String url = "http://localhost:9080/ArcGIS/"; + String url = "http://services.arcgisonline.com/ArcGIS/services/USA_Topo_Maps/MapServer"; //url = "http://services.arcgisonline.com/ArcGIS/services/"; //url = "http://sampleserver1.arcgisonline.com/ArcGIS/services/"; @@ -210,8 +225,8 @@ - String fileName = "MapProxy-2781"; - msg = new javaxt.io.File("/temp/ArcGIS/" + fileName + ".xml").getText("UTF-8"); + //String fileName = "MapProxy-2781"; + //msg = new javaxt.io.File("/temp/ArcGIS/" + fileName + ".xml").getText("UTF-8"); javaxt.http.Request request = new javaxt.http.Request(url); request.setHeader("Accept", "*/*"); request.setHeader("Content-Type", "text/xml"); @@ -221,8 +236,8 @@ javaxt.http.Response response = request.getResponse(); //System.out.println(response); //System.out.println(response.getStatus() + ": " + response.getMessage()); - //System.out.println(response.getText()); - new javaxt.io.File("/temp/ArcGIS/" + fileName + "_response.xml").write(response.getText(), "UTF-8"); + System.out.println(response.getText()); + //new javaxt.io.File("/temp/ArcGIS/" + fileName + "_response.xml").write(response.getText(), "UTF-8"); } Modified: core/BBox.java =================================================================== --- core/BBox.java 2011-04-14 00:55:30 UTC (rev 26) +++ core/BBox.java 2011-05-09 08:13:52 UTC (rev 27) @@ -34,6 +34,29 @@ this(minX, minY, maxX, maxY, null); } + + //************************************************************************** + //** Constructor + //************************************************************************** + /** "bbox" as a tuple (minx, miny, maxx, maxy). */ + + public BBox(String bbox){ + + if (bbox==null) return; //Throw Exception? + + String[] arr = bbox.split(","); + double[] box = new double[4]; + for (int i=0; i<box.length; i++){ + box[i] = Double.valueOf(arr[i]); + } + minX = box[0]; + minY = box[1]; + maxX = box[2]; + maxY = box[3]; + } + + + public double getMinX(){ return minX; } @@ -63,4 +86,14 @@ public String toString(){ return minX + "," + minY + "," + maxX + "," + maxY; } + + + public double[] toArray(){ + double[] box = new double[4]; + box[0] = minX; + box[1] = minY; + box[2] = maxX; + box[3] = maxY; + return box; + } } \ No newline at end of file Modified: core/Layer.java =================================================================== --- core/Layer.java 2011-04-14 00:55:30 UTC (rev 26) +++ core/Layer.java 2011-05-09 08:13:52 UTC (rev 27) @@ -290,7 +290,20 @@ } + else if (protocol.equalsIgnoreCase("TMS")){ + if (fileCache==null){ + Object[] affected_tiles = grid.get_affected_tiles(new BBox(bbox).toArray(), new int[]{width, height}, new SRS(srs), false); + double[] box = (double[]) affected_tiles[0]; + int[] _grid = (int[]) affected_tiles[1]; + Generator<int[]> tiles = (Generator<int[]>) affected_tiles[2]; + + } + else{ + + } + } + return null; } Modified: core/SRS.java =================================================================== --- core/SRS.java 2011-04-14 00:55:30 UTC (rev 26) +++ core/SRS.java 2011-05-09 08:13:52 UTC (rev 27) @@ -73,7 +73,7 @@ * get_epsg_num(4313) returns 4313 * get_epsg_num('31466') returns 31466 */ - private static int get_epsg_num(Object epsg_code){ + public static int get_epsg_num(Object epsg_code){ if (epsg_code instanceof String){ String epsg = (String) epsg_code; Modified: core/Service.java =================================================================== --- core/Service.java 2011-04-14 00:55:30 UTC (rev 26) +++ core/Service.java 2011-05-09 08:13:52 UTC (rev 27) @@ -22,6 +22,7 @@ private String[] formats; private java.util.List<Layer> layers = new java.util.ArrayList<Layer>(); private java.util.HashMap<String, Object> params = new java.util.HashMap<String, Object>(); + private String protocol; @@ -60,7 +61,8 @@ javaxt.http.Response response = new javaxt.http.Request(url.toString()).getResponse(); String[] contentType = response.getHeader("Content-Type").split(";"); String media = contentType[0].trim().toLowerCase(); - if (media.equals("text/xml") || media.equals("application/vnd.ogc.wms_xml")){ + if (media.equals("text/xml") || media.equals("application/xml") || + media.equals("application/vnd.ogc.wms_xml")){ Document doc = response.getXML(); Node outerNode = javaxt.xml.DOM.getOuterNode(doc); @@ -69,6 +71,9 @@ outerNodeName.equalsIgnoreCase("WMS_Capabilities")){ parseWMSCapabilities(doc); } + else if(outerNodeName.equalsIgnoreCase("TileMapService")){ + parseTMSCapabilities(doc); + } } @@ -103,6 +108,16 @@ //************************************************************************** + //** getProtocol + //************************************************************************** + /** Returns the type of service. */ + + public String getProtocol(){ + return this.protocol; + } + + + //************************************************************************** //** getTitle //************************************************************************** /** Returns the title of the service. */ @@ -262,15 +277,170 @@ } -// <editor-fold defaultstate="collapsed" desc="Parse WMS and ArcGIS Capabilities Documents. Click on the + sign on the left to edit the code."> +// <editor-fold defaultstate="collapsed" desc="Parse TMS Capabilities. Click on the + sign on the left to edit the code."> + //************************************************************************** + //** parseTMSCapabilities + //************************************************************************** + /** Used to parse a TMS Capabilities Document. */ + + private void parseTMSCapabilities(Document doc){ + + protocol = "TMS"; + + //Get Service Metadata + NodeList serviceInfo = javaxt.xml.DOM.getOuterNode(doc).getChildNodes(); + for (int i=0; i<serviceInfo.getLength(); i++){ + Node node = serviceInfo.item(i); + String nodeName = node.getNodeName(); + String nodeValue = node.getTextContent(); + if (nodeName.equalsIgnoreCase("Title")){ + this.title = nodeValue; + } + else if (nodeName.equalsIgnoreCase("Abstract")){ + this.description = nodeValue; + } + } + + //Get Layers + NodeList tileMaps = doc.getElementsByTagName("TileMap"); + for (int i=0; i<tileMaps.getLength(); i++){ + Node tileMap = tileMaps.item(i); + NamedNodeMap map = tileMap.getAttributes(); + for (int j=0; j<map.getLength(); j++){ + Node attr = map.item(j); + String attrName = attr.getNodeName(); + if (attrName.contains(":")) attrName = attrName.substring(attrName.indexOf(":")+1); + if (attrName.equalsIgnoreCase("href")){ + url = attr.getNodeValue(); + Layer layer = getTMSLayer(url); + if (layer==null && url.contains("/1.0.0/1.0.0/")){ + layer = getTMSLayer(url.replace("/1.0.0/1.0.0/", "/1.0.0/")); + } + if (layer!=null) layers.add(layer); + break; + } + } + } + + } + + private Layer getTMSLayer(String url){ + javaxt.http.Response response = new javaxt.http.Request(url).getResponse(); + if (response.getStatus()==200){ + Document doc = response.getXML(); + if (doc!=null){ + String name = null; + String description = null; + String srs = "EPSG:4326"; + double minX, minY, maxX, maxY; + minX = minY = maxX = maxY = 0; + int[] tile_size = new int[]{256,256}; + String format = "png"; + + NodeList nodes = javaxt.xml.DOM.getOuterNode(doc).getChildNodes(); + for (int i=0; i<nodes.getLength(); i++){ + Node node = nodes.item(i); + String nodeName = node.getNodeName(); + String nodeValue = node.getTextContent(); + if (nodeName.equalsIgnoreCase("Title")){ + name = nodeValue; + } + else if (nodeName.equalsIgnoreCase("Abstract")){ + description = nodeValue; + } + else if (nodeName.equalsIgnoreCase("SRS")){ + srs = nodeValue; + } + else if (nodeName.equalsIgnoreCase("BoundingBox")){ + + NamedNodeMap map = node.getAttributes(); + for (int j=0; j<map.getLength(); j++){ + Node attr = map.item(j); + String coordName = attr.getNodeName(); + String coord = attr.getNodeValue(); + + if (coordName.equalsIgnoreCase("minx")){ + minX = Double.parseDouble(coord); + } + if (coordName.equalsIgnoreCase("miny")){ + minY = Double.parseDouble(coord); + } + if (coordName.equalsIgnoreCase("maxx")){ + maxX = Double.parseDouble(coord); + } + if (coordName.equalsIgnoreCase("maxy")){ + maxY = Double.parseDouble(coord); + } + } + + + } + else if (nodeName.equalsIgnoreCase("TileFormat")){ + + int w = 256; + int h = 256; + + try{ + //<TileFormat width="256" height="256" mime-type="image/png" extension="png"/> + NamedNodeMap map = node.getAttributes(); + for (int j=0; j<map.getLength(); j++){ + Node attr = map.item(j); + String attrName = attr.getNodeName(); + String attrValue = attr.getNodeValue(); + if (attrName.equalsIgnoreCase("width")){ + w = Integer.parseInt(attrValue); + } + else if (attrName.equalsIgnoreCase("height")){ + h = Integer.parseInt(attrValue); + } + else if (attrName.equalsIgnoreCase("extension")){ + format = attrValue; + } + } + } + catch(Exception e){} + + tile_size = new int[]{w,h}; + } + } + + if (name!=null){ + Layer layer = new Layer(name); + layer.setDescription(description); + layer.setBBox(new BBox(minX, minY, maxX, maxY, srs)); + layer.addSRS(srs); + layer.setParam("host", url); + //layer.setParam("layers", layers); + layer.setParam("protocol", protocol); + + int epsg = SRS.get_epsg_num(srs); + layer.setParam("grid", new mapproxy.core.grid.TileGrid(epsg, tile_size)); + layer.setParam("format", format); + + + return layer; + } + + } + } + return null; + } + // </editor-fold> + + +// <editor-fold defaultstate="collapsed" desc="Parse WMS Capabilities. Click on the + sign on the left to edit the code."> + + //************************************************************************** //** parseWMSCapabilities //************************************************************************** /** Used to parse a WMS Capabilities Document. */ private void parseWMSCapabilities(Document doc){ + protocol = "WMS"; + NodeList serviceInfo = null; NodeList capabilities = null; NodeList outerNodes = javaxt.xml.DOM.getOuterNode(doc).getChildNodes(); @@ -444,8 +614,11 @@ + // </editor-fold> +// <editor-fold defaultstate="collapsed" desc="Parse ArcGIS Capabilities. Click on the + sign on the left to edit the code."> + //************************************************************************** //** parseArcGISCapabilities //************************************************************************** @@ -453,6 +626,9 @@ * service. */ private void parseArcGISCapabilities(String json){ + + protocol = "MapServer"; + try{ //Convert the JSON string into XML @@ -612,7 +788,7 @@ - +// </editor-fold> //************************************************************************** @@ -639,8 +815,4 @@ private String getNodeValue(Node node){ return javaxt.xml.DOM.getNodeValue(node); } - - // </editor-fold> - - } \ No newline at end of file Modified: core/grid/TileGrid.java =================================================================== --- core/grid/TileGrid.java 2011-04-14 00:55:30 UTC (rev 26) +++ core/grid/TileGrid.java 2011-05-09 08:13:52 UTC (rev 27) @@ -46,9 +46,9 @@ /** Creates a new instance of TileGrid. * * @param res_type the type of the multi-resolution pyramid. res_type: - * `RES_TYPE_CUSTOM`, `RES_TYPE_GLOBAL`, `RES_TYPE_SQRT2` + * "RES_TYPE_CUSTOM", "RES_TYPE_GLOBAL", "RES_TYPE_SQRT2" * @param levels the number of levels - * @param tile_size the size of each tile in pixel ``int(with), int(height)`` + * @param tile_size the size of each tile in pixel [int(with), int(height)] * @param bbox the bbox of the grid, tiles may overlap this bbox */ public TileGrid(int epsg, double[] bbox, int[] tile_size, String res, Modified: core/request/RequestParams.java =================================================================== --- core/request/RequestParams.java 2011-04-14 00:55:30 UTC (rev 26) +++ core/request/RequestParams.java 2011-05-09 08:13:52 UTC (rev 27) @@ -105,7 +105,8 @@ while (it.hasNext()){ String key = it.next(); String value = params.get(key, ""); - str.append(key + "=" + value); //str.append(key + "=" + java.net.URLEncoder.encode(value)); + //str.append(key + "=" + value); + str.append(key + "=" + java.net.URLEncoder.encode(value)); if (it.hasNext()) str.append("&"); } return str.toString(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-04-14 00:55:38
|
Revision: 26 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=26&view=rev Author: pborissow Date: 2011-04-14 00:55:30 +0000 (Thu, 14 Apr 2011) Log Message: ----------- Implemented tile seeding (first cut) Modified Paths: -------------- Main.java config/Config.java core/Layer.java core/Service.java core/ServiceException.java core/ServiceResponse.java core/cache/Cache.java Added Paths: ----------- core/Point.java core/Status.java core/TileSeeder.java Removed Paths: ------------- core/Point.java Modified: Main.java =================================================================== --- Main.java 2011-04-10 14:37:35 UTC (rev 25) +++ Main.java 2011-04-14 00:55:30 UTC (rev 26) @@ -1,6 +1,4 @@ package mapproxy; -import java.util.AbstractList; -import java.util.ArrayList; import mapproxy.wms.request.*; import mapproxy.wms.client.*; import mapproxy.core.grid.*; @@ -10,8 +8,9 @@ import mapproxy.config.Config; import mapproxy.server.HttpServer; -import javaxt.io.Directory; +import java.util.concurrent.ConcurrentHashMap; + //****************************************************************************** //** Main Application //****************************************************************************** @@ -61,7 +60,8 @@ //testSRS(); args = new String[]{"C:\\Documents and Settings\\peter.borissow\\My Documents\\Java\\Libraries\\mapproxy\\src\\mapproxy\\config.xml"}; - startServer(args); + //startServer(args); + seedTest(args); //testWebServices(); //testArcWebServices(); @@ -276,209 +276,85 @@ //************************************************************************** //** startServer //************************************************************************** - /** Used to start a HTTP Server used the service WMS Requests + /** Used to start a HTTP Server used the service Map Requests */ private void startServer(String[] args) throws Exception { + Config.load(getConfig(args)); + int numThreads = Config.base_config().get("threads").toInteger(); + int port = Config.base_config().get("port").toInteger(); - //Validate args - org.w3c.dom.Document xml = null; - if (args[args.length-1].toLowerCase().endsWith(".xml")){ - javaxt.io.File file = new javaxt.io.File(args[args.length-1]); - if (!file.exists()) throw new Exception("Config file not found: " + file); - else xml = file.getXML(); - } - else{ - throw new Exception("Config file is required"); - } + HttpServer mapserver = new HttpServer(port, numThreads); + mapserver.start(); + } - //Set local variables - String name = null; - String description = null; - int port = -1; - int numThreads = 1; - org.w3c.dom.NodeList layerNodes = null; + private void seedTest(String[] args) throws Exception { - //Parse outer nodes (service info and get layer nodes) - org.w3c.dom.NodeList outerNodes = javaxt.xml.DOM.getOuterNode(xml).getChildNodes(); - for (int i=0; i<outerNodes.getLength(); i++){ - org.w3c.dom.Node outerNode = outerNodes.item(i); - if (outerNode.getNodeType()==1){ - if (outerNode.getNodeName().equalsIgnoreCase("service")){ - org.w3c.dom.NodeList serviceInfo = outerNode.getChildNodes(); - for (int j=0; j<serviceInfo.getLength(); j++){ - org.w3c.dom.Node node = serviceInfo.item(j); - if (node.getNodeType()==1){ - String nodeName = node.getNodeName().toLowerCase(); - if (nodeName.equalsIgnoreCase("name")){ - name = javaxt.xml.DOM.getNodeValue(node); - } - if (nodeName.equalsIgnoreCase("description")){ - description = javaxt.xml.DOM.getNodeValue(node); - } - if (nodeName.equalsIgnoreCase("port")){ - port = Integer.parseInt(javaxt.xml.DOM.getNodeValue(node).trim()); - if (port < 1 || port > 65535) throw new Exception("Invalid Port: " + javaxt.xml.DOM.getNodeValue(node)); - } - if (nodeName.equalsIgnoreCase("numThreads")){ - numThreads = Integer.parseInt(javaxt.xml.DOM.getNodeValue(node).trim()); - if (numThreads < 1 || numThreads > 100000) throw new Exception("Invalid Number of Threads: " + javaxt.xml.DOM.getNodeValue(node)); - } - } - } - } - else if (outerNode.getNodeName().equalsIgnoreCase("layers")){ - layerNodes = outerNode.getChildNodes(); - } - else if (outerNode.getNodeName().equalsIgnoreCase("html")){ + double[] bbox = new double[]{-180,-90,180,90}; + String srs = "EPSG:4326"; + int levels = 12; - Config.base_config().set("html", javaxt.xml.DOM.getNodeValue( outerNode )); - //System.out.println( javaxt.xml.DOM.getNodeValue( outerNode )); - //layerNodes = outerNode.getChildNodes(); + Config.load(getConfig(args)); + Service service = ((mapproxy.core.Service) mapproxy.config.Config.base_config().get("mapproxy").toObject()); + Layer layer = service.getLayers()[0]; + Status status = layer.seed(2, bbox, srs, levels); - } - } - } + long lastUpdate = -1; + double percentComplete = -1; - //Create a new map service - mapproxy.core.Service mapproxy = new mapproxy.core.Service(name, "http://localhost:" + port); - mapproxy.setDescription(description); + while (true){ + synchronized (status) { + //while(status.getLastUpdate()<=lastUpdate){ + while (status.getPercentComplete()==percentComplete || !status.isComplete()) { + try { + status.wait(); + } + catch (InterruptedException e) { + } + } - //Parse layer info and create service layers - for (int i=0; i<layerNodes.getLength(); i++){ - org.w3c.dom.Node layerNode = layerNodes.item(i); - if (layerNode.getNodeType()==1){ + lastUpdate = status.getLastUpdate(); + percentComplete = status.getPercentComplete(); + status.notifyAll(); + + System.out.println(status.getPercentComplete()); + - String layerName = null; - String host = null; - String layers = null; - String cacheFormat = "png"; - String cacheDir = null; - String protocol = "WMS"; - int[] tile_size = new int[]{256,256}; - - - org.w3c.dom.NodeList params = layerNode.getChildNodes(); - for (int j=0; j<params.getLength(); j++){ - org.w3c.dom.Node param = params.item(j); - if (param.getNodeType()==1){ - - - //Get layer name/alias - if (param.getNodeName().equalsIgnoreCase("name")){ - layerName = param.getTextContent(); - if (layerName==null || layerName.trim().length()==0){ - break; - } - } - - //Get host information - if (param.getNodeName().equalsIgnoreCase("host")){ - org.w3c.dom.NodeList nodes = param.getChildNodes(); - for (int k=0; k<nodes.getLength(); k++){ - org.w3c.dom.Node node = nodes.item(k); - if (node.getNodeType()==1){ - if (node.getNodeName().equalsIgnoreCase("BaseRequest")){ - host = node.getTextContent(); - if (host==null || host.trim().length()==0){ - break; - } - else{ - host = host.trim(); - } - - protocol = javaxt.xml.DOM.getAttributeValue(node.getAttributes(), "protocol"); - - } - if (node.getNodeName().equalsIgnoreCase("layers")){ - layers = node.getTextContent(); - if (layers==null || layers.trim().length()==0){ - break; - } - else{ - if (layers.contains(",")){ - String[] arr = layers.split(","); - layers = ""; - for (int x=0; x<arr.length; x++){ - layers+=arr[x].trim(); - if (x<arr.length-1) layers+=","; - } - } - } - } - } - } - - - } - - - //Parse Cache Parameters - if (param.getNodeName().equalsIgnoreCase("FileCache")){ - org.w3c.dom.NodeList nodes = param.getChildNodes(); - for (int k=0; k<nodes.getLength(); k++){ - org.w3c.dom.Node node = nodes.item(k); - if (node.getNodeType()==1){ - if (node.getNodeName().equalsIgnoreCase("CacheDirectory")){ - cacheDir = node.getTextContent(); - } - if (node.getNodeName().equalsIgnoreCase("Format")){ - cacheFormat = node.getTextContent(); - } - if (node.getNodeName().equalsIgnoreCase("TileSize")){ - String[] arr = node.getTextContent().trim().split(","); - int width = Integer.parseInt(arr[0].trim()); - int height = Integer.parseInt(arr[1].trim()); - if (width < 1 || height < 1) throw new Exception("Invalid Tile Size: " + arr); - } - } - } - } - - - } + if (status.getPercentComplete()==1){ + System.out.println("Done!"); + return; } + } - if (layerName==null || host==null || layers==null) break; + } - mapproxy.core.Layer layer = new mapproxy.core.Layer(layerName); - layer.addSRS("EPSG:4326"); - layer.setBBox(new mapproxy.core.BBox(-180,-90,180,90,"EPSG:4326")); - layer.setParam("host", host); - layer.setParam("layers", layers); - layer.setParam("protocol", protocol); + } - if (cacheDir!=null){ - layer.setParam("cache", new FileCache(cacheDir, cacheFormat)); - layer.setParam("grid", new TileGrid(4326, tile_size)); - } - mapproxy.addLayer(layer); - + private org.w3c.dom.Document getConfig(String[] args) throws Exception { + if (args[args.length-1].toLowerCase().endsWith(".xml")){ + javaxt.io.File file = new javaxt.io.File(args[args.length-1]); + if (!file.exists()) throw new Exception("Config file not found: " + file); + else { + return file.getXML(); } } + else{ + throw new Exception("Config file is required"); + } + } - if (mapproxy.getLayers().length<1) throw new Exception("No Layers to Process!"); - //Add the service object to the global config and start the http server - Config.base_config().set("mapproxy", mapproxy); - HttpServer mapserver = new HttpServer(port, numThreads); - mapserver.start(); - } - - - - //************************************************************************** //** testWMSClient //************************************************************************** Modified: config/Config.java =================================================================== --- config/Config.java 2011-04-10 14:37:35 UTC (rev 25) +++ config/Config.java 2011-04-14 00:55:30 UTC (rev 26) @@ -1,10 +1,12 @@ package mapproxy.config; +import mapproxy.core.cache.FileCache; +import mapproxy.core.grid.TileGrid; //****************************************************************************** //** Config Class //****************************************************************************** /** - * Enter class description here + * Provides static methods to initialize and access config settings. * ******************************************************************************/ @@ -17,4 +19,191 @@ return options; } + + public static void load(org.w3c.dom.Document xml) throws Exception { + + + //Set local variables + String name = null; + String description = null; + int port = -1; + int numThreads = 1; + org.w3c.dom.NodeList layerNodes = null; + + + //Parse outer nodes (service info and get layer nodes) + org.w3c.dom.NodeList outerNodes = javaxt.xml.DOM.getOuterNode(xml).getChildNodes(); + for (int i=0; i<outerNodes.getLength(); i++){ + org.w3c.dom.Node outerNode = outerNodes.item(i); + if (outerNode.getNodeType()==1){ + if (outerNode.getNodeName().equalsIgnoreCase("service")){ + org.w3c.dom.NodeList serviceInfo = outerNode.getChildNodes(); + for (int j=0; j<serviceInfo.getLength(); j++){ + org.w3c.dom.Node node = serviceInfo.item(j); + if (node.getNodeType()==1){ + String nodeName = node.getNodeName().toLowerCase(); + if (nodeName.equalsIgnoreCase("name")){ + name = javaxt.xml.DOM.getNodeValue(node); + } + if (nodeName.equalsIgnoreCase("description")){ + description = javaxt.xml.DOM.getNodeValue(node); + } + if (nodeName.equalsIgnoreCase("port")){ + port = Integer.parseInt(javaxt.xml.DOM.getNodeValue(node).trim()); + if (port < 1 || port > 65535) throw new Exception("Invalid Port: " + javaxt.xml.DOM.getNodeValue(node)); + } + if (nodeName.equalsIgnoreCase("numThreads")){ + numThreads = Integer.parseInt(javaxt.xml.DOM.getNodeValue(node).trim()); + if (numThreads < 1 || numThreads > 100000) throw new Exception("Invalid Number of Threads: " + javaxt.xml.DOM.getNodeValue(node)); + } + } + } + } + else if (outerNode.getNodeName().equalsIgnoreCase("layers")){ + layerNodes = outerNode.getChildNodes(); + } + else if (outerNode.getNodeName().equalsIgnoreCase("html")){ + + Config.base_config().set("html", javaxt.xml.DOM.getNodeValue( outerNode )); + //System.out.println( javaxt.xml.DOM.getNodeValue( outerNode )); + //layerNodes = outerNode.getChildNodes(); + + } + } + } + + + //Create a new map service + mapproxy.core.Service mapproxy = new mapproxy.core.Service(name, "http://localhost:" + port); + mapproxy.setDescription(description); + + + //Parse layer info and create service layers + for (int i=0; i<layerNodes.getLength(); i++){ + org.w3c.dom.Node layerNode = layerNodes.item(i); + if (layerNode.getNodeType()==1){ + + String layerName = null; + String host = null; + String layers = null; + String cacheFormat = "png"; + String cacheDir = null; + String protocol = "WMS"; + int[] tile_size = new int[]{256,256}; + + + org.w3c.dom.NodeList params = layerNode.getChildNodes(); + for (int j=0; j<params.getLength(); j++){ + org.w3c.dom.Node param = params.item(j); + if (param.getNodeType()==1){ + + + //Get layer name/alias + if (param.getNodeName().equalsIgnoreCase("name")){ + layerName = param.getTextContent(); + if (layerName==null || layerName.trim().length()==0){ + break; + } + } + + //Get host information + if (param.getNodeName().equalsIgnoreCase("host")){ + org.w3c.dom.NodeList nodes = param.getChildNodes(); + for (int k=0; k<nodes.getLength(); k++){ + org.w3c.dom.Node node = nodes.item(k); + if (node.getNodeType()==1){ + if (node.getNodeName().equalsIgnoreCase("BaseRequest")){ + host = node.getTextContent(); + if (host==null || host.trim().length()==0){ + break; + } + else{ + host = host.trim(); + } + + protocol = javaxt.xml.DOM.getAttributeValue(node.getAttributes(), "protocol"); + + } + if (node.getNodeName().equalsIgnoreCase("layers")){ + layers = node.getTextContent(); + if (layers==null || layers.trim().length()==0){ + break; + } + else{ + if (layers.contains(",")){ + String[] arr = layers.split(","); + layers = ""; + for (int x=0; x<arr.length; x++){ + layers+=arr[x].trim(); + if (x<arr.length-1) layers+=","; + } + } + } + } + } + } + + + } + + + //Parse Cache Parameters + if (param.getNodeName().equalsIgnoreCase("FileCache")){ + org.w3c.dom.NodeList nodes = param.getChildNodes(); + for (int k=0; k<nodes.getLength(); k++){ + org.w3c.dom.Node node = nodes.item(k); + if (node.getNodeType()==1){ + if (node.getNodeName().equalsIgnoreCase("CacheDirectory")){ + cacheDir = node.getTextContent(); + } + if (node.getNodeName().equalsIgnoreCase("Format")){ + cacheFormat = node.getTextContent(); + } + if (node.getNodeName().equalsIgnoreCase("TileSize")){ + String[] arr = node.getTextContent().trim().split(","); + int width = Integer.parseInt(arr[0].trim()); + int height = Integer.parseInt(arr[1].trim()); + if (width < 1 || height < 1) throw new Exception("Invalid Tile Size: " + arr); + } + } + } + } + + + } + } + + if (layerName==null || host==null || layers==null) break; + + + + mapproxy.core.Layer layer = new mapproxy.core.Layer(layerName); + layer.addSRS("EPSG:4326"); + layer.setBBox(new mapproxy.core.BBox(-180,-90,180,90,"EPSG:4326")); + layer.setParam("host", host); + layer.setParam("layers", layers); + layer.setParam("protocol", protocol); + + if (cacheDir!=null){ + layer.setParam("cache", new FileCache(cacheDir, cacheFormat)); + layer.setParam("grid", new TileGrid(4326, tile_size)); + } + mapproxy.addLayer(layer); + + + } + } + + + + if (mapproxy.getLayers().length<1) throw new Exception("No Layers to Process!"); + + + //Add the service object to the global config and start the http server + Config.base_config().set("mapproxy", mapproxy); + Config.base_config().set("threads", numThreads); + Config.base_config().set("port", port); + + } + } Modified: core/Layer.java =================================================================== --- core/Layer.java 2011-04-10 14:37:35 UTC (rev 25) +++ core/Layer.java 2011-04-14 00:55:30 UTC (rev 26) @@ -1,4 +1,12 @@ package mapproxy.core; +import mapproxy.wms.request.*; +import mapproxy.wms.client.*; +import mapproxy.core.grid.*; +import mapproxy.core.cache.*; +import mapproxy.wms.cache.WMSTileSource; +import mapproxy.arcgis.cache.*; +import mapproxy.arcgis.client.*; +import java.util.concurrent.ConcurrentHashMap; //****************************************************************************** //** Layer Class @@ -10,7 +18,7 @@ * ******************************************************************************/ -public class Layer { +public class Layer implements Comparable { private String name; private String description; @@ -106,14 +114,7 @@ /** Returns an array of sub-layers (children) of this layer */ public Layer[] getLayers(){ - Layer[] arr = new Layer[layers.size()]; - int i=0; - java.util.Iterator<Layer> it = layers.iterator(); - while (it.hasNext()){ - arr[i] = it.next(); - i++; - } - return arr; + return layers.toArray(new Layer[layers.size()]); } //************************************************************************** @@ -200,6 +201,8 @@ this.bbox = bbox; } + + @Override //************************************************************************** //** toString //************************************************************************** @@ -209,8 +212,117 @@ return name; } + @Override public int hashCode(){ return name.toUpperCase().hashCode(); } + + @Override + public int compareTo(Object obj){ + if (obj==null) return -1; + else return -obj.toString().compareTo(name.toUpperCase()); + } + + + + + + //************************************************************************** + //** getImage + //************************************************************************** + /** Used to return an image for a given bbox. + * @param width Image width + * @param height Image height + * @param format Requested format + * @param bbox Bounding box + * @param srs Spatial reference system associated with the bbox. + */ + public javaxt.io.Image getImage(int width, int height, String format, String bbox, String srs){ + + FileCache fileCache = (FileCache) this.getParam("cache"); + TileGrid grid = (TileGrid) this.getParam("grid"); + + String host = (String) this.getParam("host"); + if (!host.contains("?")) host += "?"; + //host += url.getQueryString(); + + WMSMapRequestParams param = new WMSMapRequestParams(); + param.set("layers", (String) this.getParam("layers")); + param.set("bbox", bbox); + + WMS111MapRequest req = new WMS111MapRequest(param, host); + req.params.size(new int[]{width, height}); + req.params.set("srs", srs); + + + + //if (format.equalsIgnoreCase("image/PNG24")) format = "jpeg"; //<-- This is crazy! If I return a 24 bit PNG, ArcMap doesn't display anything. If I return a JPEG, works like a champ + if (!format.toLowerCase().startsWith("image/")) format = "image/" + format; + if (format.equalsIgnoreCase("image/PNG24") && fileCache!=null) format = "image/png"; + //format = "image/png"; + req.params.set("format", format); + + String protocol = (String) this.getParam("protocol"); + if (protocol.equalsIgnoreCase("WMS")){ + + if (fileCache==null){ + return new WMSClient(req).get_map(req); + } + else{ + WMSTileSource wms = new WMSTileSource(grid, new WMSClient(req)); + CacheManager cacheManager = new CacheManager(fileCache, wms); + Cache cache = new Cache(cacheManager, grid, true); + return cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()); + } + } + else if (protocol.equalsIgnoreCase("MapServer")){ + + if (fileCache==null){ + return new MapClient(req).get_map(req); + } + else{ + MapTileSource arcMapServer = new MapTileSource(grid, new MapClient(req)); + CacheManager cacheManager = new CacheManager(fileCache, arcMapServer); + Cache cache = new Cache(cacheManager, grid, true); + return cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()); + } + + + } + + return null; + + } + + + public javaxt.io.Image getImage(int width, int height, String format, double[] bbox, String srs){ + return this.getImage(width, height, format, bbox[0] + "," + bbox[1] + "," + bbox[2] + "," + bbox[3], srs); + } + + + + //************************************************************************** + //** seedLayers + //************************************************************************** + /** Used to seed the current layer at a given point + * + * @param bbox Bounding box + * @param srs Spatial reference system associated with the bbox. + * @param levels Number of resolution levels + * @return Returns a HashMap with status information. Keys include + * "Total Files", "Total Processed", and "Is Complete". + */ + public Status seed(int numThreads, double[] bbox, String srs, int levels){ + if (numThreads<1) numThreads = 1; + for (int i=0; i<numThreads; i++){ + Thread t = new Thread(new TileSeeder()); + t.start(); + } + + + + return TileSeeder.addLayer(this, bbox, levels); + } + } \ No newline at end of file Deleted: core/Point.java =================================================================== --- core/Point.java 2011-04-10 14:37:35 UTC (rev 25) +++ core/Point.java 2011-04-14 00:55:30 UTC (rev 26) @@ -1,42 +0,0 @@ -package mapproxy.core; - -//****************************************************************************** -//** Point Class -//****************************************************************************** -/** - * Enter class description here - * - ******************************************************************************/ - -public class Point { - - - public double x; - public double y; - - //************************************************************************** - //** Constructor - //************************************************************************** - /** Creates a new instance of Point. */ - - public Point(double x, double y){ - this.x = x; - this.y = y; - } - - @Override - public String toString(){ - return x + ", " + y; - } - - @Override - public boolean equals(Object obj){ - if (obj instanceof Point){ - Point point = (Point) obj; - return (this.x == point.x && this.y == point.y); - } - return false; - } - - -} Added: core/Point.java =================================================================== --- core/Point.java (rev 0) +++ core/Point.java 2011-04-14 00:55:30 UTC (rev 26) @@ -0,0 +1,42 @@ +package mapproxy.core; + +//****************************************************************************** +//** Point Class +//****************************************************************************** +/** + * Enter class description here + * + ******************************************************************************/ + +public class Point { + + + public double x; + public double y; + + //************************************************************************** + //** Constructor + //************************************************************************** + /** Creates a new instance of Point. */ + + public Point(double x, double y){ + this.x = x; + this.y = y; + } + + @Override + public String toString(){ + return x + ", " + y; + } + + @Override + public boolean equals(Object obj){ + if (obj instanceof Point){ + Point point = (Point) obj; + return (this.x == point.x && this.y == point.y); + } + return false; + } + + +} Modified: core/Service.java =================================================================== --- core/Service.java 2011-04-10 14:37:35 UTC (rev 25) +++ core/Service.java 2011-04-14 00:55:30 UTC (rev 26) @@ -24,6 +24,7 @@ private java.util.HashMap<String, Object> params = new java.util.HashMap<String, Object>(); + //************************************************************************** //** Constructor //************************************************************************** @@ -160,6 +161,12 @@ return params.get(key); } + + //************************************************************************** + //** setParam + //************************************************************************** + /** Sets a parameter with given key. */ + public void setParam(String key, Object val){ params.put(key, val); } @@ -209,21 +216,30 @@ /** Returns a complete list of layers associated with this service. */ public Layer[] getLayers(){ - Layer[] arr = new Layer[layers.size()]; - int i=0; - java.util.Iterator<Layer> it = layers.iterator(); - while (it.hasNext()){ - arr[i] = it.next(); - i++; - } - return arr; + return layers.toArray(new Layer[layers.size()]); } + //************************************************************************** + //** getResponse + //************************************************************************** + /** Used to generate a response to a service request. The response might + * include an image or a capabilities document. + * @param requestURL Requested URL (e.g. WMS GetMap request) + * @param requestBody Body of the http request. Typically contains the + * contents of an HTTP Post request, including any SOAP messages. + */ public ServiceResponse getResponse(String requestURL, String requestBody) throws Exception { return new ServiceResponse(requestURL, requestBody, this); } + //************************************************************************** + //** getResponse + //************************************************************************** + /** Used to generate a response to a service request. The response might + * include an image or a capabilities document. + * @param requestURL Requested URL (e.g. WMS GetMap request) + */ public ServiceResponse getResponse(String requestURL) throws Exception { return this.getResponse(requestURL, null); } @@ -627,5 +643,4 @@ // </editor-fold> - } \ No newline at end of file Modified: core/ServiceException.java =================================================================== --- core/ServiceException.java 2011-04-10 14:37:35 UTC (rev 25) +++ core/ServiceException.java 2011-04-14 00:55:30 UTC (rev 26) @@ -23,13 +23,25 @@ } private String getWMSException(String error){ - StringBuffer str = new StringBuffer(); - str.append("<?xml version='1.0' encoding=\"ISO-8859-1\" standalone=\"no\" ?>"); - str.append("<!DOCTYPE ServiceExceptionReport SYSTEM \"http://schemas.opengis.net/wms/1.1.1/exception_1_1_1.dtd\">"); - str.append("<ServiceExceptionReport version=\"1.1.1\"><ServiceException>"); - str.append(error); - str.append("</ServiceException></ServiceExceptionReport>"); - return str.toString(); + StringBuffer xml = new StringBuffer(); + xml.append("<?xml version='1.0' encoding=\"ISO-8859-1\" standalone=\"no\" ?>"); + xml.append("<!DOCTYPE ServiceExceptionReport SYSTEM \"http://schemas.opengis.net/wms/1.1.1/exception_1_1_1.dtd\">"); + xml.append("<ServiceExceptionReport version=\"1.1.1\"><ServiceException>"); + xml.append(error); + xml.append("</ServiceException></ServiceExceptionReport>"); + return xml.toString(); } + + private String getTMSException(String error){ + StringBuffer xml = new StringBuffer(); + xml.append("<?xml version=\"1.0\" ?>"); + xml.append("<TileMapServerError>"); + xml.append("<Message>"); + xml.append(error); + xml.append("</Message>"); + xml.append("</TileMapServerError>"); + return xml.toString(); + } + } \ No newline at end of file Modified: core/ServiceResponse.java =================================================================== --- core/ServiceResponse.java 2011-04-10 14:37:35 UTC (rev 25) +++ core/ServiceResponse.java 2011-04-14 00:55:30 UTC (rev 26) @@ -1,11 +1,6 @@ package mapproxy.core; -import mapproxy.wms.request.*; -import mapproxy.wms.client.*; import mapproxy.core.grid.*; import mapproxy.core.cache.*; -import mapproxy.wms.cache.WMSTileSource; -import mapproxy.arcgis.cache.*; -import mapproxy.arcgis.client.*; import org.w3c.dom.*; import javaxt.xml.DOM; @@ -215,10 +210,18 @@ String url = this.url.toString(); if (url.contains("?")) url = url.substring(0, url.indexOf("?")); - String html = mapproxy.config.Config.base_config().get("html").toString(); + String html; + if (mapproxy.config.Config.base_config().get("html")!=null){ + html = mapproxy.config.Config.base_config().get("html").toString(); + } + else{ + html = "<html><body><h1>@SERVICENAME</h1><p>@SERVICEDESCRIPTION</p>Layers:<ul>@LAYERS</ul>Services:<ul>@SERVICES</ul></body></html>"; + } + + html = html.replace("@SERVICENAME", service.getName()); html = html.replace("@SERVICEDESCRIPTION", service.getDescription()); - + StringBuffer layers = new StringBuffer(); for (Layer layer : service.getLayers()){ layers.append("<li>" + layer.getName() + "</li>"); @@ -276,7 +279,8 @@ if (fileCache==null){ TileGrid grid = new TileGrid(4326, new int[]{256,256}); //<--Maybe there's a way to encode these parameters in the URL? Need to check the TMS spec... double[] bbox = grid.tile_bbox(req.tile[0], req.tile[1], req.tile[2]); - rsp = getImage(layer, grid.tile_size[0], grid.tile_size[1], format, bbox, grid.srs.toString()).getByteArray(format); + rsp = layer.getImage(grid.tile_size[0], grid.tile_size[1], format, bbox, grid.srs.toString()).getByteArray(format); + //rsp = getImage(layer, grid.tile_size[0], grid.tile_size[1], format, bbox, grid.srs.toString()).getByteArray(format); } else{ @@ -305,7 +309,8 @@ //Create image and update cache double[] bbox = grid.tile_bbox(req.tile[0], req.tile[1], req.tile[2]); - rsp = getImage(layer, grid.tile_size[0], grid.tile_size[1], fileCache.file_ext, bbox, grid.srs.toString()).getByteArray(format); + rsp = layer.getImage(grid.tile_size[0], grid.tile_size[1], fileCache.file_ext, bbox, grid.srs.toString()).getByteArray(format); + //rsp = getImage(layer, grid.tile_size[0], grid.tile_size[1], fileCache.file_ext, bbox, grid.srs.toString()).getByteArray(format); } } @@ -358,7 +363,8 @@ } if (layer!=null){ - image.addImage(getImage(layer, width, height, format, bbox, srs), 0, 0, false); + image.addImage(layer.getImage(width, height, format, bbox, srs), 0, 0, false); + //image.addImage(getImage(layer, width, height, format, bbox, srs), 0, 0, false); } } @@ -471,78 +477,7 @@ } - //************************************************************************** - //** getImage - //************************************************************************** - /** Used to retrieve an image from a server for a given layer - */ - private javaxt.io.Image getImage(mapproxy.core.Layer layer, int width, int height, String format, String bbox, String srs){ - - FileCache fileCache = (FileCache) layer.getParam("cache"); - TileGrid grid = (TileGrid) layer.getParam("grid"); - - String host = (String) layer.getParam("host"); - if (!host.contains("?")) host += "?"; - //host += url.getQueryString(); - - WMSMapRequestParams param = new WMSMapRequestParams(); - param.set("layers", (String) layer.getParam("layers")); - param.set("bbox", bbox); - - WMS111MapRequest req = new WMS111MapRequest(param, host); - req.params.size(new int[]{width, height}); - req.params.set("srs", srs); - - - - //if (format.equalsIgnoreCase("image/PNG24")) format = "jpeg"; //<-- This is crazy! If I return a 24 bit PNG, ArcMap doesn't display anything. If I return a JPEG, works like a champ - if (!format.toLowerCase().startsWith("image/")) format = "image/" + format; - if (format.equalsIgnoreCase("image/PNG24") && fileCache!=null) format = "image/png"; - //format = "image/png"; - req.params.set("format", format); - - String protocol = (String) layer.getParam("protocol"); - if (protocol.equalsIgnoreCase("WMS")){ - - if (fileCache==null){ - return new WMSClient(req).get_map(req); - } - else{ - WMSTileSource wms = new WMSTileSource(grid, new WMSClient(req)); - CacheManager cacheManager = new CacheManager(fileCache, wms); - Cache cache = new Cache(cacheManager, grid, true); - return cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()); - } - } - else if (protocol.equalsIgnoreCase("MapServer")){ - - if (fileCache==null){ - return new MapClient(req).get_map(req); - } - else{ - MapTileSource arcMapServer = new MapTileSource(grid, new MapClient(req)); - CacheManager cacheManager = new CacheManager(fileCache, arcMapServer); - Cache cache = new Cache(cacheManager, grid, true); - return cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()); - } - - - } - - return null; - - } - - - private javaxt.io.Image getImage(mapproxy.core.Layer layer, int width, int height, String format, double[] bbox, String srs){ - return this.getImage(layer, width, height, format, bbox[0] + "," + bbox[1] + "," + bbox[2] + "," + bbox[3], srs); - } - - - - - //************************************************************************** //** getWMSCapabilities //************************************************************************** /** Used to construct a response to a WMS GetCapabilities request Added: core/Status.java =================================================================== --- core/Status.java (rev 0) +++ core/Status.java 2011-04-14 00:55:30 UTC (rev 26) @@ -0,0 +1,61 @@ +package mapproxy.core; + +//****************************************************************************** +//** Status Class +//****************************************************************************** +/** + * Enter class description here + * + ******************************************************************************/ + +public class Status { + + private int numTiles = 0; + private int totalTiles = -1; + private long lastUpdate = -1; + + //************************************************************************** + //** Constructor + //************************************************************************** + /** Creates a new instance of Status. */ + + public Status(){ + + } + + protected void setTotal(int totalTiles){ + this.totalTiles = totalTiles; + lastUpdate = new java.util.Date().getTime(); + } + + public long getLastUpdate(){ + return lastUpdate; + } + + public double getPercentComplete(){ + if (totalTiles>0){ + return (double)numTiles/(double)totalTiles; + } + else{ + return 0; + } + } + + public boolean isComplete(){ + return (numTiles==totalTiles); + } + + protected void updateTileCount(){ + numTiles++; + lastUpdate = new java.util.Date().getTime(); + } + + public int getNumTilesProcessed(){ + return this.numTiles; + } + + public int getTotalTiles(){ + return this.totalTiles; + } + +} Added: core/TileSeeder.java =================================================================== --- core/TileSeeder.java (rev 0) +++ core/TileSeeder.java 2011-04-14 00:55:30 UTC (rev 26) @@ -0,0 +1,284 @@ +package mapproxy.core; +import mapproxy.core.cache.*; +import mapproxy.core.grid.TileGrid; +import java.util.concurrent.ConcurrentHashMap; + +//****************************************************************************** +//** TileSeeder Class +//****************************************************************************** +/** + * Thread used to generate a tile cache + * + ******************************************************************************/ + +public class TileSeeder implements Runnable { + + private static java.util.List<Object[]> seeds = new java.util.LinkedList<Object[]>(); + + private static ConcurrentHashMap<Integer, Layer> layers = new ConcurrentHashMap<Integer, Layer>(); + + private static ConcurrentHashMap<Integer, Status> stats = new ConcurrentHashMap<Integer, Status>(); + + + + //************************************************************************** + //** TileIterator + //************************************************************************** + /** Class used to iterate through tiles and add them to the queue */ + + private static class TileIterator implements Runnable { + int layerID; + private double[] bbox; + private int levels; + private TileIterator(int layerID, double[] bbox, int levels){ + this.layerID = layerID; + this.bbox = bbox; + this.levels = levels; + } + public void run(){ + + + + Layer layer; + synchronized (layers) { + layer = layers.get(layerID); + layers.notifyAll(); + } + + TileGrid grid = (TileGrid) layer.getParam("grid"); + + + int numTiles = 0; + for (int level=0; level<levels; level++){ + Object[] arr = _create_tile_iterator(grid, bbox, level); + //int est_number_of_tiles = (Integer) arr[0]; + Generator<int[]> tiles = (Generator<int[]>) arr[1]; + + + for (int[] tile : tiles){ + + synchronized (seeds) { + seeds.add(seeds.size(), new Object[]{layerID, tile}); + seeds.notifyAll(); + } + + numTiles++; + + } + + } + + + //Update the stats for this layer + synchronized (stats){ + + Status status = stats.get(layerID); + synchronized (status){ + status.setTotal(numTiles); + status.notifyAll(); + } + + //stats.get(layerID).setTotal(numTiles); + stats.notifyAll(); + } + + + /* + //Add null tile to notify the threads that we are done + synchronized (seeds) { + seeds.add(seeds.size(), new Object[]{layerID, numTiles}); + seeds.notifyAll(); + } + */ + + + } + } + + + //************************************************************************** + //** Constructor + //************************************************************************** + /** Creates a new instance of TileSeeder. */ + + public TileSeeder(){ + } + + + + //************************************************************************** + //** addLayer + //************************************************************************** + /** Used to add a layer for the TileSeeder to process. */ + + public static Status addLayer(Layer layer, double[] bbox, int levels){ + + + FileCache cache = (FileCache) layer.getParam("cache"); + TileGrid grid = (TileGrid) layer.getParam("grid"); + if (cache==null || grid==null) return null; + + + int layerID; + synchronized (layers) { + layerID = layers.size(); + layers.put(layerID, layer); + layers.notifyAll(); + } + + + Status status = new Status(); + + synchronized (stats){ + stats.put(layerID, status); + stats.notifyAll(); + } + + new Thread(new TileIterator(layerID, bbox, levels)).run(); + + return status; + + } + + + /* + public static void stop(){ + synchronized (seeds) { + seeds.add(seeds.size(), null); + seeds.notifyAll(); + } + } + */ + + + //************************************************************************** + //** run + //************************************************************************** + /** Used to process tiles added to the queue. */ + + public void run(){ + while (true) { + + //Find request in pool + Object[] arr; + synchronized (seeds) { + while (seeds.isEmpty()) { + try { + seeds.wait(); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + } + arr = (Object[]) seeds.remove(0); + if (arr==null){ + seeds.add(null); + seeds.notifyAll(); + return; + } + } + + + + + Layer layer; + int layerID = (Integer) arr[0]; + synchronized (layers) { + layer = layers.get(layerID); + layers.notifyAll(); + } + + Object obj = arr[1]; + if (obj instanceof int[]){ + int[] tile = (int[]) obj; + FileCache cache = (FileCache) layer.getParam("cache"); + TileGrid grid = (TileGrid) layer.getParam("grid"); + layer.getImage(grid.tile_size[0], grid.tile_size[1], cache.file_ext, grid.tile_bbox(tile[0],tile[1],tile[2]), grid.srs.toString()); + /* + System.out.println(Python.cstr(tile)); + try{ + Thread.sleep(500); + } + catch(Exception e){} + */ + + synchronized (stats){ + //Integer numTiles = (Integer) stats.get(layerID).get("Total Processed"); + //if (numTiles==null) numTiles = 0; + Status status = stats.get(layerID); + synchronized (status){ + status.updateTileCount(); + status.notifyAll(); + } + + stats.notifyAll(); + } + + + /* + synchronized (stats){ + Integer total = (Integer) stats.get(layerID).get("Total Files"); + if (total!=null){ + Integer numTiles = (Integer) stats.get(layerID).get("Total Processed"); + if (numTiles==null) numTiles = 0; + if (numTiles==total){ + stats.get(layerID).put("Is Complete", true); + } + } + stats.notifyAll(); + } + */ + + + } + + + + + } // end while + } + + + + + + //************************************************************************** + //** _create_tile_iterator + //************************************************************************** + /** Return all tiles that intersect the `bbox` on `level`. + * @return estimated number of tiles, tile iterator + */ + private static Object[] _create_tile_iterator(TileGrid grid, double[] bbox, int level){ + + double res = grid.resolution(level); + int[] pixelSize = bbox_pixel_size(bbox, res); + int w = pixelSize[0]; + int h = pixelSize[1]; + + Object[] affected_tiles = grid.get_affected_tiles(bbox, pixelSize, null, false); + bbox = (double[]) affected_tiles[0]; + //int[] _grid = (int[]) affected_tiles[1]; + Generator<int[]> tiles = (Generator<int[]>) affected_tiles[2]; + + int est_number_of_tiles = cint((w/grid.tile_size[0] * + h/grid.tile_size[1])); + return new Object[]{est_number_of_tiles, tiles}; + } + + + //************************************************************************** + //** bbox_pixel_size + //************************************************************************** + /** Return the size of the `bbox` in pixel at the given `res`. + */ + private static int[] bbox_pixel_size(double[] bbox, double res){ + double w = bbox[2] - bbox[0]; + double h = bbox[3] - bbox[1]; + return new int[]{cint(w/res), cint(h/res)}; + } + + private static int cint(double d){ + return javaxt.utils.string.toInt(d); + } + +} Modified: core/cache/Cache.java =================================================================== --- core/cache/Cache.java 2011-04-10 14:37:35 UTC (rev 25) +++ core/cache/Cache.java 2011-04-14 00:55:30 UTC (rev 26) @@ -123,8 +123,10 @@ * @return `ImageSource` */ public javaxt.io.Image image(double[] req_bbox, SRS req_srs, int[] out_size){ - System.out.println("src_srs: " + this.grid.srs); - System.out.println("req_srs: " + req_srs); + if (!this.grid.srs.equals(req_srs)){ + System.out.println("src_srs: " + this.grid.srs); + System.out.println("req_srs: " + req_srs); + } TiledImage tiled_image = this._tiled_image(req_bbox, req_srs, out_size); return tiled_image.transform(req_bbox, req_srs, out_size); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-04-10 14:37:44
|
Revision: 25 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=25&view=rev Author: pborissow Date: 2011-04-10 14:37:35 +0000 (Sun, 10 Apr 2011) Log Message: ----------- Implemented new ServiceResponse class to help abstract some of the complexities associated with generating maps and service responses. Updated the RequestProcessor class to leverage the new ServiceResponse class. This made the RequestProcessor class a lot simpler and easier to manage. Modified Paths: -------------- Main.java core/Capabilities.java core/Service.java core/ServiceException.java core/image/ImageTransformer.java server/RequestProcessor.java Added Paths: ----------- core/Generator.java core/ServiceResponse.java Removed Paths: ------------- core/Generator.java Modified: Main.java =================================================================== --- Main.java 2011-04-05 11:36:23 UTC (rev 24) +++ Main.java 2011-04-10 14:37:35 UTC (rev 25) @@ -1,4 +1,5 @@ package mapproxy; +import java.util.AbstractList; import java.util.ArrayList; import mapproxy.wms.request.*; import mapproxy.wms.client.*; @@ -9,6 +10,8 @@ import mapproxy.config.Config; import mapproxy.server.HttpServer; +import javaxt.io.Directory; + //****************************************************************************** //** Main Application //****************************************************************************** @@ -27,14 +30,10 @@ * @param args the command line arguments */ public static void main(String[] args) throws Exception { - try{ new Main(args); - } - catch(Exception e){ - e.printStackTrace(); - } } + //************************************************************************** //** Constructor //************************************************************************** @@ -44,15 +43,7 @@ Config.base_config().set("cache.max_tile_limit", 500); Config.base_config().set("image.resampling_method", "bicubic"); - /* - */ - - - - - - String url = "http://localhost:6277/cgi-bin/mapserv.exe?map=/data/world.map&" + "layers=grid,polboundaries&" + @@ -78,6 +69,8 @@ } + + private void testTMS(){ Modified: core/Capabilities.java =================================================================== --- core/Capabilities.java 2011-04-05 11:36:23 UTC (rev 24) +++ core/Capabilities.java 2011-04-10 14:37:35 UTC (rev 25) @@ -36,6 +36,9 @@ if (format.equalsIgnoreCase("WMS")){ return WMS(); } + else if (format.equalsIgnoreCase("TMS")){ + return TMS(); + } else if (format.equalsIgnoreCase("ArcGIS.JSON")){ return ArcGIS_JSON(); } @@ -170,6 +173,35 @@ //************************************************************************** + //** TMS Capabilities + //************************************************************************** + /** Returns an XML document suitable for a TileMapService request. */ + + private String TMS(){ + + String url = service.getURL(); + + StringBuffer xml = new StringBuffer(); + xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); + xml.append("<TileMapService version=\"1.0.0\">"); + xml.append("<Title>" + service.getTitle() + "</Title>"); + xml.append("<Abstract>" + service.getDescription() + "</Abstract>"); + xml.append("<TileMaps>"); + for (Layer layer : service.getLayers()){ + + xml.append( + "<TileMap title=\"" + layer.getName() + "\" " + + "srs=\"" + layer.getSRS()[0] + "\" " + + "profile=\"{{layer.grid.profile}}\" " + + "href=\"" + url + layer.getName() + "\"/>"); + } + xml.append("</TileMaps>"); + xml.append("</TileMapService>"); + return xml.toString(); + } + + + //************************************************************************** //** ArcGIS REST Capabilities //************************************************************************** /** Returns a JSON document suitable for a ArcGIS REST service. */ Deleted: core/Generator.java =================================================================== --- core/Generator.java 2011-04-05 11:36:23 UTC (rev 24) +++ core/Generator.java 2011-04-10 14:37:35 UTC (rev 25) @@ -1,207 +0,0 @@ -package mapproxy.core; -// Copyright (c) 2007-2008 Adrian Kuhn <akuhn(a)iam.unibe.ch> -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// The software is provided "as is", without warranty of any kind, express or -// implied, including but not limited to the warranties of merchantability, -// fitness for a particular purpose and noninfringement. In no event shall the -// authors or copyright holders be liable for any claim, damages or other -// liability, whether in an action of contract, tort or otherwise, arising from, -// out of or in connection with the software or the use or other dealings in -// the software. - - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * An iterator that yields its values one at a time. Subclasses must define a - * method called {@link #run()} and may call {@link yield(T)} to return values - * one at a time. - * <p> - * The generator ends when it reaches a return statement or the end of the - * method. On the other hand, an generator may run forever and thus yield an - * infinite sequence (see Example 1 for an example). - * <p> - * Please beware that calling {@link #hasNext()} on the generator (and thus - * any use in a for-each loop) provokes a lookahead of one value. Therefore - * you cannot repeatedly yield the same object, but rather, you must clone the - * value on each yield statement (see Example 3 for an example). - * <p> - * <b>Example 1:</b> Yields an infinite sequence of fibonacci numbers. - * <pre>Generator<Integer> fibonacci = new Generator<Integer>() { - * @Override - * public void run() { - * int a = 0, b = 1; - * while (true) { - * a = b + (b = a); - * yield(a); - * } - * } - *}; - * - *for (int x : fibonacci) { - * if (x > 20000) break; - * System.out.println(x); - *}</pre> - * <p> - * <b>Example 2:</b> Yields all characters of the string "Hello, Worlds!". - * <pre>Generator<char>> hello = new Generator<char>() { - * @Override - * public void run() { - * String str = "Hello, Worlds!"; - * for (int n = 0; n < str.length; n++) { - * yield(str.atChar(n)); - * } - * } - *}; - * - *for (char each : hello) { - * System.out.println(each); - *}</pre> - * <p> - * <b>Example 3:</b> Yields all perutations of an array. - * <pre>public static <T> Generator<T[]> permute(final T[] a) { - * return new Generator<T[]>() { - * @Override - * public void run() { - * permute(a.length - 1); - * } - * private void permute(int n) { - * if (n == 0) yield(a.clone()); - * else for (int k = n; k >= 0; k--) { - * swap(n,k); - * permute(n - 1); - * swap(n,k); - * } - * } - * private void swap(int n, int m) { - * T temp = a[n]; - * a[n] = a[m]; - * a[m] = temp; - * } - * }; - *}</pre> - * - * <p> - * - * <b>NB:</b> this class makes use of Threads, you might want to double-check - * its source code before using it in a multi-threaded application. - * @author Adrian Kuhn <akuhn(at)iam.unibe.ch> - * @see http://smallwiki.unibe.ch/adriankuhn/yield4java/ - * - */ -public abstract class Generator<T> implements Iterable<T> { - - public abstract void run(); - - public Iterator<T> iterator() { - return new Iter(); - } - - private static final Object DONE = new Object(); - private static final Object EMPTY = new Object(); - private Object drop = EMPTY; - private Thread th = null; - - private synchronized Object take() { - while (drop == EMPTY) { - try { - wait(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - Object temp = drop; - if (drop != DONE) - drop = EMPTY; - notifyAll(); - return temp; - } - - private synchronized void put(Object value) { - if (drop == DONE) - throw new IllegalStateException(); - if (drop != EMPTY) - throw new IllegalStateException(); - drop = value; - notifyAll(); - while (drop != EMPTY) { - try { - wait(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - } - - protected void yield(T value) { - put(value); - } - - public synchronized void done() { - if (drop == DONE) - throw new IllegalStateException(); - if (drop != EMPTY) - throw new IllegalStateException(); - drop = DONE; - notifyAll(); - } - - private class Iter implements Iterator<T>, Runnable { - - private Object next = EMPTY; - - public Iter() { - if (th != null) - throw new IllegalStateException("Can not run coroutine twice"); - th = new Thread(this); - th.setDaemon(true); - th.start(); - } - - public void run() { - Generator.this.run(); - done(); - } - - public boolean hasNext() { - if (next == EMPTY) - next = take(); - return next != DONE; - } - - @SuppressWarnings("unchecked") - public T next() { - if (next == EMPTY) - next = take(); - if (next == DONE) - throw new NoSuchElementException(); - Object temp = next; - next = EMPTY; - return (T) temp; - } - - public void remove() { - throw new UnsupportedOperationException(); - - } - - @SuppressWarnings("deprecation") - @Override - protected void finalize() throws Throwable { - th.stop(); // let's commit suicide - } - - } - -} \ No newline at end of file Added: core/Generator.java =================================================================== --- core/Generator.java (rev 0) +++ core/Generator.java 2011-04-10 14:37:35 UTC (rev 25) @@ -0,0 +1,207 @@ +package mapproxy.core; +// Copyright (c) 2007-2008 Adrian Kuhn <akuhn(a)iam.unibe.ch> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// The software is provided "as is", without warranty of any kind, express or +// implied, including but not limited to the warranties of merchantability, +// fitness for a particular purpose and noninfringement. In no event shall the +// authors or copyright holders be liable for any claim, damages or other +// liability, whether in an action of contract, tort or otherwise, arising from, +// out of or in connection with the software or the use or other dealings in +// the software. + + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * An iterator that yields its values one at a time. Subclasses must define a + * method called {@link #run()} and may call {@link yield(T)} to return values + * one at a time. + * <p> + * The generator ends when it reaches a return statement or the end of the + * method. On the other hand, an generator may run forever and thus yield an + * infinite sequence (see Example 1 for an example). + * <p> + * Please beware that calling {@link #hasNext()} on the generator (and thus + * any use in a for-each loop) provokes a lookahead of one value. Therefore + * you cannot repeatedly yield the same object, but rather, you must clone the + * value on each yield statement (see Example 3 for an example). + * <p> + * <b>Example 1:</b> Yields an infinite sequence of fibonacci numbers. + * <pre>Generator<Integer> fibonacci = new Generator<Integer>() { + * @Override + * public void run() { + * int a = 0, b = 1; + * while (true) { + * a = b + (b = a); + * yield(a); + * } + * } + *}; + * + *for (int x : fibonacci) { + * if (x > 20000) break; + * System.out.println(x); + *}</pre> + * <p> + * <b>Example 2:</b> Yields all characters of the string "Hello, Worlds!". + * <pre>Generator<char>> hello = new Generator<char>() { + * @Override + * public void run() { + * String str = "Hello, Worlds!"; + * for (int n = 0; n < str.length; n++) { + * yield(str.atChar(n)); + * } + * } + *}; + * + *for (char each : hello) { + * System.out.println(each); + *}</pre> + * <p> + * <b>Example 3:</b> Yields all perutations of an array. + * <pre>public static <T> Generator<T[]> permute(final T[] a) { + * return new Generator<T[]>() { + * @Override + * public void run() { + * permute(a.length - 1); + * } + * private void permute(int n) { + * if (n == 0) yield(a.clone()); + * else for (int k = n; k >= 0; k--) { + * swap(n,k); + * permute(n - 1); + * swap(n,k); + * } + * } + * private void swap(int n, int m) { + * T temp = a[n]; + * a[n] = a[m]; + * a[m] = temp; + * } + * }; + *}</pre> + * + * <p> + * + * <b>NB:</b> this class makes use of Threads, you might want to double-check + * its source code before using it in a multi-threaded application. + * @author Adrian Kuhn <akuhn(at)iam.unibe.ch> + * @see http://smallwiki.unibe.ch/adriankuhn/yield4java/ + * + */ +public abstract class Generator<T> implements Iterable<T> { + + public abstract void run(); + + public Iterator<T> iterator() { + return new Iter(); + } + + private static final Object DONE = new Object(); + private static final Object EMPTY = new Object(); + private Object drop = EMPTY; + private Thread th = null; + + private synchronized Object take() { + while (drop == EMPTY) { + try { + wait(); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + } + Object temp = drop; + if (drop != DONE) + drop = EMPTY; + notifyAll(); + return temp; + } + + private synchronized void put(Object value) { + if (drop == DONE) + throw new IllegalStateException(); + if (drop != EMPTY) + throw new IllegalStateException(); + drop = value; + notifyAll(); + while (drop != EMPTY) { + try { + wait(); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + } + } + + protected void yield(T value) { + put(value); + } + + public synchronized void done() { + if (drop == DONE) + throw new IllegalStateException(); + if (drop != EMPTY) + throw new IllegalStateException(); + drop = DONE; + notifyAll(); + } + + private class Iter implements Iterator<T>, Runnable { + + private Object next = EMPTY; + + public Iter() { + if (th != null) + throw new IllegalStateException("Can not run coroutine twice"); + th = new Thread(this); + th.setDaemon(true); + th.start(); + } + + public void run() { + Generator.this.run(); + done(); + } + + public boolean hasNext() { + if (next == EMPTY) + next = take(); + return next != DONE; + } + + @SuppressWarnings("unchecked") + public T next() { + if (next == EMPTY) + next = take(); + if (next == DONE) + throw new NoSuchElementException(); + Object temp = next; + next = EMPTY; + return (T) temp; + } + + public void remove() { + throw new UnsupportedOperationException(); + + } + + @SuppressWarnings("deprecation") + @Override + protected void finalize() throws Throwable { + th.stop(); // let's commit suicide + } + + } + +} \ No newline at end of file Modified: core/Service.java =================================================================== --- core/Service.java 2011-04-05 11:36:23 UTC (rev 24) +++ core/Service.java 2011-04-10 14:37:35 UTC (rev 25) @@ -220,6 +220,14 @@ } + public ServiceResponse getResponse(String requestURL, String requestBody) throws Exception { + return new ServiceResponse(requestURL, requestBody, this); + } + + public ServiceResponse getResponse(String requestURL) throws Exception { + return this.getResponse(requestURL, null); + } + /* public Map getMap(Layer[] layers, BBox bbox, String srs, int width, int height, String format){ return new Map(layers, bbox, srs, width, height, format); @@ -238,8 +246,8 @@ } +// <editor-fold defaultstate="collapsed" desc="Parse WMS and ArcGIS Capabilities Documents. Click on the + sign on the left to edit the code."> - //************************************************************************** //** parseWMSCapabilities //************************************************************************** @@ -616,4 +624,8 @@ return javaxt.xml.DOM.getNodeValue(node); } + // </editor-fold> + + + } \ No newline at end of file Modified: core/ServiceException.java =================================================================== --- core/ServiceException.java 2011-04-05 11:36:23 UTC (rev 24) +++ core/ServiceException.java 2011-04-10 14:37:35 UTC (rev 25) @@ -4,7 +4,7 @@ //** Service Exception //****************************************************************************** /** - * Enter class description here + * Used to represent a server exception. Not yet implemented or used. * * Note that this class was not part of the original mapproxy baseline. * Added: core/ServiceResponse.java =================================================================== --- core/ServiceResponse.java (rev 0) +++ core/ServiceResponse.java 2011-04-10 14:37:35 UTC (rev 25) @@ -0,0 +1,839 @@ +package mapproxy.core; +import mapproxy.wms.request.*; +import mapproxy.wms.client.*; +import mapproxy.core.grid.*; +import mapproxy.core.cache.*; +import mapproxy.wms.cache.WMSTileSource; +import mapproxy.arcgis.cache.*; +import mapproxy.arcgis.client.*; +import org.w3c.dom.*; +import javaxt.xml.DOM; + +//****************************************************************************** +//** ServiceResponse Class +//****************************************************************************** +/** + * Used to generate a response to a service request. The response might + * include an image or a capabilities document. + * + * Note that this class was not part of the original mapproxy baseline. + * + ******************************************************************************/ + +public class ServiceResponse { + + private javaxt.utils.Date date; + private javaxt.utils.URL url; + private Service service; + private String body; + private String contentType; + private String key; + private byte[] rsp; + + //************************************************************************** + //** Constructor + //************************************************************************** + /** Creates a new instance of ServiceResponse. */ + + protected ServiceResponse(String requestURL, String requestBody, Service service) throws Exception { + + //Clean up any duplicate values in the query string (wierd bug in ArcMap 9.2) + javaxt.utils.URL url = new javaxt.utils.URL(requestURL); + java.util.HashMap<String, java.util.List<String>> params = url.getParameters(); + java.util.Iterator<String> it = params.keySet().iterator(); + while (it.hasNext()){ + String key = it.next(); + java.util.List<String> val = params.get(key); + if (val==null){ + url.setParameter(key, null); + } + else{ + java.util.HashSet<String> uniqueValues = new java.util.HashSet<String>(); + for (int i=0; i<val.size(); i++){ + uniqueValues.add(val.get(i)); + } + String vals = ""; + java.util.Iterator<String> it2 = uniqueValues.iterator(); + while (it2.hasNext()){ + vals += it2.next(); + if (it2.hasNext()) vals +=","; + } + url.setParameter(key, vals); + } + } + + + this.url = new javaxt.utils.URL(url.toString()); + + if (requestBody!=null){ + requestBody = requestBody.trim(); + if (requestBody.length()==0) requestBody = null; + } + this.body = requestBody; + + this.service = service; + + javaxt.utils.Date date = new javaxt.utils.Date(); + date.setTimeZone("GMT"); + this.date = date; + + init(false); + } + + + //************************************************************************** + //** init + //************************************************************************** + /** Used to initialize three class variables: key, contentType, and rsp. + * + * @param getBytes Used to initialize the rsp variable. If set to true, + * rsp will be populated with a byte array. If set to false, the rsp + * variable will not be set. This fine grain control is useful for http + * applications where a server may only need the key to implement http + * cache control. + */ + private void init(boolean getBytes){ + + if (getBytes && this.rsp!=null) return; + + boolean responseSent = true; + String path = url.getPath().toLowerCase(); + if (!path.endsWith("/")) path+="/"; + if (path.contains("/ImageServer/".toLowerCase()) || + path.contains("/MapServer/".toLowerCase()) || + path.contains("/ArcGIS/".toLowerCase())){ + + if (url.getQueryString().equalsIgnoreCase("WSDL") || body!=null){ + try{ + getArcGISSoapResponse(getBytes); + } + catch(java.io.UnsupportedEncodingException e){ + //This error should never be thrown. Only occurs if the + //string can't be encoded into UTF-8. + } + } + else{ + + String f = url.getParameter("f"); + if (f.equalsIgnoreCase("json")){ + getArcMapCapabilities(getBytes); + } + else if (f.equalsIgnoreCase("image")){ + getArcMapImage(getBytes); + } + else{ + responseSent = false; + } + + } + } + else if (path.contains("/wms/")){ + String action = url.getParameter("request"); + if (action.equalsIgnoreCase("GetMap")){ + getMap(getBytes); + } + else if (action.equalsIgnoreCase("GetCapabilities")){ + getWMSCapabilities(getBytes); + } + else{ + responseSent = false; + } + } + else if (path.contains("/tms/")){ + if (path.equals("/tms/")){ + getTMSCapabilities(getBytes); + } + else getTile(getBytes); + } + else{ + responseSent = false; + } + + if (!responseSent) getLandingPage(getBytes); + + } + + + //************************************************************************** + //** getID + //************************************************************************** + /** Returns an ID for the response. This ID can be stored as key in a cache + * map. + */ + public String getID(){ + return key; + } + + + //************************************************************************** + //** getContentType + //************************************************************************** + /** Returns the HTTP Content-Type for the response. */ + + public String getContentType(){ + return contentType; + } + + + //************************************************************************** + //** getDate + //************************************************************************** + /** Returns the date for the response. */ + + public javaxt.utils.Date getDate(){ + return date; + } + + + //************************************************************************** + //** getByteArray + //************************************************************************** + /** Returns a byte array containing the response. The byte array can be used + * in the body of an http response. + */ + public byte[] getByteArray(){ + this.init(true); //<-- Inititalize the byte array... + return rsp; + } + + + + //************************************************************************** + //** getLandingPage + //************************************************************************** + /** Used to construct an HTML landing page for the service. + */ + private void getLandingPage(boolean getBytes) { + + + key = "HOME"; + contentType = "text/html"; + + if (!getBytes) return; + + + String url = this.url.toString(); + if (url.contains("?")) url = url.substring(0, url.indexOf("?")); + + String html = mapproxy.config.Config.base_config().get("html").toString(); + html = html.replace("@SERVICENAME", service.getName()); + html = html.replace("@SERVICEDESCRIPTION", service.getDescription()); + + StringBuffer layers = new StringBuffer(); + for (Layer layer : service.getLayers()){ + layers.append("<li>" + layer.getName() + "</li>"); + } + html = html.replace("@LAYERS", layers.toString()); + + + StringBuffer services = new StringBuffer(); + services.append("<li><a href=\"/WMS/?service=WMS&request=GetCapabilities&version=1.1.1\">WMS</a></li>"); + services.append("<li><a href=\"/TMS/?\">TMS</a></li>"); + services.append("<li><a href=\"/ArcGIS/?wsdl\">ArcGIS MapServer (SOAP)</a></li>"); + services.append("<li><a href=\"/ArcGIS/?f=json\">ArcGIS MapServer (REST)</a></li>"); + html = html.replace("@SERVICES", services.toString()); + + + try{ + rsp = html.toString().getBytes("UTF-8"); + } + catch (java.io.UnsupportedEncodingException e){ + } + + } + + + + + + //************************************************************************** + //** getTile + //************************************************************************** + /** Used to construct a response to a TMS Map request + */ + private void getTile(boolean getBytes) { + + //Set local variables + String url = this.url.toString(); + + + //Check whether this request is in the http cache + mapproxy.tms.TileRequest req = new mapproxy.tms.TileRequest(url); + key = req.id(); + if (!getBytes) return; + + + //Set format and + String format = req.format; + contentType = "image/"+format; + + + //Find requested layer in the mapproxy service definition + Layer layer = service.getLayer(req.layer); + FileCache fileCache = (FileCache) layer.getParam("cache"); + + + if (fileCache==null){ + TileGrid grid = new TileGrid(4326, new int[]{256,256}); //<--Maybe there's a way to encode these parameters in the URL? Need to check the TMS spec... + double[] bbox = grid.tile_bbox(req.tile[0], req.tile[1], req.tile[2]); + rsp = getImage(layer, grid.tile_size[0], grid.tile_size[1], format, bbox, grid.srs.toString()).getByteArray(format); + } + else{ + + //Instantiate the TMS cache + TileGrid grid = (TileGrid) layer.getParam("grid"); + mapproxy.tms.cache.TMSTileSource tms = new mapproxy.tms.cache.TMSTileSource(grid, url); + CacheManager cacheManager = new CacheManager(fileCache, tms); + Cache cache = new Cache(cacheManager, grid, true); + req.tile = new mapproxy.tms.TileServiceGrid(grid).internal_tile_coord(req.tile, true); + + + try{ + + //Find the requested tile in the cache. Note that this will throw an error if the tile doesn't exist + javaxt.io.File file = new javaxt.io.File(cache.tile(req.tile).location); + if (file.exists() && file.getSize()>0){ + if (file.getExtension().equalsIgnoreCase(format)){ + rsp = file.getBytes().toByteArray(); + } + else{ + rsp = file.getImage().getByteArray(format); + } + } + } + catch(Exception e){ + + //Create image and update cache + double[] bbox = grid.tile_bbox(req.tile[0], req.tile[1], req.tile[2]); + rsp = getImage(layer, grid.tile_size[0], grid.tile_size[1], fileCache.file_ext, bbox, grid.srs.toString()).getByteArray(format); + } + + } + } + + + //************************************************************************** + //** getMap + //************************************************************************** + /** Used to construct a response to a WMS GetMap request + */ + private void getMap(boolean getBytes) { + + //Parse querystring parameters + String layers = url.getParameter("layers"); + String bbox = url.getParameter("bbox"); + String srs = url.getParameter("srs"); + int width = javaxt.utils.string.toInt(url.getParameter("width")); + int height = javaxt.utils.string.toInt(url.getParameter("height")); + String format = url.getParameter("format"); + if (!format.toLowerCase().startsWith("image/")) format = "image/" + format; + + //Set content type + if (format.equalsIgnoreCase("image/PNG24")) contentType = "image/png"; + else contentType = format; + + //Create unique key + key = bbox + "|" + layers + "|" + contentType + "|" + width + "|" + height + "|" + srs; + + //Exit method as needed + if (!getBytes) return; + + + //Create image for each layer + javaxt.io.Image image = new javaxt.io.Image(width, height); + for (String layerName : layers.split(",")){ + + mapproxy.core.Layer layer = service.getLayer(layerName); + + if (layer==null){ + int layerID = -1; + try{ + layerID = Integer.parseInt(layerName); + if (layerID>=0 && layerID<service.getLayers().length){ + layer = service.getLayers()[layerID]; + } + } + catch(Exception e){ + } + } + + if (layer!=null){ + image.addImage(getImage(layer, width, height, format, bbox, srs), 0, 0, false); + } + } + + + //Convert the image into a byte array + if (format.toLowerCase().endsWith("png24")) format = "image/png"; + rsp = image.getByteArray(format); + + + //rsp = new javaxt.io.File("/temp/ArcGIS/ExportImage.png").getBytes().toByteArray(); + //rsp = new javaxt.io.Image("/temp/ArcGIS/ExportImage.png").getByteArray("png"); + + } + + + //************************************************************************** + //** getArcMapImage + //************************************************************************** + /** Used to construct a response to an ArcMap Image Export request. Basically + * this method transforms the request into a WMS getMap request. + */ + private void getArcMapImage(boolean getBytes) { + + javaxt.utils.URL url = new javaxt.utils.URL(this.url.toString()); + + + //Remove extranous parameters + url.removeParameter("f"); + url.removeParameter("dpi"); + url.removeParameter("imagesr"); + + + //Update the layers parameter + String layers = url.removeParameter("layers"); + if (layers!=null){ + layers = layers.trim(); + if (layers.length()==0){ + layers=null; + } + } + if (layers==null){ + layers=""; + for (int i=0; i<service.getLayers().length; i++){ + layers+= service.getLayers()[i]; + if (i<this.service.getLayers().length-1) layers+=","; + } + } + url.setParameter("layers", layers); + + + + //Update the SRS parameter + String srs = url.removeParameter("bboxsr"); + if (!srs.contains(":")) srs = "EPSG:" + srs; + url.setParameter("srs", srs); + + + //Update the BBOX parameter as needed. For example, ArcMap returns the following: + //bbox={"xmin":-140.90176870508722,"ymin":5.39213971511016,"xmax":-50.75590345473839,"ymax":70.5993603884707,"spatialReference":{"wkid":4326}} + String bbox = url.removeParameter("bbox").trim(); + if (bbox.contains(":")){ + if (bbox.startsWith("{") && bbox.endsWith("}")){ + bbox = bbox.substring(1, bbox.length()-1).trim(); + } + java.util.HashMap<String, String> coords = new java.util.HashMap<String, String>(); + for (String param : bbox.split(",")){ + if (param.startsWith("\"xmin\"")){ + coords.put("minX", param.substring(param.indexOf(":")+1)); + } + if (param.startsWith("\"ymin\"")){ + coords.put("minY", param.substring(param.indexOf(":")+1)); + } + if (param.startsWith("\"xmax\"")){ + coords.put("maxX", param.substring(param.indexOf(":")+1)); + } + if (param.startsWith("\"ymax\"")){ + coords.put("maxY", param.substring(param.indexOf(":")+1)); + } + } + bbox = coords.get("minX") + "," + coords.get("minY") + "," + coords.get("maxX") + "," + coords.get("maxY"); + } + url.setParameter("bbox", bbox); + + + //Update the format + String format = url.getParameter("format"); + if (format.toLowerCase().startsWith("png")) format = "png"; + if (!format.toLowerCase().startsWith("image/")) format = "image/" + format; + url.setParameter("format", format); + + + url.setParameter("request", "GetMap"); + url.setParameter("service", "WMS"); + url.setParameter("version", "1.1.1"); + + + //Set output width/height + String[] size = url.removeParameter("size").split(","); + url.setParameter("width", size[0]); + url.setParameter("height", size[1]); + + + javaxt.utils.URL orgURL = this.url; + this.url = url; + + this.getMap(getBytes); + + this.url = orgURL; + + } + + + + //************************************************************************** + //** getImage + //************************************************************************** + /** Used to retrieve an image from a server for a given layer + */ + private javaxt.io.Image getImage(mapproxy.core.Layer layer, int width, int height, String format, String bbox, String srs){ + + FileCache fileCache = (FileCache) layer.getParam("cache"); + TileGrid grid = (TileGrid) layer.getParam("grid"); + + String host = (String) layer.getParam("host"); + if (!host.contains("?")) host += "?"; + //host += url.getQueryString(); + + WMSMapRequestParams param = new WMSMapRequestParams(); + param.set("layers", (String) layer.getParam("layers")); + param.set("bbox", bbox); + + WMS111MapRequest req = new WMS111MapRequest(param, host); + req.params.size(new int[]{width, height}); + req.params.set("srs", srs); + + + + //if (format.equalsIgnoreCase("image/PNG24")) format = "jpeg"; //<-- This is crazy! If I return a 24 bit PNG, ArcMap doesn't display anything. If I return a JPEG, works like a champ + if (!format.toLowerCase().startsWith("image/")) format = "image/" + format; + if (format.equalsIgnoreCase("image/PNG24") && fileCache!=null) format = "image/png"; + //format = "image/png"; + req.params.set("format", format); + + String protocol = (String) layer.getParam("protocol"); + if (protocol.equalsIgnoreCase("WMS")){ + + if (fileCache==null){ + return new WMSClient(req).get_map(req); + } + else{ + WMSTileSource wms = new WMSTileSource(grid, new WMSClient(req)); + CacheManager cacheManager = new CacheManager(fileCache, wms); + Cache cache = new Cache(cacheManager, grid, true); + return cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()); + } + } + else if (protocol.equalsIgnoreCase("MapServer")){ + + if (fileCache==null){ + return new MapClient(req).get_map(req); + } + else{ + MapTileSource arcMapServer = new MapTileSource(grid, new MapClient(req)); + CacheManager cacheManager = new CacheManager(fileCache, arcMapServer); + Cache cache = new Cache(cacheManager, grid, true); + return cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()); + } + + + } + + return null; + + } + + + private javaxt.io.Image getImage(mapproxy.core.Layer layer, int width, int height, String format, double[] bbox, String srs){ + return this.getImage(layer, width, height, format, bbox[0] + "," + bbox[1] + "," + bbox[2] + "," + bbox[3], srs); + } + + + + + //************************************************************************** + //** getWMSCapabilities + //************************************************************************** + /** Used to construct a response to a WMS GetCapabilities request + */ + private void getWMSCapabilities(boolean getBytes) { + + key = "WMS Capabilities"; + contentType = "text/xml"; + + if (!getBytes) return; + + String url = this.url.toString(); + if (url.contains("?")) url = url.substring(0, url.indexOf("?")); + if (!url.endsWith("/")) url += "/"; + if (!url.toLowerCase().endsWith("/wms/")) url += "wms/"; + + //Get Capabilities + String orgURL = service.getURL(); + service.setURL(url); + rsp = service.getCapabilities().toString("WMS").getBytes(); + service.setURL(orgURL); + } + + + //************************************************************************** + //** getTMSCapabilities + //************************************************************************** + /** Used to construct a response to a TMS GetCapabilities request + */ + private void getTMSCapabilities(boolean getBytes) { + + key = "TMS Capabilities"; + contentType = "text/xml"; + + if (!getBytes) return; + + String url = this.url.toString(); + if (url.contains("?")) url = url.substring(0, url.indexOf("?")); + if (!url.endsWith("/")) url += "/"; + if (!url.toLowerCase().endsWith("/tms/")) url += "tms/"; + + //Get Capabilities + String orgURL = service.getURL(); + service.setURL(url); + rsp = service.getCapabilities().toString("TMS").getBytes(); + service.setURL(orgURL); + } + + + //************************************************************************** + //** getArcMapCapabilities + //************************************************************************** + /** Used to construct a response to an ArcMap REST Capabilities request + */ + private void getArcMapCapabilities(boolean getBytes) { + + key = "ArcMap Capabilities"; + contentType = "text/plain"; + + + String callback = url.getParameter("callback"); + if (callback!=null){ + callback = callback.trim(); + if (callback.length()==0) callback = null; + } + + + if (callback!=null){ + key += " + Callback"; + } + + if (!getBytes) return; + + + StringBuffer json = new StringBuffer(); + if (callback!=null) json.append(callback+"("); + json.append(this.service.getCapabilities().toString("ArcGIS.JSON")); + if (callback!=null) json.append(");"); + + + //Convert the xml into a byte array + rsp = json.toString().getBytes(); + + + } + + + + //************************************************************************** + //** getArcGISSoapResponse + //************************************************************************** + /** Used to construct a response to an ArcGIS SOAP client + */ + private void getArcGISSoapResponse(boolean getBytes) throws java.io.UnsupportedEncodingException { + + mapproxy.arcgis.server.MapServer arcgis = new mapproxy.arcgis.server.MapServer(service); + + contentType = "text/xml"; + + if (body==null || body.length()==0) body = " "; + if (body.substring(0,1).equals("<")){ + String resultsNode = "Body"; //soap:Body + Document xml = DOM.createDocument(body); + NodeList response = xml.getElementsByTagName(resultsNode); + if (response!=null){ + + //Special Case: Probably Missing Namespace in Soap.resultsNode + if (response.getLength()==0) { + resultsNode = getResultsNode(body, resultsNode); + response = xml.getElementsByTagName(resultsNode); + } + + String msg = DOM.getNodeValue(response.item(0)); + if (msg.contains("GetMessageVersion")){ + key = "ArcGIS GetMessageVersion"; + rsp = arcgis.getMessageVersion().getBytes("UTF-8"); + } + else if (msg.contains("GetMessageFormats")){ + key = "ArcGIS GetMessageFormats"; + rsp = arcgis.getMessageFormats().getBytes("UTF-8"); + } + else if (msg.contains("GetFolders")){ + key = "ArcGIS GetFolders"; + rsp = arcgis.getFolders().getBytes("UTF-8"); + } + else if (msg.contains("GetServiceDescriptions")){ + key = "ArcGIS GetServiceDescriptions"; + rsp = arcgis.getServiceDescriptions().getBytes("UTF-8"); + } + else if (msg.contains("GetDefaultMapName")){ + key = "ArcGIS GetDefaultMapName"; + rsp = arcgis.getDefaultMapName().getBytes("UTF-8"); + } + else if (msg.contains("GetServerInfo")){ + key = "ArcGIS GetServerInfo"; + rsp = arcgis.getServerInfo().getBytes("UTF-8"); + } + else if (msg.contains("GetSupportedImageReturnTypes")){ + key = "ArcGIS GetSupportedImageReturnTypes"; + rsp = arcgis.getSupportedImageReturnTypes().getBytes("UTF-8"); + } + else if (msg.contains("HasSingleFusedMapCache")){ + key = "ArcGIS HasSingleFusedMapCache"; + rsp = arcgis.hasSingleFusedMapCache().getBytes("UTF-8"); + } + else if (msg.contains("GetTokenServiceURL")){ + key = "ArcGIS GetTokenServiceURL"; + rsp = arcgis.getTokenServiceURL().getBytes("UTF-8"); + } + else if (msg.contains("IsFixedScaleMap")){ + key = "ArcGIS IsFixedScaleMap"; + rsp = arcgis.isFixedScaleMap().getBytes("UTF-8"); + } + else if (msg.contains("GetTileCacheInfo")){ + key = "ArcGIS GetTileCacheInfo"; + rsp = arcgis.getTileCacheInfo().getBytes("UTF-8"); + } + else if (msg.contains("GetTileImageInfo")){ + key = "ArcGIS GetTileImageInfo"; + rsp = arcgis.getTileImageInfo().getBytes("UTF-8"); + } + else if (msg.contains("GetLegendInfo")){ + key = "ArcGIS GetLegendInfo"; + //rsp = new javaxt.io.File("/temp/GetLegendInfo.xml").getText("UTF-8").getBytes("UTF-8"); + //rsp = arcgis.getLegendInfo().getBytes("UTF-8"); + } + else if (msg.contains("ExportMapImage")){ + System.out.println("ExportMapImage"); +new javaxt.io.File("/temp/ExportImage.xml").write(body, "UTF-8"); + + String returnType = getNodeValue("ImageReturnType", xml); + String width = getNodeValue("ImageWidth", xml); + String height = getNodeValue("ImageHeight", xml); + String format = getNodeValue("ImageFormat", xml); + + + String layers = ""; + NodeList nodeList = xml.getElementsByTagName("LayerDescription"); + for (int i=0; i<nodeList.getLength(); i++ ) { + if (nodeList.item(i).getNodeType()==1){ + String layerID = ""; + String isVisible = ""; + NodeList layerAttributes = nodeList.item(i).getChildNodes(); + for (int j=0; j<layerAttributes.getLength(); j++ ) { + Node layerAttribute = layerAttributes.item(j); + if (layerAttribute.getNodeType()==1){ + if (layerAttribute.getNodeName().equalsIgnoreCase("LayerID")){ + layerID = javaxt.xml.DOM.getNodeValue(layerAttribute).trim(); + } + else if (layerAttribute.getNodeName().equalsIgnoreCase("Visible")){ + isVisible = javaxt.xml.DOM.getNodeValue(layerAttribute).trim(); + } + } + } + if (layerID.length()>0){ + if (isVisible.equalsIgnoreCase("true")){ + layers+=layerID + ","; + } + } + } + } + /* + NodeList nodeList = xml.getElementsByTagName("LayerID"); + for (int i=0; i<nodeList.getLength(); i++ ) { + if (nodeList.item(i).getNodeType()==1){ + String layer = javaxt.xml.DOM.getNodeValue(nodeList.item(i)).trim(); + if (layer.length()>0){ + layers+=layer + ","; + } + } + } + */ + if (layers.endsWith(",")){ + layers = layers.substring(0, layers.length()-1); + } + + String minX = getNodeValue("XMin", xml); + String minY = getNodeValue("YMin", xml); + String maxX = getNodeValue("XMax", xml); + String maxY = getNodeValue("YMax", xml); + String bbox = minX + "," + minY + "," + maxX + "," + maxY; + String wkt = getNodeValue("WKT", xml); + + + //Update the request URL to point to the WMS endpoint + String wms = this.url.toString(); + wms = wms.substring(0, wms.indexOf(this.url.getPath())) + "/wms"; + + + //Generate ExportImage SOAP Response + rsp = arcgis.getExportMapImageResponse(new javaxt.utils.URL(wms), layers, bbox, wkt, width, height, format, returnType).getBytes("UTF-8"); + + + /* + //Redirect request to ArcGIS Server (Debug Use Only) + msg = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tns=\"http://www.esri.com/schemas/ArcGIS/9.0\">" + msg; + msg += "</soap:Envelope>"; + + javaxt.http.Request req = new javaxt.http.Request("http://services.arcgisonline.com/ArcGIS/services/USA_Topo_Maps/MapServer"); + req.setHeader("Accept", "*"); + req.setHeader("Content-Type", "text/xml"); + req.setHeader("User-Agent", "ArcGIS Client Using WinInet"); + req.setHeader("SOAPAction", "\"\""); + + req.write(msg); + + String txt = req.getResponse().getText("UTF-8"); + String img = getNodeValue("ImageURL", DOM.createDocument(txt)); + System.out.println(img); + txt = txt.replace(img, "<![CDATA[http://localhost:9080/wms?height=597&bbox=319898.427173501,-238695.385822158,1250996.29959783,693964.731354558&request=GetMap&width=596&layers=0&service=WMS&srs=EPSG:2781&format=image/jpeg&version=1.1.1&date="+ new java.util.Date().getTime() +"]]>"); + rsp = txt.getBytes("UTF-8"); + new javaxt.io.File("/temp/ExportImageResponse.xml").write(rsp); + */ + + + } + else{ + System.out.println( msg ); + } + + } + } + + + //Return a WSDL by default + if (rsp==null){ + key = "ArcGIS WSDL"; + rsp = arcgis.getWSDL().getBytes("UTF-8"); + } + + } + + + private String getResultsNode(String ServiceResponse, String resultsNode){ + resultsNode = ServiceResponse.substring(0, + ServiceResponse.toLowerCase().indexOf(resultsNode.toLowerCase()) + resultsNode.length()); + + resultsNode = resultsNode.substring(resultsNode.lastIndexOf("<")+1); + return resultsNode; + } + + + private String getNodeValue(String nodeName, Document xml){ + + NodeList nodeList = xml.getElementsByTagName(nodeName); + for (int i=0; i<nodeList.getLength(); i++ ) { + if (nodeList.item(i).getNodeType()==1){ + return javaxt.xml.DOM.getNodeValue(nodeList.item(i)); + } + } + return ""; + } + +} \ No newline at end of file Modified: core/image/ImageTransformer.java =================================================================== --- core/image/ImageTransformer.java 2011-04-05 11:36:23 UTC (rev 24) +++ core/image/ImageTransformer.java 2011-04-10 14:37:35 UTC (rev 25) @@ -195,8 +195,19 @@ GridCoverage2D gc2dProj = (GridCoverage2D)Operations.DEFAULT.resample(gc2d, this.dst_srs.crs); + //TODO: Crop Output? + /* + final AbstractProcessor processor = new DefaultProcessor(null); + final ParameterValueGroup param = processor.getOperation("CoverageCrop").getParameters(); - src_img = new javaxt.io.Image(convertRenderedImage(gc2dProj.getRenderedImage())); + final GeneralEnvelope crop = new GeneralEnvelope( ... ); //<--Define new extents + param.parameter("Source").setValue( gc2dProj ); + param.parameter("Envelope").setValue( crop ); + + gc2dProj = (GridCoverage2D) processor.doOperation(param); + */ + + src_img = new javaxt.io.Image(gc2dProj.getRenderedImage()); src_img.resize(dst_size[0], dst_size[1], false); } @@ -281,29 +292,9 @@ return pt; } - public BufferedImage convertRenderedImage(RenderedImage img) { - if (img instanceof BufferedImage) { - return (BufferedImage)img; - } - java.awt.image.ColorModel cm = img.getColorModel(); - int width = img.getWidth(); - int height = img.getHeight(); - java.awt.image.WritableRaster raster = - cm.createCompatibleWritableRaster(width, height); - boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); - java.util.Hashtable properties = new java.util.Hashtable(); - String[] keys = img.getPropertyNames(); - if (keys!=null) { - for (int i = 0; i < keys.length; i++) { - properties.put(keys[i], img.getProperty(keys[i])); - } - } - BufferedImage result = new BufferedImage(cm, raster, isAlphaPremultiplied, properties); - img.copyData(raster); - return result; - } + //************************************************************************** //** _no_transformation_needed //************************************************************************** Modified: server/RequestProcessor.java =================================================================== --- server/RequestProcessor.java 2011-04-05 11:36:23 UTC (rev 24) +++ server/RequestProcessor.java 2011-04-10 14:37:35 UTC (rev 25) @@ -1,30 +1,18 @@ package mapproxy.server; -import org.w3c.dom.*; -import javaxt.xml.DOM; +import mapproxy.core.*; import java.io.IOException; import java.nio.channels.SocketChannel; - -import mapproxy.wms.request.*; -import mapproxy.wms.client.*; -import mapproxy.core.grid.*; -import mapproxy.core.cache.*; -import mapproxy.core.*; -import mapproxy.wms.cache.WMSTileSource; -import mapproxy.arcgis.cache.*; -import mapproxy.arcgis.client.*; import java.util.concurrent.ConcurrentHashMap; - import java.util.zip.*; - //****************************************************************************** //** RequestProcessor //****************************************************************************** /** - * Used to process HTTP Requests and send responses back to the client. As new - * http requests come in (via the processRequest method), they are added to a - * que (pool). Requests in the que are processed by instances of this class - * via the run method. + * Used to process HTTP Requests and send responses back to the client. As + * new http requests come in (via the processRequest method), they are added + * to a queue (pool). Requests in the queue are processed by instances of + * this class via the run method. * ******************************************************************************/ @@ -33,9 +21,10 @@ /** Request pool */ private static java.util.List<SocketChannel> pool = new java.util.LinkedList<SocketChannel>(); + /** Hashmap used to store requests and http responses. Used to manage/send eTags and 304 responses. */ private static ConcurrentHashMap<String, String> httpCache = new ConcurrentHashMap<String, String>(); - private static String serverName = "MapProxy Server 0.8.1 RC3"; + private static String serverName = "MapProxy Server 0.8.1 RC4"; //************************************************************************** //** Constructor @@ -114,49 +103,15 @@ //Extract Header from Request RequestHeader request = new RequestHeader(connection); - javaxt.utils.URL url = new javaxt.utils.URL(request.getURL()); + //System.out.println(request.toString()); - //Clean up any duplicate values in the query string (wierd bug in ArcMap 9.2) - java.util.HashMap<String, java.util.List<String>> params = url.getParameters(); - java.util.Iterator<String> it = params.keySet().iterator(); - while (it.hasNext()){ - String key = it.next(); - java.util.List<String> val = params.get(key); - if (val==null){ - url.setParameter(key, null); - } - else{ - java.util.HashSet<String> uniqueValues = new java.util.HashSet<String>(); - for (int i=0; i<val.size(); i++){ - uniqueValues.add(val.get(i)); - } - String vals = ""; - java.util.Iterator<String> it2 = uniqueValues.iterator(); - while (it2.hasNext()){ - vals += it2.next(); - if (it2.hasNext()) vals +=","; - } - url.setParameter(key, vals); - } - } - request.setURL(new java.net.URL(url.toString())); - - //Print the requested URL - //System.out.println(request.getMethod() + ": " + url); - //System.out.println(); - System.out.println(request.toString()); - - + //Read in any remaining bytes from the connection (body of the http request) StringBuffer body = new StringBuffer(); java.nio.charset.Charset charset = java.nio.charset.Charset.forName("UTF-8"); java.nio.charset.CharsetDecoder decoder = charset.newDecoder(); - - int bufferSize = 21480; - - //Read in any remaining bytes from the connection (body of the http request) java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocateDirect(bufferSize); int numRead = 0; while (numRead >= 0) { @@ -182,77 +137,17 @@ //Send response to back to the client - boolean responseSent = true; - String path = url.getPath().toLowerCase(); - if (!path.endsWith("/")) path+="/"; - if (path.contains("/ImageServer/".toLowerCase()) || - path.contains("/MapServer/".toLowerCase()) || - path.contains("/ArcGIS/".toLowerCase())){ - if (url.getQueryString().equalsIgnoreCase("WSDL")){ - this.getWSDL(request, connection); - } - else if (body.length()>0){ - this.getSoapResponse(body.toString().trim(), request, connection); - } - else{ - - String f = url.getParameter("f"); - if (f.equalsIgnoreCase("json")){ - getArcMapCapabilities(request, connection); - } - else if (f.equalsIgnoreCase("image")){ - getArcMapImage(request, connection); - } - else{ - responseSent = false; - } - - } + try { + this.getResponse(request, connection, body.toString()); } - else if (path.contains("/wms/")){ - String action = url.getParameter("request"); - if (action.equalsIgnoreCase("GetMap")){ - getMap(request, connection); - } - else if (action.equalsIgnoreCase("GetCapabilities")){ - getCapabilities(request, connection); - } - else{ - responseSent = false; - } + catch (Exception e) { + e.printStackTrace(); } - else if (path.contains("/tms/")){ - getTile(request, connection); - - } - else{ - responseSent = false; - ... [truncated message content] |
From: <pbo...@us...> - 2011-04-05 11:36:30
|
Revision: 24 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=24&view=rev Author: pborissow Date: 2011-04-05 11:36:23 +0000 (Tue, 05 Apr 2011) Log Message: ----------- Implemented tile creation for TMS Modified Paths: -------------- Main.java config.xml server/RequestProcessor.java tms/TileRequest.java tms/TileServiceGrid.java tms/cache/TMSTileSource.java Modified: Main.java =================================================================== --- Main.java 2011-04-04 21:48:28 UTC (rev 23) +++ Main.java 2011-04-05 11:36:23 UTC (rev 24) @@ -27,7 +27,12 @@ * @param args the command line arguments */ public static void main(String[] args) throws Exception { + try{ new Main(args); + } + catch(Exception e){ + e.printStackTrace(); + } } //************************************************************************** Modified: config.xml =================================================================== --- config.xml 2011-04-04 21:48:28 UTC (rev 23) +++ config.xml 2011-04-05 11:36:23 UTC (rev 24) @@ -2,7 +2,7 @@ <mapproxy> <service> - <name>MapProxy Server 0.8.1 RC3</name> + <name>MapProxy Server 0.8.1 RC4</name> <description>Map proxy and tile cache for web map services</description> <port>9080</port> <numThreads>200</numThreads> Modified: server/RequestProcessor.java =================================================================== --- server/RequestProcessor.java 2011-04-04 21:48:28 UTC (rev 23) +++ server/RequestProcessor.java 2011-04-05 11:36:23 UTC (rev 24) @@ -86,9 +86,9 @@ } if (connection!=null) { - System.out.println(); - System.out.println("New Request From: " + connection.socket().getInetAddress()); - System.out.println("TimeStamp: " + new java.util.Date()); + //System.out.println(); + //System.out.println("New Request From: " + connection.socket().getInetAddress()); + //System.out.println("TimeStamp: " + new java.util.Date()); parseInputStream(connection); } @@ -144,8 +144,8 @@ //Print the requested URL - System.out.println(request.getMethod() + ": " + url); - System.out.println(); + //System.out.println(request.getMethod() + ": " + url); + //System.out.println(); System.out.println(request.toString()); @@ -264,119 +264,196 @@ } + //************************************************************************** + //** getLandingPage + //************************************************************************** + /** Used to construct an HTML landing page for the service. + */ + private void getLandingPage(RequestHeader request, SocketChannel connection) throws IOException { + javaxt.utils.Date date = new javaxt.utils.Date(); + date.setTimeZone("GMT"); + //Check whether this request is in the http cache + String key = "HOME"; + if (useCache(request, connection, key, date)) return; + + mapproxy.core.Service service = this.getMapProxy(); + + String url = request.getURL().toString(); + if (url.contains("?")) url = url.substring(0, url.indexOf("?")); + + String html = mapproxy.config.Config.base_config().get("html").toString(); + html = html.replace("@SERVICENAME", service.getName()); + html = html.replace("@SERVICEDESCRIPTION", service.getDescription()); + + StringBuffer layers = new StringBuffer(); + for (Layer layer : service.getLayers()){ + layers.append("<li>" + layer.getName() + "</li>"); + } + html = html.replace("@LAYERS", layers.toString()); + + + StringBuffer services = new StringBuffer(); + services.append("<li><a href=\"/WMS/?service=WMS&request=GetCapabilities&version=1.1.1\">WMS</a></li>"); + services.append("<li><a href=\"/TMS/?\">TMS</a></li>"); + services.append("<li><a href=\"/ArcGIS/?wsdl\">ArcGIS MapServer (SOAP)</a></li>"); + services.append("<li><a href=\"/ArcGIS/?f=json\">ArcGIS MapServer (REST)</a></li>"); + html = html.replace("@SERVICES", services.toString()); + + byte[] rsp = html.toString().getBytes("UTF-8"); + + + //Create a custom ETag + String eTag = "W/\"" + rsp.length + "-" + date.getTime() + "\""; + + + //Create http response header + String header = getHeader(date, "text/html", rsp.length, eTag, false); + byte[] hdr = header.getBytes(); + + + //Create a buffer to write bytes to the socket + int bufferSize = hdr.length + rsp.length; + java.nio.ByteBuffer output = java.nio.ByteBuffer.allocateDirect(bufferSize); + + output.put(hdr); + output.put(rsp); + output.flip(); + synchronized(connection) { + connection.write(output); + } + + + //Update the http cache + this.updateCache(key, eTag); + + } + + + + //************************************************************************** - //** getTile + //** getCapabilities //************************************************************************** - /** Used to construct a response to a TMS Map request + /** Used to construct a response to a WMS GetCapabilities request */ - private void getTile(RequestHeader request, SocketChannel connection) throws IOException { + private void getCapabilities(RequestHeader request, SocketChannel connection) throws IOException { javaxt.utils.Date date = new javaxt.utils.Date(); date.setTimeZone("GMT"); + String url = request.getURL().toString(); + if (url.contains("?")) url = url.substring(0, url.indexOf("?")); + if (!url.endsWith("/")) url += "/"; + if (!url.toLowerCase().endsWith("/wms/")) url += "wms/"; - javaxt.utils.URL url = new javaxt.utils.URL(request.getURL()); - System.out.println(url); + //Get Capabilities + mapproxy.core.Service service = getMapProxy(); + String orgURL = service.getURL(); + service.setURL(url); + byte[] rsp = service.getCapabilities().toString("WMS").getBytes(); + service.setURL(orgURL); - //Check whether this request is in the http cache - mapproxy.tms.TileRequest req = new mapproxy.tms.TileRequest(url.toString()); - String key = req.id(); - String eTag = request.getProperty("if-none-match"); - String cacheControl = request.getProperty("cache-control"); + //Create a custom ETag + String eTag = "W/\"" + rsp.length + "-" + date.getTime() + "\""; - if (cacheControl==null) cacheControl = ""; - if (cacheControl.equalsIgnoreCase("no-cache")==false && eTag!=null){ + //Create http response header + String header = getHeader(date, "text/xml", rsp.length, eTag, false); + byte[] hdr = header.getBytes(); - String val = null; - synchronized (httpCache){ - val = httpCache.get(key); - } - if (val!=null){ - if (val.equals(eTag)){ - //Return 304 Response Code - StringBuffer header = new StringBuffer(); - header.append("HTTP/1.1 304 Not Modified\r\n"); - header.append("Date: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); - header.append("Server: " + serverName + "\r\n"); - header.append("ETag: " + eTag + "\r\n"); - header.append("\r\n"); + //Create a buffer to write bytes to the socket + int bufferSize = hdr.length + rsp.length; + java.nio.ByteBuffer output = java.nio.ByteBuffer.allocateDirect(bufferSize); - System.out.println("304 Response!"); - //System.out.println(header); - byte[] response = header.toString().getBytes(); - java.nio.ByteBuffer output = java.nio.ByteBuffer.allocateDirect(response.length); - output.put(response); - output.flip(); - synchronized(connection) { - connection.write(output); - } - return; - } - } - + output.put(hdr); + output.put(rsp); + output.flip(); + synchronized(connection) { + connection.write(output); } + } + + //************************************************************************** + //** getTile + //************************************************************************** + /** Used to construct a response to a TMS Map request + */ + private void getTile(RequestHeader request, SocketChannel connection) throws IOException { + + //Set local variables + String url = request.getURL().toString(); + javaxt.utils.Date date = new javaxt.utils.Date(); + date.setTimeZone("GMT"); + + + //Check whether this request is in the http cache + mapproxy.tms.TileRequest req = new mapproxy.tms.TileRequest(url); + String key = req.id(); + if (useCache(request, connection, key, date)) return; + + + //Find requested layer in the mapproxy service definition mapproxy.core.Service mapproxy = this.getMapProxy(); + mapproxy.core.Layer layer = mapproxy.getLayer(req.layer); - mapproxy.core.Layer layer = mapproxy.getLayers()[0]; + + //Instantiate the TMS cache and find the requested tile FileCache fileCache = (FileCache) layer.getParam("cache"); TileGrid grid = (TileGrid) layer.getParam("grid"); - - mapproxy.tms.cache.TMSTileSource tms = new mapproxy.tms.cache.TMSTileSource(grid, url.toString()); + mapproxy.tms.cache.TMSTileSource tms = new mapproxy.tms.cache.TMSTileSource(grid, url); CacheManager cacheManager = new CacheManager(fileCache, tms); Cache cache = new Cache(cacheManager, grid, true); + req.tile = new mapproxy.tms.TileServiceGrid(grid).internal_tile_coord(req.tile, true); - String format = req.format; - byte[] img; + String path = ""; try{ - req.tile = new mapproxy.tms.TileServiceGrid(grid).internal_tile_coord(req.tile, true); - img = new javaxt.io.File(cache.tile(req.tile).location).getBytes().toByteArray(); + path = cache.tile(req.tile).location; } catch(Exception e){ - img = new javaxt.io.Image(grid.tile_size[0], grid.tile_size[1]).getByteArray(format); + int[] coord = req.tile; + double[] bbox = grid.tile_bbox(coord[0], coord[1], coord[2]); + getImage(layer, grid.tile_size[0], grid.tile_size[1], fileCache.file_ext, bbox, grid.srs.toString()); + try{ + path = cache.tile(req.tile).location; + } + catch(Exception ex){ + } } + javaxt.io.File file = new javaxt.io.File(path); + //Convert the tile into a byte array + byte[] img; + String format = req.format; + if (file.exists() && file.getSize()>0){ + if (file.getExtension().equalsIgnoreCase(format)){ + img = file.getBytes().toByteArray(); + } + else{ + img = file.getImage().getByteArray(format); + } + } + else{ + img = new javaxt.io.Image(grid.tile_size[0], grid.tile_size[1]).getByteArray(format); + } + //Create http response header + String eTag = "W/\"" + img.length + "-" + date.getTime() + "\""; + String header = getHeader(date, "image/"+format, img.length, eTag, false); + byte[] hdr = header.getBytes(); + - - //Create a custom ETag - eTag = "W/\"" + img.length + "-" + date.getTime() + "\""; - - - //Write Response Header - StringBuffer header = new StringBuffer(); - header.append("HTTP/1.1 200 OK\r\n"); - header.append("Date: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); - header.append("Server: " + serverName + "\r\n"); - header.append("Content-Type: " + format + "\r\n"); - header.append("Content-Length: " + img.length + "\r\n"); - header.append("ETag: " + eTag + "\r\n"); - header.append("Last-Modified: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); //Sat, 23 Oct 2010 13:04:28 GMT - //header.append("Cache-Control: " + "max-age=" + (365*24*60*60) + "\r\n"); //vs "no-cache" - header.append("Accept-Ranges: bytes\r\n"); - header.append("Connection: Keep-Alive\r\n"); - - header.append("\r\n"); - - System.out.print("\r\n" + header.toString()); - - - //Convert the header into a byte array - byte[] hdr = header.toString().getBytes(); - - - //Create a buffer to write bytes to the socket + //Create a buffer to write response to the socket int bufferSize = img.length + hdr.length; java.nio.ByteBuffer output = java.nio.ByteBuffer.allocateDirect(bufferSize); @@ -387,18 +464,12 @@ connection.write(output); } - System.out.println("Completed writing bytes..."); //Update the http cache - synchronized (httpCache){ - httpCache.put(key, eTag); - } - + this.updateCache(key, eTag); } - - //************************************************************************** //** getMap //************************************************************************** @@ -412,7 +483,7 @@ javaxt.utils.URL url = new javaxt.utils.URL(request.getURL()); - System.out.println(url); + //System.out.println(url); String layers = url.removeParameter("layers"); String bbox = url.removeParameter("bbox"); @@ -429,46 +500,13 @@ //Check whether this request is in the http cache String key = bbox + "|" + layers + "|" + format + "|" + width + "|" + height + "|" + srs; - - String eTag = request.getProperty("if-none-match"); - String cacheControl = request.getProperty("cache-control"); + if (useCache(request, connection, key, date)) return; - if (cacheControl==null) cacheControl = ""; - if (cacheControl.equalsIgnoreCase("no-cache")==false && eTag!=null){ - String val = null; - synchronized (httpCache){ - val = httpCache.get(key); - } - if (val!=null){ - if (val.equals(eTag)){ + mapproxy.core.Service mapproxy = this.getMapProxy(); - //Return 304 Response Code - StringBuffer header = new StringBuffer(); - header.append("HTTP/1.1 304 Not Modified\r\n"); - header.append("Date: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); - header.append("Server: " + serverName + "\r\n"); - header.append("ETag: " + eTag + "\r\n"); - header.append("\r\n"); - System.out.println("304 Response!"); - //System.out.println(header); - byte[] response = header.toString().getBytes(); - java.nio.ByteBuffer output = java.nio.ByteBuffer.allocateDirect(response.length); - output.put(response); - output.flip(); - synchronized(connection) { - connection.write(output); - } - return; - } - } - - } - - - mapproxy.core.Service mapproxy = this.getMapProxy(); - + //Create image for each layer javaxt.io.Image image = new javaxt.io.Image(width, height); for (String layerName : layers.split(",")){ @@ -485,61 +523,12 @@ catch(Exception e){ } } - if (layer!=null){ - FileCache fileCache = (FileCache) layer.getParam("cache"); - TileGrid grid = (TileGrid) layer.getParam("grid"); - - String host = (String) layer.getParam("host"); - if (!host.contains("?")) host += "?"; - //host += url.getQueryString(); - - WMSMapRequestParams param = new WMSMapRequestParams(); - param.set("layers", (String) layer.getParam("layers")); - param.set("bbox", bbox); - - WMS111MapRequest req = new WMS111MapRequest(param, host); - req.params.size(new int[]{width, height}); - req.params.set("srs", srs); - - - - //if (format.equalsIgnoreCase("image/PNG24")) format = "jpeg"; //<-- This is crazy! If I return a 24 bit PNG, ArcMap doesn't display anything. If I return a JPEG, works like a champ - if (!format.toLowerCase().startsWith("image/")) format = "image/" + format; - if (format.equalsIgnoreCase("image/PNG24") && fileCache!=null) format = "image/png"; - format = "image/png"; - req.params.set("format", format); - - String protocol = (String) layer.getParam("protocol"); - if (protocol.equalsIgnoreCase("WMS")){ - - if (fileCache==null){ - image.addImage(new WMSClient(req).get_map(req), 0, 0, false); - } - else{ - WMSTileSource wms = new WMSTileSource(grid, new WMSClient(req)); - CacheManager cacheManager = new CacheManager(fileCache, wms); - Cache cache = new Cache(cacheManager, grid, true); - image.addImage(cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()), 0, 0, false); - } - } - else if (protocol.equalsIgnoreCase("MapServer")){ - - if (fileCache==null){ - image.addImage(new MapClient(req).get_map(req), 0, 0, false); - } - else{ - MapTileSource arcMapServer = new MapTileSource(grid, new MapClient(req)); - CacheManager cacheManager = new CacheManager(fileCache, arcMapServer); - Cache cache = new Cache(cacheManager, grid, true); - image.addImage(cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()), 0, 0, false); - } - - - } + image.addImage(getImage(layer, width, height, format, bbox, srs), 0, 0, false); } } + //Convert the image into a byte array //byte[] img = new javaxt.io.File("/temp/ArcGIS/ExportImage.png").getBytes().toByteArray(); @@ -548,37 +537,15 @@ - - //Create a custom ETag - eTag = "W/\"" + img.length + "-" + date.getTime() + "\""; + String eTag = "W/\"" + img.length + "-" + date.getTime() + "\""; - //Write Response Header - StringBuffer header = new StringBuffer(); - header.append("HTTP/1.1 200 OK\r\n"); - header.append("Date: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); - header.append("Server: " + serverName + "\r\n"); - header.append("Content-Type: " + format + "\r\n"); - header.append("Content-Length: " + img.length + "\r\n"); - header.append("ETag: " + eTag + "\r\n"); - header.append("Last-Modified: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); //Sat, 23 Oct 2010 13:04:28 GMT - //header.append("Cache-Control: " + "max-age=" + (365*24*60*60) + "\r\n"); //vs "no-cache" - header.append("Accept-Ranges: bytes\r\n"); - header.append("Connection: Keep-Alive\r\n"); + //Create http response header + String header = getHeader(date, format, img.length, eTag, false); + byte[] hdr = header.getBytes(); - //header.append("Proxy-Connection: Keep-Alive\r\n"); - //header.append("Via: 1.1 SPATCFW003\r\n"); - header.append("\r\n"); - - System.out.print("\r\n" + header.toString()); - - - //Convert the header into a byte array - byte[] hdr = header.toString().getBytes(); - - //Create a buffer to write bytes to the socket int bufferSize = img.length + hdr.length; java.nio.ByteBuffer output = java.nio.ByteBuffer.allocateDirect(bufferSize); @@ -590,149 +557,86 @@ connection.write(output); } - System.out.println("Completed writing bytes..."); + //System.out.println("Completed writing bytes..."); + //Update the http cache - synchronized (httpCache){ - httpCache.put(key, eTag); - } + this.updateCache(key, eTag); } - private mapproxy.core.Service getMapProxy(){ - return ((mapproxy.core.Service) mapproxy.config.Config.base_config().get("mapproxy").toObject()); - } //************************************************************************** - //** getLandingPage + //** getImage //************************************************************************** - /** Used to construct an HTML landing page for the service. + /** Used to retrieve an image from a server for a given layer */ - private void getLandingPage(RequestHeader request, SocketChannel connection) throws IOException { + private javaxt.io.Image getImage(mapproxy.core.Layer layer, int width, int height, String format, String bbox, String srs){ - mapproxy.core.Service service = this.getMapProxy(); + FileCache fileCache = (FileCache) layer.getParam("cache"); + TileGrid grid = (TileGrid) layer.getParam("grid"); - javaxt.utils.Date date = new javaxt.utils.Date(); - date.setTimeZone("GMT"); + String host = (String) layer.getParam("host"); + if (!host.contains("?")) host += "?"; + //host += url.getQueryString(); - String url = request.getURL().toString(); - if (url.contains("?")) url = url.substring(0, url.indexOf("?")); - - String html = mapproxy.config.Config.base_config().get("html").toString(); - html = html.replace("@SERVICENAME", service.getName()); - html = html.replace("@SERVICEDESCRIPTION", service.getDescription()); + WMSMapRequestParams param = new WMSMapRequestParams(); + param.set("layers", (String) layer.getParam("layers")); + param.set("bbox", bbox); - StringBuffer layers = new StringBuffer(); - for (Layer layer : service.getLayers()){ - layers.append("<li>" + layer.getName() + "</li>"); - } - html = html.replace("@LAYERS", layers.toString()); + WMS111MapRequest req = new WMS111MapRequest(param, host); + req.params.size(new int[]{width, height}); + req.params.set("srs", srs); - - StringBuffer services = new StringBuffer(); - services.append("<li><a href=\"/WMS/?service=WMS&request=GetCapabilities&version=1.1.1\">WMS</a></li>"); - services.append("<li><a href=\"/ArcGIS/?wsdl\">ArcGIS MapServer (SOAP)</a></li>"); - services.append("<li><a href=\"/ArcGIS/?f=json\">ArcGIS MapServer (REST)</a></li>"); - html = html.replace("@SERVICES", services.toString()); - byte[] rsp = html.toString().getBytes("UTF-8"); + //if (format.equalsIgnoreCase("image/PNG24")) format = "jpeg"; //<-- This is crazy! If I return a 24 bit PNG, ArcMap doesn't display anything. If I return a JPEG, works like a champ + if (!format.toLowerCase().startsWith("image/")) format = "image/" + format; + if (format.equalsIgnoreCase("image/PNG24") && fileCache!=null) format = "image/png"; + //format = "image/png"; + req.params.set("format", format); - //Create a custom ETag - String eTag = "W/\"" + rsp.length + "-" + date.getTime() + "\""; + String protocol = (String) layer.getParam("protocol"); + if (protocol.equalsIgnoreCase("WMS")){ + if (fileCache==null){ + return new WMSClient(req).get_map(req); + } + else{ + WMSTileSource wms = new WMSTileSource(grid, new WMSClient(req)); + CacheManager cacheManager = new CacheManager(fileCache, wms); + Cache cache = new Cache(cacheManager, grid, true); + return cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()); + } + } + else if (protocol.equalsIgnoreCase("MapServer")){ - //Construct Response Header - StringBuffer header = new StringBuffer(); - header.append("HTTP/1.1 200 OK\r\n"); - header.append("Date: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); - header.append("Server: " + serverName + "\r\n"); - header.append("Content-Type: text/html\r\n"); - header.append("Content-Length: " + rsp.length + "\r\n"); - header.append("ETag: " + eTag + "\r\n"); - header.append("Last-Modified: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); //Sat, 23 Oct 2010 13:04:28 GMT - //header.append("Cache-Control: " + "max-age=" + (365*24*60*60) + "\r\n"); //vs "no-cache" - header.append("\r\n"); + if (fileCache==null){ + return new MapClient(req).get_map(req); + } + else{ + MapTileSource arcMapServer = new MapTileSource(grid, new MapClient(req)); + CacheManager cacheManager = new CacheManager(fileCache, arcMapServer); + Cache cache = new Cache(cacheManager, grid, true); + return cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()); + } - //System.out.println(header); - //Convert the header into a byte array - byte[] hdr = header.toString().getBytes(); + } - //Create a buffer to write bytes to the socket - int bufferSize = hdr.length + rsp.length; - java.nio.ByteBuffer output = java.nio.ByteBuffer.allocateDirect(bufferSize); + return null; - output.put(hdr); - output.put(rsp); - output.flip(); - synchronized(connection) { - connection.write(output); - } } + private javaxt.io.Image getImage(mapproxy.core.Layer layer, int width, int height, String format, double[] bbox, String srs){ + return this.getImage(layer, width, height, format, bbox[0] + "," + bbox[1] + "," + bbox[2] + "," + bbox[3], srs); + } - //************************************************************************** - //** getCapabilities - //************************************************************************** - /** Used to construct a response to a WMS GetCapabilities request - */ - private void getCapabilities(RequestHeader request, SocketChannel connection) throws IOException { - javaxt.utils.Date date = new javaxt.utils.Date(); - date.setTimeZone("GMT"); - - String url = request.getURL().toString(); - if (url.contains("?")) url = url.substring(0, url.indexOf("?")); - if (!url.endsWith("/")) url += "/"; - if (!url.toLowerCase().endsWith("/wms/")) url += "wms/"; - - //Get Capabilities - - mapproxy.core.Service service = getMapProxy(); - String orgURL = service.getURL(); - service.setURL(url); - byte[] rsp = service.getCapabilities().toString("WMS").getBytes(); - service.setURL(orgURL); - - - //Create a custom ETag - String eTag = "W/\"" + rsp.length + "-" + date.getTime() + "\""; - - - //Construct Response Header - StringBuffer header = new StringBuffer(); - header.append("HTTP/1.1 200 OK\r\n"); - header.append("Date: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); - header.append("Server: " + serverName + "\r\n"); - header.append("Content-Type: text/xml\r\n"); - header.append("Content-Length: " + rsp.length + "\r\n"); - header.append("ETag: " + eTag + "\r\n"); - header.append("Last-Modified: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); //Sat, 23 Oct 2010 13:04:28 GMT - //header.append("Cache-Control: " + "max-age=" + (365*24*60*60) + "\r\n"); //vs "no-cache" - header.append("\r\n"); - - //System.out.println(header); - - //Convert the header into a byte array - byte[] hdr = header.toString().getBytes(); - - //Create a buffer to write bytes to the socket - int bufferSize = hdr.length + rsp.length; - java.nio.ByteBuffer output = java.nio.ByteBuffer.allocateDirect(bufferSize); - - output.put(hdr); - output.put(rsp); - output.flip(); - synchronized(connection) { - connection.write(output); - } - } - //************************************************************************** //** getArcMapImage //************************************************************************** @@ -1152,8 +1056,104 @@ return ""; } + //************************************************************************** + //** getHeader + //************************************************************************** + /** Used to construct an http response header + */ + private String getHeader(javaxt.utils.Date date, String format, long length, String eTag, boolean gzip){ + StringBuffer header = new StringBuffer(); + header.append("HTTP/1.1 200 OK\r\n"); + header.append("Date: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); + header.append("Server: " + serverName + "\r\n"); + header.append("Content-Type: " + format + "\r\n"); + header.append("Content-Length: " + length + "\r\n"); + header.append("ETag: " + eTag + "\r\n"); + header.append("Last-Modified: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); //Sat, 23 Oct 2010 13:04:28 GMT + //header.append("Cache-Control: " + "max-age=" + (365*24*60*60) + "\r\n"); //vs "no-cache" + //header.append("Accept-Ranges: bytes\r\n"); + header.append("Connection: Keep-Alive\r\n"); + if (gzip){ + header.append("Content-Encoding: gzip\r\n"); + } + header.append("\r\n"); + //System.out.print("\r\n" + header.toString()); + return header.toString(); + } + + //************************************************************************** + //** useCache + //************************************************************************** + /** Used to check whether the request is in the http cache. If so, sends a + * 304 http response and returns true. Otherwise, nothing is sent back to + * the client and the method returns false. + */ + private boolean useCache(RequestHeader request, SocketChannel connection, String key, javaxt.utils.Date date) throws IOException { + + String eTag = request.getProperty("if-none-match"); + String cacheControl = request.getProperty("cache-control"); + + if (cacheControl==null) cacheControl = ""; + if (cacheControl.equalsIgnoreCase("no-cache")==false && eTag!=null){ + + String val = null; + synchronized (httpCache){ + val = httpCache.get(key); + } + if (val!=null){ + if (val.equals(eTag)){ + + //Return 304 Response Code + StringBuffer header = new StringBuffer(); + header.append("HTTP/1.1 304 Not Modified\r\n"); + header.append("Date: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); + header.append("Server: " + serverName + "\r\n"); + header.append("ETag: " + eTag + "\r\n"); + header.append("\r\n"); + + System.out.println("304 Response!"); + //System.out.println(header); + byte[] response = header.toString().getBytes(); + java.nio.ByteBuffer output = java.nio.ByteBuffer.allocateDirect(response.length); + output.put(response); + output.flip(); + synchronized(connection) { + connection.write(output); + } + return true; + } + } + + } + + return false; + } + + + //************************************************************************** + //** updateCache + //************************************************************************** + /** Used to update the http cache. + */ + private void updateCache(String key, String eTag){ + synchronized (httpCache){ + httpCache.put(key, eTag); //<-- Need to make this smarter so we don't run out of memory... + } + } + + + private boolean compressResponse(RequestHeader request){ + return request.getProperty("Accept-Encoding").toLowerCase().contains("gzip"); + } + + + //************************************************************************** + //** gzip + //************************************************************************** + /** Used gzip compress a byte array + */ private byte[] gzip(byte[] img) throws IOException { System.out.println(img.length + " bytes"); @@ -1167,4 +1167,9 @@ return img; } + + private mapproxy.core.Service getMapProxy(){ + return ((mapproxy.core.Service) mapproxy.config.Config.base_config().get("mapproxy").toObject()); + } + } \ No newline at end of file Modified: tms/TileRequest.java =================================================================== --- tms/TileRequest.java 2011-04-04 21:48:28 UTC (rev 23) +++ tms/TileRequest.java 2011-04-05 11:36:23 UTC (rev 24) @@ -4,12 +4,13 @@ //** TileRequest Class //****************************************************************************** /** - * + * Used to represent a TMS request. * ******************************************************************************/ public class TileRequest { + private String url; public String layer; public String format = "png"; public int[] tile; @@ -22,6 +23,7 @@ */ public TileRequest(String url){ + this.url = url; format = url.substring(url.lastIndexOf(".")+1); url = url.substring(0, url.lastIndexOf(".")); int y = cint(url.substring(url.lastIndexOf("/")+1)); @@ -33,9 +35,24 @@ tile = new int[]{x,y,z}; layer = url.substring(url.lastIndexOf("/")+1); - System.out.println("format: " + format); - System.out.println("layer: " + layer); - System.out.println("tile: " + mapproxy.core.Python.cstr(tile)); + if (layer.contains("%")){ + try{ + layer = new java.net.URLDecoder().decode(layer, "UTF-8"); + } + catch(Exception e){ + //Try to decode the string manually + String find[] = new String[]{"%20","%2C","%2F","%3A"}; + String replace[] = new String[]{" ",",","/",":"}; + for (int i=0; i<find.length; i++){ + layer = layer.replace(find[i],replace[i]); + } + } + } + + + //System.out.println("format: " + format); + //System.out.println("layer: " + layer); + //System.out.println("tile: " + mapproxy.core.Python.cstr(tile)); } public String id(){ @@ -49,4 +66,9 @@ return javaxt.utils.string.cint(s); } + + public String toString(){ + return this.url; + } + } Modified: tms/TileServiceGrid.java =================================================================== --- tms/TileServiceGrid.java 2011-04-04 21:48:28 UTC (rev 23) +++ tms/TileServiceGrid.java 2011-04-05 11:36:23 UTC (rev 24) @@ -137,10 +137,6 @@ if (z < 0) return null; - //Added hack for OpenLayers - if (this.grid.srs.isGeographic()){ - //z *= 2; - } if (use_profiles && this._skip_first_level) z += 1; @@ -151,7 +147,7 @@ //x = x+2; //y = y+1; //z = 4; - System.out.println("z: " + z); + //System.out.println("z: " + z); return this.grid.limit_tile(new int[]{x, y, z}); } Modified: tms/cache/TMSTileSource.java =================================================================== --- tms/cache/TMSTileSource.java 2011-04-04 21:48:28 UTC (rev 23) +++ tms/cache/TMSTileSource.java 2011-04-05 11:36:23 UTC (rev 24) @@ -2,7 +2,7 @@ import mapproxy.tms.*; import mapproxy.core.cache.*; import mapproxy.core.grid.*; -import mapproxy.core.image.*; +//import mapproxy.core.image.*; //import mapproxy.wms.request.*; import mapproxy.core.Python; @@ -93,7 +93,6 @@ * tiles. * @param tile_map tile_collection */ - public TileCollection create_tile(_Tile tile, TileCollection tile_map){ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-04-04 21:48:36
|
Revision: 23 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=23&view=rev Author: pborissow Date: 2011-04-04 21:48:28 +0000 (Mon, 04 Apr 2011) Log Message: ----------- Initial cut at a TMS. Also, added bug fixes for ArcGIS MapServer. Modified Paths: -------------- Main.java arcgis/server/MapServer.java config.xml core/Capabilities.java core/SRS.java core/cache/CacheManager.java core/cache/_SequentialTileCreator.java core/grid/Grid.java core/grid/TileGrid.java core/image/ImageTransformer.java server/RequestProcessor.java Added Paths: ----------- ArcGIS.htm OpenLayers.htm tms/ tms/TMSClient.java tms/TileRequest.java tms/TileServiceGrid.java tms/TileServiceLayer.java tms/cache/ tms/cache/TMSTileSource.java Removed Paths: ------------- wms/server/Capabilities.java Added: ArcGIS.htm =================================================================== --- ArcGIS.htm (rev 0) +++ ArcGIS.htm 2011-04-04 21:48:28 UTC (rev 23) @@ -0,0 +1,24 @@ +<html> +<head> +<title>ArcGIS JavaScript API</title> +<link type="text/css" rel="stylesheet" href="http://serverapi.arcgisonline.com/jsapi/arcgis/1.2/js/dojo/dijit/themes/tundra/tundra.css" /> +<script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis?v=1.2"></script> +<script type="text/javascript"> + dojo.require("esri.map"); + var map; + function Init() { + dojo.style(dojo.byId("map"), { width: "100%", height: "100%" }); + map = new esri.Map("map"); + var layer = new esri.layers.ArcGISDynamicMapServiceLayer("http://localhost:9080/ArcGIS"); + map.addLayer(layer); + } + dojo.addOnLoad(Init); +</script> +</head> +<body class="tundra" style="padding:0;margin:0;"> +<div id="map" style="padding:0;margin:0;width:100%;border:0px;"></div> +<!-- +Built using the <a href="http://resources.esri.com/arcgisserver/apis/javascript/arcgis">ArcGIS JavaScript API</a> +--> +</body> +</html> \ No newline at end of file Modified: Main.java =================================================================== --- Main.java 2011-03-31 23:40:08 UTC (rev 22) +++ Main.java 2011-04-04 21:48:28 UTC (rev 23) @@ -64,16 +64,78 @@ //testCache(url); //testSRS(); - + args = new String[]{"C:\\Documents and Settings\\peter.borissow\\My Documents\\Java\\Libraries\\mapproxy\\src\\mapproxy\\config.xml"}; startServer(args); //testWebServices(); //testArcWebServices(); + //testTMS(); + } + private void testTMS(){ + + +/* + FileCache fileCache = new FileCache("/temp/mapproxy/java/ew/", "png"); + int[] tile_size = new int[]{256,256}; + TileGrid grid = new TileGrid(4326, tile_size); + + WMS111MapRequest req = getWMS111MapRequest(url); + WMSTileSource wms = new WMSTileSource(grid, new WMSClient[]{new WMSClient(req)}); + + */ + + FileCache fileCache = new FileCache("/temp/mapproxy/world.map/", "png"); + int[] tile_size = new int[]{256,256}; + TileGrid grid = new TileGrid(4326, tile_size); + + + String url = "http://localhost:9080/tms/Default%20Basemap/2/9/13.png"; + mapproxy.tms.TileRequest req = new mapproxy.tms.TileRequest(url); + + +/* + System.out.println(Python.cstr(req.tile)); + System.out.println(fileCache.tile_location(new _Tile(req.tile), false)); + + int[] coord = req.tile; + System.out.println(Python.cstr(grid.tile_bbox(coord[0], coord[1], coord[2]))); +*/ + + mapproxy.tms.cache.TMSTileSource tms = new mapproxy.tms.cache.TMSTileSource(grid, url); + + CacheManager cacheManager = new CacheManager(fileCache, tms); + Cache cache = new Cache(cacheManager, grid, true); + + + + //Update the + mapproxy.tms.TileServiceGrid g = new mapproxy.tms.TileServiceGrid(grid); + req.tile = g.internal_tile_coord(req.tile, true); + + int[] coord = req.tile; + System.out.println(Python.cstr(grid.tile_bbox(coord[0], coord[1], coord[2]))); + + //System.out.println(cache.tile(req.tile).source); + + + //http://localhost:9080/ArcGIS/?LAYERS=Default Basemap&FORMAT=png&BBOX=-12.897806,38.540149,-0.043791,51.394164&SIZE=256,256&F=image&BBOXSR=4326&IMAGESR=4326 + //cache.image(req.params.bbox(), new SRS(req.params.srs()), req.params.size()).saveAs("/temp/ew_cache.png"); + + + /* + mapproxy.tms.TileServiceLayer lyr = new mapproxy.tms.TileServiceLayer(null, cache); + lyr.render(req, false); + */ + + +// } + + private void testSRS(){ /* @@ -127,7 +189,8 @@ private void testWebServices() throws Exception { - String url = "http://services.arcgisonline.com/ArcGIS/services/USA_Topo_Maps/MapServer"; + String url = "http://localhost:9080/ArcGIS/"; + //String url = "http://services.arcgisonline.com/ArcGIS/services/USA_Topo_Maps/MapServer"; //url = "http://services.arcgisonline.com/ArcGIS/services/"; //url = "http://sampleserver1.arcgisonline.com/ArcGIS/services/"; @@ -147,8 +210,10 @@ //msg += "<soap:Body><tns:GetTileImageInfo><MapName>Layers</MapName></tns:GetTileImageInfo></soap:Body>"; msg += "</soap:Envelope>"; - - //msg = new javaxt.io.File("/temp/testMapImageRequest.xml").getText("UTF-8"); + + + String fileName = "MapProxy-2781"; + msg = new javaxt.io.File("/temp/ArcGIS/" + fileName + ".xml").getText("UTF-8"); javaxt.http.Request request = new javaxt.http.Request(url); request.setHeader("Accept", "*/*"); request.setHeader("Content-Type", "text/xml"); @@ -156,10 +221,10 @@ request.setHeader("SOAPAction", "\"\""); request.write(msg); javaxt.http.Response response = request.getResponse(); - System.out.println(response); + //System.out.println(response); //System.out.println(response.getStatus() + ": " + response.getMessage()); - System.out.println(response.getText()); - //new javaxt.io.File("/temp/GetServerInfo.xml").write(response.getText(), "UTF-8"); + //System.out.println(response.getText()); + new javaxt.io.File("/temp/ArcGIS/" + fileName + "_response.xml").write(response.getText(), "UTF-8"); } Added: OpenLayers.htm =================================================================== --- OpenLayers.htm (rev 0) +++ OpenLayers.htm 2011-04-04 21:48:28 UTC (rev 23) @@ -0,0 +1,197 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <link rel="stylesheet" href="OpenLayers-2.7/theme/default/style.css" type="text/css" /> + <link rel="stylesheet" href="style.css" type="text/css" /> + <style type="text/css"> + body { background-color: #FFFFFF; + margin-left: 0px; margin-right: 0px; margin-top: 0px; margin-bottom: 0px; + } + body, textarea, input, td { + font-family:"MS Sans Serif",tahoma,arial,helvetica,sans-serif; + font-size: 8pt;color:#000000;text-decoration:none; text-align:left;font-weight: normal; + } + </style> + <script src="http://www.openlayers.org/api/OpenLayers.js"></script> + <script type="text/javascript"> + var lon = 5; + var lat = 40; + var zoom = 2; + var map, layer, tags; + + function init(){ + //map = new OpenLayers.Map( 'map' ); + tags = document.getElementById("tags"); + + + map = new OpenLayers.Map( 'map', + { + //maxExtent: new OpenLayers.Bounds(-130, 30, -80, 55), + //maxResolution: 360 / 256 / Math.pow(2, 4), + + maxExtent: new OpenLayers.Bounds(-180, -90, 180, 90), + //minScale: 70000000, + //maxScale: 1000, + units: "degrees" + }); + + + map.projection = new OpenLayers.Projection("EPSG:4326"); + map.displayProjection = new OpenLayers.Projection("EPSG:4326"); + + + var wms = new OpenLayers.Layer.WMS( + "MapProxy", + "http://localhost:9080/WMS/", + { + layers: 'Default Basemap', //List of layers to display + format: 'image/png' + }, + { tileSize: new OpenLayers.Size(256,256), buffer: 1, 'isBaseLayer':true } //Rendering options + + ); + //map.addLayer(wms); + + + + var vmap = new OpenLayers.Layer.TMS( "VMAP", + "http://tilecache.osgeo.org/wms-c/Basic.py/", + { + layername: 'basic', type:'png', zoomOffset: -1, + projection: new OpenLayers.Projection("EPSG:4326") + } + ); + map.addLayer(vmap); + + + + var tms = new OpenLayers.Layer.TMS( + "TMS", + "http://localhost:9080/TMS/", + { + layername: 'Default Basemap', type:'png', zoomOffset: -1, + projection: new OpenLayers.Projection("EPSG:4326") + } + ); + map.addLayer(tms); + + + var arcgis = new OpenLayers.Layer.ArcGIS93Rest( + "ArcGIS", + "http://localhost:9080/ArcGIS/", + { + layers: "Default Basemap" + } + ); + map.addLayer(arcgis); + + + + layer = new OpenLayers.Layer.WMS( + "OpenLayers WMS", + "http://www.kartographia.com/MapProxy/demo/mapproxy.jsp", //"/cgi-bin/mapserv.exe?map=D:/maps/world.map", + { + layers: 'world_grid,polboundaries,hydro,cities,geogrid', //List of layers to display + format: 'image/png' + }, + { tileSize: new OpenLayers.Size(256,256), buffer: 1, 'isBaseLayer':true } //Rendering options + + ); + //map.addLayer(layer); + + + + var highways = new OpenLayers.Layer.ArcGIS93Rest("Highways", + "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer/export", + { + layers: "0,1,2" + } + ); + //map.addLayer(highways); + + var modis = new OpenLayers.Layer.ArcGIS93Rest("MODIS", + "http://localhost:9080/ImageServer", //"http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/World/MODIS/ImageServer/exportImage", + { + layers: "0" + }, + { + 'singleTile':true, + 'transitionEffect':'resize'} + ); + //map.addLayer(modis); + + map.setCenter(new OpenLayers.LonLat(lon, lat), zoom); + map.addControl( new OpenLayers.Control.LayerSwitcher() ); + + + + //Add logic to process map move events. This event is fired whenever + //the map is moved or the extents have changed. + map.events.register("moveend", null, function(e){ + var scale = map.getScale(); + //document.forms[0].scale.value = "1:"+addCommas(Math.round(scale)); + document.title = "1:"+addCommas(Math.round(scale)); + }); + + + map.events.register("mousemove", null, function(e){ + + var lonlat = map.getLonLatFromViewPortPx(e.xy); + if(lonlat == null){ + return; + } + var lat = lonlat.lat; + var lon = lonlat.lon; + + + var p = 1000000000; //precision + lat = Math.round(lat*p)/p; + lon = Math.round(lon*p)/p; + + p = (p + '').length-1; + + if (lat.toString().indexOf(".")<0) { + lat+=".0000"; + } + if (lon.toString().indexOf(".")<0) { + lon+=".0000"; + } + + var arr = (lat + '0000000000').split("\."); + arr[1] = arr[1].substring(0, p); + lat = arr[0] + "." + arr[1]; + + arr = (lon + '0000000000').split("\."); + arr[1] = arr[1].substring(0, p); + lon = arr[0] + "." + arr[1]; + + tags.innerHTML = lat + ", " + lon; + }); + + + function addCommas(nStr){ + nStr += ''; + x = nStr.split('.'); + x1 = x[0]; + x2 = x.length > 1 ? '.' + x[1] : ''; + var rgx = /(\d+)(\d{3})/; + while (rgx.test(x1)) { + x1 = x1.replace(rgx, '$1' + ',' + '$2'); + } + return x1 + x2; + } + + } + </script> + </head> + <body onload="init()"> + <table width="100%" height="100%" border="0"> + <tr> + <td id="map" width="100%" height="100%"></td> + </tr> + <tr> + <td id="tags" align="right" height="20"></td> + </tr> + </table> + + </body> +</html> \ No newline at end of file Modified: arcgis/server/MapServer.java =================================================================== --- arcgis/server/MapServer.java 2011-03-31 23:40:08 UTC (rev 22) +++ arcgis/server/MapServer.java 2011-04-04 21:48:28 UTC (rev 23) @@ -165,7 +165,8 @@ */ public String getExportMapImageResponse(javaxt.utils.URL url, String layers, String bbox, String wkt, String width, String height, String format, String returnType){ - + + //Convert the WKT into an EPSG for the WMS url String srs = "EPSG:4326"; try{ CoordinateReferenceSystem crs = CRS.parseWKT(wkt); @@ -176,6 +177,12 @@ catch(Exception e){ e.printStackTrace(); } + + + //Update the format parameter + if (format.startsWith("esriImage")) format = format.substring("esriImage".length()); + //if (format.equalsIgnoreCase("PNG24")) format = "jpeg"; //<-- This is crazy! If I return a 24 bit PNG, ArcMap doesn't display anything. If I return a JPEG, works like a champ + url.setParameter("BBOX", bbox); @@ -238,7 +245,7 @@ xml.append("</soap:Body>"); xml.append("</soap:Envelope>"); - new javaxt.io.File("/temp/export.xml").write(xml.toString(), "UTF-8"); + //new javaxt.io.File("/temp/export.xml").write(xml.toString(), "UTF-8"); return xml.toString(); Modified: config.xml =================================================================== --- config.xml 2011-03-31 23:40:08 UTC (rev 22) +++ config.xml 2011-04-04 21:48:28 UTC (rev 23) @@ -41,8 +41,21 @@ <Layers>country_names</Layers> </Host> </Layer> - + + <Layer> + <Name>USA_Topo_Maps</Name> + <Host> + <BaseRequest protocol="MapServer"> + <![CDATA[ + http://services.arcgisonline.com/ArcGIS/rest/services/USA_Topo_Maps/MapServer + ]]> + </BaseRequest> + <Layers>0</Layers> + </Host> + </Layer> +<!-- + <Layer> <Name>ESRI_StateCityHighway_USA</Name> <Host> <BaseRequest protocol="MapServer"> @@ -78,7 +91,7 @@ </layer> - <!-- + <layer> <name>MODIS</name> <CacheDir>/temp/mapproxy/modis/</CacheDir> @@ -101,19 +114,12 @@ </Service> <Layers>states</Layers> </layer> - --> + - <Layer> - <Name>US States</Name> - <Host> - <BaseRequest protocol="MapServer"> - <![CDATA[ - http://services.arcgisonline.com/ArcGIS/rest/services/USA_Topo_Maps/MapServer - ]]> - </BaseRequest> - <Layers>0</Layers> - </Host> - </Layer> + + +--> + </layers> Modified: core/Capabilities.java =================================================================== --- core/Capabilities.java 2011-03-31 23:40:08 UTC (rev 22) +++ core/Capabilities.java 2011-04-04 21:48:28 UTC (rev 23) @@ -371,7 +371,7 @@ xml.append("</MapLayerInfo>"); x++; - break; + //break; } Modified: core/SRS.java =================================================================== --- core/SRS.java 2011-03-31 23:40:08 UTC (rev 22) +++ core/SRS.java 2011-04-04 21:48:28 UTC (rev 23) @@ -15,6 +15,7 @@ public class SRS { + private int epsg; private String proj; public CoordinateReferenceSystem crs; //<-- GeoTools CRS (Added to support ImageTransformer) @@ -26,7 +27,7 @@ public SRS(String srs_code){ - int epsg = 4326; + epsg = 4326; try{ epsg = get_epsg_num(srs_code); } @@ -36,7 +37,7 @@ this.proj = "epsg:" + epsg; - //Set GeoTools CRS (Added to support ImageTransformer) + //Set GeoTools CRS try{ if (epsg == 4326) crs = CRS.decode(this.proj, true); else crs = CRS.decode(this.proj); @@ -57,8 +58,13 @@ + public boolean isGeographic(){ + return mapproxy.core.grid.Grid.geodetic_epsg_codes.contains(epsg); + } + + //************************************************************************** //** get_epsg_num //************************************************************************** @@ -67,7 +73,7 @@ * get_epsg_num(4313) returns 4313 * get_epsg_num('31466') returns 31466 */ - public static int get_epsg_num(Object epsg_code){ + private static int get_epsg_num(Object epsg_code){ if (epsg_code instanceof String){ String epsg = (String) epsg_code; @@ -247,7 +253,8 @@ //************************************************************************** //** is_latlong //************************************************************************** - /** + /** Unused method. Referenced in the mapproxy.wms.layer.MultiLayer class + * >>> SRS(4326).is_latlong True >>> SRS(31466).is_latlong Modified: core/cache/CacheManager.java =================================================================== --- core/cache/CacheManager.java 2011-03-31 23:40:08 UTC (rev 22) +++ core/cache/CacheManager.java 2011-04-04 21:48:28 UTC (rev 23) @@ -98,7 +98,7 @@ /** Return the given `tiles` with the `_Tile.source` set. If a tile is not * cached, it will be created. */ - public TileCollection _load_tiles(TileCollection tiles, boolean with_metadata){ + private TileCollection _load_tiles(TileCollection tiles, boolean with_metadata){ tiles = this._load_cached_tiles(tiles, with_metadata); tiles = this._create_tiles(tiles, with_metadata); @@ -115,7 +115,7 @@ * @param tiles * @param with_metadata */ - public TileCollection _create_tiles(TileCollection tiles, boolean with_metadata){ + private TileCollection _create_tiles(TileCollection tiles, boolean with_metadata){ /* Modified: core/cache/_SequentialTileCreator.java =================================================================== --- core/cache/_SequentialTileCreator.java 2011-03-31 23:40:08 UTC (rev 22) +++ core/cache/_SequentialTileCreator.java 2011-04-04 21:48:28 UTC (rev 23) @@ -24,7 +24,6 @@ } public TileCollection create_tiles(TileCollection tiles, TileCollection tile_collection){ -System.out.println("TileCollection.create_tiles()"); TileCollection created_tiles = new TileCollection(); for (_Tile tile : tiles){ //for tile in tiles: @@ -53,4 +52,4 @@ -} +} \ No newline at end of file Modified: core/grid/Grid.java =================================================================== --- core/grid/Grid.java 2011-03-31 23:40:08 UTC (rev 22) +++ core/grid/Grid.java 2011-04-04 21:48:28 UTC (rev 23) @@ -12,7 +12,7 @@ public abstract class Grid { - public java.util.List<Integer> geodetic_epsg_codes = + public static java.util.List<Integer> geodetic_epsg_codes = java.util.Arrays.asList(new Integer[]{4326, 31466, 31467, 31468, 31469}); //public int[] tile_size = new int[]{256, 256}; Modified: core/grid/TileGrid.java =================================================================== --- core/grid/TileGrid.java 2011-03-31 23:40:08 UTC (rev 22) +++ core/grid/TileGrid.java 2011-04-04 21:48:28 UTC (rev 23) @@ -26,9 +26,9 @@ private double[] res = null; private double[] resolutions = null; private boolean is_geodetic = false; - private int levels; - private String res_type; - protected java.util.List<int[]> grid_sizes; + public int levels; //<-- flipped from private to public for the TileServiceGrid Class + public String res_type; //<-- flipped from private to public for the TileServiceGrid Class + public java.util.List<int[]> grid_sizes; //<-- flipped from protected to public for the TileServiceGrid Class private double stretch_factor = 1.15; @@ -114,7 +114,7 @@ this(epsg, null, tile_size, null, true, null); } - + //************************************************************************** //** _calc_grids //************************************************************************** @@ -340,7 +340,7 @@ * @param tiles ordered list of tiles * @return Returns the bbox of all tiles */ - private double[] _get_bbox(java.util.List<int[]> tiles){ + public double[] _get_bbox(java.util.List<int[]> tiles){ int[] ll = tiles.get(0); int[] ur = tiles.get(tiles.size()-1); //ur = tiles[-1] double[] pt0 = this._get_south_west_point(ll); @@ -369,10 +369,9 @@ private double[] _get_south_west_point(int[] tile_coord){ //x, y, z = tile_coord - int[] coord = tile_coord; - int x = coord[0]; - int y = coord[1]; - int z = coord[2]; + int x = tile_coord[0]; + int y = tile_coord[1]; + int z = tile_coord[2]; double res = this.resolution(z); double x0 = this.bbox[0] + x * res * this.tile_size[0]; @@ -405,5 +404,39 @@ double height = res * this.tile_size[1]; return new double[]{x0, y0, x0+width, y0+height}; } + + + //************************************************************************** + //** limit_tile + //************************************************************************** + /** Check if the "tile_coord" is in the grid. + * @return the "tile_coord" if it is within the "grid", otherwise null. + + >>> grid = TileGrid(epsg=900913) + >>> grid.limit_tile((-1, 0, 2)) == None + True + >>> grid.limit_tile((1, 2, 1)) == None + True + >>> grid.limit_tile((1, 2, 2)) + (1, 2, 2) + */ + + public int[] limit_tile(int[] tile_coord){ + + //x, y, z = tile_coord + int x = tile_coord[0]; + int y = tile_coord[1]; + int z = tile_coord[2]; + + int[] grid = this.grid_sizes.get(z); + //System.out.println(mapproxy.core.Python.cstr(tile_coord)); + //System.out.println(mapproxy.core.Python.cstr(grid)); + + if (z < 0 || z >= this.levels) + return null; + if (x < 0 || y < 0 || x >= grid[0] || y >= grid[1]) + return null; + return new int[]{x, y, z}; + } } \ No newline at end of file Modified: core/image/ImageTransformer.java =================================================================== --- core/image/ImageTransformer.java 2011-03-31 23:40:08 UTC (rev 22) +++ core/image/ImageTransformer.java 2011-04-04 21:48:28 UTC (rev 23) @@ -183,7 +183,8 @@ //System.out.println(y1 + " to " + y2 + " = " + (h)); - //System.out.println(src_bbox[0] + ", " + src_bbox[1] + ", " + src_bbox[2] + ", " + src_bbox[3]); + System.out.println(src_bbox[0] + ", " + src_bbox[1] + ", " + src_bbox[2] + ", " + src_bbox[3]); + System.out.println(dst_bbox[0] + ", " + dst_bbox[1] + ", " + dst_bbox[2] + ", " + dst_bbox[3]); Envelope2D envelope = new Envelope2D(this.src_srs.crs, src_bbox[0], src_bbox[1], w, h); Modified: server/RequestProcessor.java =================================================================== --- server/RequestProcessor.java 2011-03-31 23:40:08 UTC (rev 22) +++ server/RequestProcessor.java 2011-04-04 21:48:28 UTC (rev 23) @@ -14,7 +14,9 @@ import mapproxy.arcgis.client.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.zip.*; + //****************************************************************************** //** RequestProcessor //****************************************************************************** @@ -219,6 +221,10 @@ responseSent = false; } } + else if (path.contains("/tms/")){ + getTile(request, connection); + + } else{ responseSent = false; } @@ -258,9 +264,142 @@ } - + + //************************************************************************** + //** getTile + //************************************************************************** + /** Used to construct a response to a TMS Map request + */ + private void getTile(RequestHeader request, SocketChannel connection) throws IOException { + + + javaxt.utils.Date date = new javaxt.utils.Date(); + date.setTimeZone("GMT"); + + + javaxt.utils.URL url = new javaxt.utils.URL(request.getURL()); + System.out.println(url); + + + //Check whether this request is in the http cache + mapproxy.tms.TileRequest req = new mapproxy.tms.TileRequest(url.toString()); + String key = req.id(); + + String eTag = request.getProperty("if-none-match"); + String cacheControl = request.getProperty("cache-control"); + + if (cacheControl==null) cacheControl = ""; + if (cacheControl.equalsIgnoreCase("no-cache")==false && eTag!=null){ + + String val = null; + synchronized (httpCache){ + val = httpCache.get(key); + } + if (val!=null){ + if (val.equals(eTag)){ + + //Return 304 Response Code + StringBuffer header = new StringBuffer(); + header.append("HTTP/1.1 304 Not Modified\r\n"); + header.append("Date: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); + header.append("Server: " + serverName + "\r\n"); + header.append("ETag: " + eTag + "\r\n"); + header.append("\r\n"); + + System.out.println("304 Response!"); + //System.out.println(header); + byte[] response = header.toString().getBytes(); + java.nio.ByteBuffer output = java.nio.ByteBuffer.allocateDirect(response.length); + output.put(response); + output.flip(); + synchronized(connection) { + connection.write(output); + } + return; + } + } + + } + + + mapproxy.core.Service mapproxy = this.getMapProxy(); + + mapproxy.core.Layer layer = mapproxy.getLayers()[0]; + FileCache fileCache = (FileCache) layer.getParam("cache"); + TileGrid grid = (TileGrid) layer.getParam("grid"); + + mapproxy.tms.cache.TMSTileSource tms = new mapproxy.tms.cache.TMSTileSource(grid, url.toString()); + CacheManager cacheManager = new CacheManager(fileCache, tms); + Cache cache = new Cache(cacheManager, grid, true); + + String format = req.format; + + byte[] img; + try{ + req.tile = new mapproxy.tms.TileServiceGrid(grid).internal_tile_coord(req.tile, true); + img = new javaxt.io.File(cache.tile(req.tile).location).getBytes().toByteArray(); + } + catch(Exception e){ + img = new javaxt.io.Image(grid.tile_size[0], grid.tile_size[1]).getByteArray(format); + } + + + + + + + //Create a custom ETag + eTag = "W/\"" + img.length + "-" + date.getTime() + "\""; + + + //Write Response Header + StringBuffer header = new StringBuffer(); + header.append("HTTP/1.1 200 OK\r\n"); + header.append("Date: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); + header.append("Server: " + serverName + "\r\n"); + header.append("Content-Type: " + format + "\r\n"); + header.append("Content-Length: " + img.length + "\r\n"); + header.append("ETag: " + eTag + "\r\n"); + header.append("Last-Modified: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); //Sat, 23 Oct 2010 13:04:28 GMT + //header.append("Cache-Control: " + "max-age=" + (365*24*60*60) + "\r\n"); //vs "no-cache" + header.append("Accept-Ranges: bytes\r\n"); + header.append("Connection: Keep-Alive\r\n"); + + header.append("\r\n"); + + System.out.print("\r\n" + header.toString()); + + + //Convert the header into a byte array + byte[] hdr = header.toString().getBytes(); + + + //Create a buffer to write bytes to the socket + int bufferSize = img.length + hdr.length; + java.nio.ByteBuffer output = java.nio.ByteBuffer.allocateDirect(bufferSize); + + output.put(hdr); + output.put(img); + output.flip(); + synchronized(connection) { + connection.write(output); + } + + System.out.println("Completed writing bytes..."); + + //Update the http cache + synchronized (httpCache){ + httpCache.put(key, eTag); + } + + } + + + + + //************************************************************************** //** getMap //************************************************************************** /** Used to construct a response to a WMS GetMap request @@ -300,7 +439,7 @@ String val = null; synchronized (httpCache){ val = httpCache.get(key); - } + } if (val!=null){ if (val.equals(eTag)){ @@ -324,6 +463,7 @@ return; } } + } @@ -360,13 +500,15 @@ param.set("bbox", bbox); WMS111MapRequest req = new WMS111MapRequest(param, host); - req.params.size(new int[]{width, height}); - //req.params.set("format", format); + req.params.size(new int[]{width, height}); req.params.set("srs", srs); + + //if (format.equalsIgnoreCase("image/PNG24")) format = "jpeg"; //<-- This is crazy! If I return a 24 bit PNG, ArcMap doesn't display anything. If I return a JPEG, works like a champ if (!format.toLowerCase().startsWith("image/")) format = "image/" + format; - if (format.toUpperCase().endsWith("PNG24") && fileCache!=null) format = "image/png"; + if (format.equalsIgnoreCase("image/PNG24") && fileCache!=null) format = "image/png"; + format = "image/png"; req.params.set("format", format); String protocol = (String) layer.getParam("protocol"); @@ -400,8 +542,14 @@ } //Convert the image into a byte array + //byte[] img = new javaxt.io.File("/temp/ArcGIS/ExportImage.png").getBytes().toByteArray(); + //byte[] img = new javaxt.io.Image("/temp/ArcGIS/ExportImage.png").getByteArray("png"); byte[] img = image.getByteArray(format); + + + + //Create a custom ETag eTag = "W/\"" + img.length + "-" + date.getTime() + "\""; @@ -416,6 +564,12 @@ header.append("ETag: " + eTag + "\r\n"); header.append("Last-Modified: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); //Sat, 23 Oct 2010 13:04:28 GMT //header.append("Cache-Control: " + "max-age=" + (365*24*60*60) + "\r\n"); //vs "no-cache" + header.append("Accept-Ranges: bytes\r\n"); + header.append("Connection: Keep-Alive\r\n"); + + //header.append("Proxy-Connection: Keep-Alive\r\n"); + //header.append("Via: 1.1 SPATCFW003\r\n"); + header.append("\r\n"); System.out.print("\r\n" + header.toString()); @@ -436,6 +590,7 @@ connection.write(output); } + System.out.println("Completed writing bytes..."); //Update the http cache synchronized (httpCache){ @@ -754,17 +909,17 @@ if (body.substring(0,1).equals("<")){ String resultsNode = "Body"; //soap:Body - Document XMLDoc = DOM.createDocument(body); - NodeList Response = XMLDoc.getElementsByTagName(resultsNode); - if (Response!=null){ + Document xml = DOM.createDocument(body); + NodeList response = xml.getElementsByTagName(resultsNode); + if (response!=null){ //Special Case: Probably Missing Namespace in Soap.resultsNode - if (Response.getLength()==0) { + if (response.getLength()==0) { resultsNode = getResultsNode(body, resultsNode); - Response = XMLDoc.getElementsByTagName(resultsNode); + response = xml.getElementsByTagName(resultsNode); } - String msg = DOM.getNodeValue(Response.item(0)); + String msg = DOM.getNodeValue(response.item(0)); if (msg.contains("GetMessageVersion")){ System.out.println("GetMessageVersion"); rsp = arcgis.getMessageVersion().getBytes("UTF-8"); @@ -815,22 +970,47 @@ } else if (msg.contains("GetLegendInfo")){ System.out.println("GetLegendInfo"); - rsp = new javaxt.io.File("/temp/GetLegendInfo.xml").getText("UTF-8").getBytes("UTF-8"); + //rsp = new javaxt.io.File("/temp/GetLegendInfo.xml").getText("UTF-8").getBytes("UTF-8"); //rsp = arcgis.getLegendInfo().getBytes("UTF-8"); } else if (msg.contains("ExportMapImage")){ System.out.println("ExportMapImage"); - +new javaxt.io.File("/temp/ExportImage.xml").write(body, "UTF-8"); - String returnType = getNodeValue("ImageReturnType", XMLDoc); - String width = getNodeValue("ImageWidth", XMLDoc); - String height = getNodeValue("ImageHeight", XMLDoc); - String format = getNodeValue("ImageFormat", XMLDoc); + String returnType = getNodeValue("ImageReturnType", xml); + String width = getNodeValue("ImageWidth", xml); + String height = getNodeValue("ImageHeight", xml); + String format = getNodeValue("ImageFormat", xml); String layers = ""; - NodeList nodeList = XMLDoc.getElementsByTagName("LayerID"); + NodeList nodeList = xml.getElementsByTagName("LayerDescription"); for (int i=0; i<nodeList.getLength(); i++ ) { + if (nodeList.item(i).getNodeType()==1){ + String layerID = ""; + String isVisible = ""; + NodeList layerAttributes = nodeList.item(i).getChildNodes(); + for (int j=0; j<layerAttributes.getLength(); j++ ) { + Node layerAttribute = layerAttributes.item(j); + if (layerAttribute.getNodeType()==1){ + if (layerAttribute.getNodeName().equalsIgnoreCase("LayerID")){ + layerID = javaxt.xml.DOM.getNodeValue(layerAttribute).trim(); + } + else if (layerAttribute.getNodeName().equalsIgnoreCase("Visible")){ + isVisible = javaxt.xml.DOM.getNodeValue(layerAttribute).trim(); + } + } + } + if (layerID.length()>0){ + if (isVisible.equalsIgnoreCase("true")){ + layers+=layerID + ","; + } + } + } + } + /* + NodeList nodeList = xml.getElementsByTagName("LayerID"); + for (int i=0; i<nodeList.getLength(); i++ ) { if (nodeList.item(i).getNodeType()==1){ String layer = javaxt.xml.DOM.getNodeValue(nodeList.item(i)).trim(); if (layer.length()>0){ @@ -838,16 +1018,17 @@ } } } + */ if (layers.endsWith(",")){ layers = layers.substring(0, layers.length()-1); } - String minX = getNodeValue("XMin", XMLDoc); - String minY = getNodeValue("YMin", XMLDoc); - String maxX = getNodeValue("XMax", XMLDoc); - String maxY = getNodeValue("YMax", XMLDoc); + String minX = getNodeValue("XMin", xml); + String minY = getNodeValue("YMin", xml); + String maxX = getNodeValue("XMax", xml); + String maxY = getNodeValue("YMax", xml); String bbox = minX + "," + minY + "," + maxX + "," + maxY; - String wkt = getNodeValue("WKT", XMLDoc); + String wkt = getNodeValue("WKT", xml); //Update the request URL to point to the WMS endpoint @@ -855,12 +1036,13 @@ wms = wms.substring(0, wms.indexOf(request.getURL().getPath())) + "/wms"; - //Get the ExportImage SOAP Response + //Generate ExportImage SOAP Response rsp = arcgis.getExportMapImageResponse(new javaxt.utils.URL(wms), layers, bbox, wkt, width, height, format, returnType).getBytes("UTF-8"); -/* - * - * msg = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tns=\"http://www.esri.com/schemas/ArcGIS/9.0\">" + msg; + + /* + //Redirect request to ArcGIS Server (Debug Use Only) + msg = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tns=\"http://www.esri.com/schemas/ArcGIS/9.0\">" + msg; msg += "</soap:Envelope>"; javaxt.http.Request req = new javaxt.http.Request("http://services.arcgisonline.com/ArcGIS/services/USA_Topo_Maps/MapServer"); @@ -870,17 +1052,16 @@ req.setHeader("SOAPAction", "\"\""); req.write(msg); - javaxt.http.Response response = req.getResponse(); - System.out.println(response); - String xml = response.getText("UTF-8"); - System.out.println(xml); - System.out.println("\r\n"); - //rsp = xml.getBytes("UTF-8"); - //url = new javaxt.utils.URL(getNodeValue("ImageURL", DOM.createDocument(xml))); - format = "jpeg"; - rsp = arcgis.getExportMapImageResponse(url, layers, bbox, "4326", width, height, format, returnType).getBytes("UTF-8"); -*/ + String txt = req.getResponse().getText("UTF-8"); + String img = getNodeValue("ImageURL", DOM.createDocument(txt)); + System.out.println(img); + txt = txt.replace(img, "<![CDATA[http://localhost:9080/wms?height=597&bbox=319898.427173501,-238695.385822158,1250996.29959783,693964.731354558&request=GetMap&width=596&layers=0&service=WMS&srs=EPSG:2781&format=image/jpeg&version=1.1.1&date="+ new java.util.Date().getTime() +"]]>"); + rsp = txt.getBytes("UTF-8"); + new javaxt.io.File("/temp/ExportImageResponse.xml").write(rsp); + */ + + } else{ System.out.println( msg ); @@ -895,6 +1076,20 @@ rsp = arcgis.getWSDL().getBytes("UTF-8"); } + + + //GZIP Compress the response + boolean gzip = request.getProperty("Accept-Encoding").toLowerCase().contains("gzip"); + if (gzip){ + try { + rsp = gzip(rsp); + } + catch (IOException e) { + gzip = false; + } + } + + javaxt.utils.Date date = new javaxt.utils.Date(); date.setTimeZone("GMT"); @@ -912,6 +1107,9 @@ header.append("ETag: " + eTag + "\r\n"); header.append("Last-Modified: " + date.toString("EEE, dd MMM yyyy HH:mm:ss zzz") + "\r\n"); //Sat, 23 Oct 2010 13:04:28 GMT //header.append("Cache-Control: " + "max-age=" + (365*24*60*60) + "\r\n"); //vs "no-cache" + if (gzip){ + header.append("Content-Encoding: gzip\r\n"); + } header.append("\r\n"); System.out.println(header); @@ -955,4 +1153,18 @@ } + + private byte[] gzip(byte[] img) throws IOException { + + System.out.println(img.length + " bytes"); + java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream(img.length); + GZIPOutputStream out = new GZIPOutputStream(bos); + out.write(img); + out.finish(); + out.close(); + img = bos.toByteArray(); + System.out.println(img.length + " bytes"); + return img; + } + } \ No newline at end of file Added: tms/TMSClient.java =================================================================== --- tms/TMSClient.java (rev 0) +++ tms/TMSClient.java 2011-04-04 21:48:28 UTC (rev 23) @@ -0,0 +1,37 @@ +package mapproxy.tms; + +//****************************************************************************** +//** TMSClient Class +//****************************************************************************** +/** + * Enter class description here + * + ******************************************************************************/ + +public class TMSClient { + + public String url; + private String format = "png"; + + //************************************************************************** + //** Constructor + //************************************************************************** + /** Creates a new instance of TMSClient. */ + + public TMSClient(String url, String format){ + if (!url.endsWith("/")) url+="/"; + if (format.toLowerCase().startsWith("image/")) format = format.substring(6); + this.url = url; + this.format = format; + } + + public javaxt.io.Image get_tile(int[] tile_coord){ + //x, y, z = tile_coord + int x = tile_coord[0]; + int y = tile_coord[1]; + int z = tile_coord[2]; + return new javaxt.http.Request(url + z + "/" + x + "/" + y + "." + format).getResponse().getImage(); + } + + +} \ No newline at end of file Added: tms/TileRequest.java =================================================================== --- tms/TileRequest.java (rev 0) +++ tms/TileRequest.java 2011-04-04 21:48:28 UTC (rev 23) @@ -0,0 +1,52 @@ +package mapproxy.tms; + +//****************************************************************************** +//** TileRequest Class +//****************************************************************************** +/** + * + * + ******************************************************************************/ + +public class TileRequest { + + public String layer; + public String format = "png"; + public int[] tile; + + //************************************************************************** + //** Constructor + //************************************************************************** + /** Creates a new instance of TileRequest. Assumes the url ends with a tms + * request. Example: "/layer/z/x/y.format" + */ + public TileRequest(String url){ + + format = url.substring(url.lastIndexOf(".")+1); + url = url.substring(0, url.lastIndexOf(".")); + int y = cint(url.substring(url.lastIndexOf("/")+1)); + url = url.substring(0, url.lastIndexOf("/")); + int x = cint(url.substring(url.lastIndexOf("/")+1)); + url = url.substring(0, url.lastIndexOf("/")); + int z = cint(url.substring(url.lastIndexOf("/")+1)); + url = url.substring(0, url.lastIndexOf("/")); + tile = new int[]{x,y,z}; + layer = url.substring(url.lastIndexOf("/")+1); + + System.out.println("format: " + format); + System.out.println("layer: " + layer); + System.out.println("tile: " + mapproxy.core.Python.cstr(tile)); + } + + public String id(){ + int x = tile[0]; + int y = tile[1]; + int z = tile[2]; + return "/" + layer + "/" + z + "/" + x + "/" + y + "." + format; + } + + private int cint(String s){ + return javaxt.utils.string.cint(s); + } + +} Added: tms/TileServiceGrid.java =================================================================== --- tms/TileServiceGrid.java (rev 0) +++ tms/TileServiceGrid.java 2011-04-04 21:48:28 UTC (rev 23) @@ -0,0 +1,158 @@ +package mapproxy.tms; +import mapproxy.core.Python; +import mapproxy.core.grid.Grid; +import mapproxy.core.grid.TileGrid; + +//****************************************************************************** +//** TileServiceGrid Class +//****************************************************************************** +/** + * Wraps a "TileGrid" and adds some "TileService" specific methods. + * + ******************************************************************************/ + +public class TileServiceGrid { //extends TileGrid + + private boolean _skip_first_level = true; + private boolean _skip_odd_level = false; + private TileGrid grid; + private String profile; + private String srs_name; + + //************************************************************************** + //** Constructor + //************************************************************************** + /** Creates a new instance of TileServiceGrid. */ + + public TileServiceGrid(TileGrid grid){ + this.grid = grid; + if (this.grid.res_type.equals(TileGrid.RES_TYPE_GLOBAL) || + this.grid.res_type.equals(TileGrid.RES_TYPE_SQRT2)){ + if (this.grid.srs.equals(900913)){ + this.profile = "global-mercator"; + this.srs_name = "OSGEO:41001"; // as required by TMS 1.0.0 + this._skip_first_level = true; + } + else if (this.grid.srs.isGeographic()){ + this.profile = "global-geodetic"; + this.srs_name = this.grid.srs.toString(); //"EPSG:4326"; + this._skip_first_level = true; + } + } + else{ + this.profile = "local"; + this.srs_name = this.grid.srs.toString(); + this._skip_first_level = false; + } + + this._skip_odd_level = false; + if (this.grid.res_type.equalsIgnoreCase(TileGrid.RES_TYPE_SQRT2)) + this._skip_odd_level = true; + } + + + //************************************************************************** + //** internal_level + //************************************************************************** + /** returns the internal level */ + + public int internal_level(int level){ + + if (this._skip_first_level){ + level += 1; + if (this._skip_odd_level) + level += 1; + } + if (this._skip_odd_level) + level *= 2; + return level; + } + + + //************************************************************************** + //** bbox + //************************************************************************** + /** + * @return the bbox of all tiles of the first level + */ + public double[] bbox(){ + int first_level = this.internal_level(0); + int[] grid_size = this.grid.grid_sizes.get(first_level); + java.util.List<int[]> tiles = new java.util.ArrayList<int[]>(); + tiles.add(new int[]{0, 0, first_level}); + tiles.add(new int[]{grid_size[0]-1, grid_size[1]-1, first_level}); + return this.grid._get_bbox(tiles); + } + + + + //************************************************************************** + //** tile_sets + //************************************************************************** + /** Get all public tile sets for this layer. + * @return the order and resolution of each tile set + */ + public java.util.List<double[]> tile_sets(){ + + java.util.List<double[]> tile_sets = new java.util.ArrayList<double[]>(); //tile_sets = [] + int num_levels = this.grid.levels; + int start = 0; + int step = 1; + if (this._skip_first_level){ + if (this._skip_odd_level) + start = 2; + else + start = 1; + } + if (this._skip_odd_level) + step = 2; + /* + for order, level in enumerate(range(start, num_levels, step)): + tile_sets.append((order, self.grid.resolutions[level])) + */ + int order = 0; + for (int level : (Python.range(start, num_levels, step)) ){ + tile_sets.add(new double[]{order, this.grid.resolution(level)}); + } + + return tile_sets; + } + + + //************************************************************************** + //** internal_tile_coord + //************************************************************************** + /** Converts public tile coords to internal tile coords. + * @param tile_coord the public tile coord + * @param use_profiles True if the tile service supports global + profiles (see `mapproxy.core.server.TileServer`) + */ + public int[] internal_tile_coord(int[] tile_coord, boolean use_profiles){ + + //x, y, z = tile_coord + int x = tile_coord[0]; + int y = tile_coord[1]; + int z = tile_coord[2]; + + if (z < 0) + return null; + + //Added hack for OpenLayers + if (this.grid.srs.isGeographic()){ + //z *= 2; + } + + if (use_profiles && this._skip_first_level) + z += 1; + + if (this._skip_odd_level) + z *= 2; + + //x = x+2; + //y = y+1; + //z = 4; + System.out.println("z: " + z); + return this.grid.limit_tile(new int[]{x, y, z}); + } + +} \ No newline at end of file Added: tms/TileServiceLayer.java =================================================================== --- tms/TileServiceLayer.java (rev 0) +++ tms/TileServiceLayer.java 2011-04-04 21:48:28 UTC (rev 23) @@ -0,0 +1,86 @@ +package mapproxy.tms; +import mapproxy.core.layer.*; +//import mapproxy.wms.request.WMSRequest; +import mapproxy.core.cache.Cache; + +//****************************************************************************** +//** TileServiceLayer Class +//****************************************************************************** +/** + * Enter class description here + * + ******************************************************************************/ + +public class TileServiceLayer extends Layer { + + private LayerMetaData md; + private Cache cache; + private TileServiceGrid grid; + + + //************************************************************************** + //** Constructor + //************************************************************************** + /** Creates a new instance of TileServiceLayer. */ + + public TileServiceLayer(LayerMetaData md, Cache cache){ + if (md==null) + this.md = new LayerMetaData(); + this.md = md; + this.cache = cache; + this.grid = new TileServiceGrid(cache.grid); + } + + + + + protected double[] _bbox(){ + return this.grid.bbox(); + } +/* + private SRS _srs(){ + return this.grid.srs; + } + + + + public String format(){ + _mime_class, format, _options = split_mime_type(self.format_mime_type) + return format; + } +*/ + + public String format_mime_type(){ + return this.md.get("format", "image/png"); + } + + private int[] _internal_tile_coord(TileRequest tile_request, boolean use_profiles){ //use_profiles=False + int[] tile_coord = this.grid.internal_tile_coord(tile_request.tile, use_profiles); + if (tile_coord == null){ + //raise RequestError('The requested tile is outside the bounding box' + // ' of the tile map.', request=tile_request) + } + return tile_coord; + } + + /* + public TileResponse render(TileRequest tile_request, boolean use_profiles){ //use_profiles=False + //if (tile_request.format != self.format){ + //raise RequestError('invalid format (%s). this tile set only supports (%s)' + // % (tile_request.format, self.format), request=tile_request) + //} + int[] tile_coord = this._internal_tile_coord(tile_request, use_profiles); + System.out.println(mapproxy.core.Python.cstr(tile_coord)); + //try{ + //System.out.println(this.cache.tile(tile_coord).toString()); + //return new TileResponse(this.cache.tile(tile_coord)); + return null; + //} + //catch(Exception e){//except TileCacheError, e: + //log.error(e) + //raise RequestError(e.message, request=tile_request, internal=True) + //} + } + */ + +} Added: tms/cache/TMSTileSource.java =================================================================== --- tms/cache/TMSTileSource.java (rev 0) +++ tms/cache/TMSTileSource.java 2011-04-04 21:48:28 UTC (rev 23) @@ -0,0 +1,132 @@ +package mapproxy.tms.cache; +import mapproxy.tms.*; +import mapproxy.core.cache.*; +import mapproxy.core.grid.*; +import mapproxy.core.image.*; +//import mapproxy.wms.request.*; +import mapproxy.core.Python; + +//****************************************************************************** +//** TMSTileSource Class +//****************************************************************************** +/** + * This `TileSource` retrieves new tiles from a TMS server. + * + ******************************************************************************/ + +public class TMSTileSource extends TileSource { + + + private int meta_buffer = 0; + private int[] meta_size = new int[]{2, 2}; + private TileGrid grid; + private String format; + private MetaGrid meta_grid; + + private TMSClient tms_client; + private boolean inverse = false; + + + //************************************************************************** + //** Constructor + //************************************************************************** + /** Creates a new instance of TMSTileSource. */ + + public TMSTileSource(TileGrid grid, String url, String format, boolean inverse){ + + + this.init(lock_dir); + + this.grid = grid; + if (format==null){ + format = "image/png"; //clients[0].request_template.params.format; + } + this.format = format; + this.meta_grid = new MetaGrid(grid, meta_size, meta_buffer); + + + this.tms_client = new TMSClient(url, format); + this.inverse = inverse; + + } + + public TMSTileSource(TileGrid grid, String url){ + this(grid, url, "png", false); + } + + + + public String id(){ + return this.tms_client.url; + } + + + //************************************************************************** + //** create_tile + //************************************************************************** + /** Retrieve the requested `tile`. + */ + /* + public create_tile(tile, _tile_map){ + + + if (this.inverse) + coord = this.grid.flip_tile_coord(tile.coord); + else + coord = tile.coord; + try{ + buf = StringIO(self.tms_client.get_tile(coord).read()) + tile.source = ImageSource(buf) + except HTTPClientError, e: + reraise_exception(TileSourceError(e.message), sys.exc_info()) + return [tile]; + + } + */ + + + @Override + //************************************************************************** + //** create_tile + //************************************************************************** + /** Retrieve the metatile that contains the requested tile and save all + * tiles. + * @param tile_map tile_collection + */ + + public TileCollection create_tile(_Tile tile, TileCollection tile_map){ + + + System.out.println("TileCollection create_tile:"); + System.out.println(Python.cstr(tile.coord)); + + for (_Tile t : tile_map){ + System.out.println(Python.cstr(t.coord)); + } + return tile_map; + + //req.tile = tms_grid.internal_tile_coord(req.tile, true); + + //javaxt.io.Image meta_tile = _get_meta_tile(tile); + //Generator<TileCoordinate> tiles = meta_grid.tiles(tile.coord); + //return _split_meta_tile(meta_tile, tiles, tile_map); + } + + + + //************************************************************************** + //** _get_meta_tile + //************************************************************************** + /* + private javaxt.io.Image _get_meta_tile(_Tile tile){ + double[] bbox = meta_grid.meta_bbox(tile.coord); + int[] size = meta_grid.tile_size(tile.coord[2]); + + + mapproxy.tms.TileServiceGrid g = new mapproxy.tms.TileServiceGrid(grid); + tms_request.tile = g.internal_tile_coord(tms_request.tile, true); + + } + */ + +} Deleted: wms/server/Capabilities.java =================================================================== --- wms/server/Capabilities.java 2011-03-31 23:40:08 UTC (rev 22) +++ wms/server/Capabilities.java 2011-04-04 21:48:28 UTC (rev 23) @@ -1,46 +0,0 @@ -package mapproxy.wms.server; - -//****************************************************************************** -//** Capabilities Class -//****************************************************************************** -/** - * Renders WMS capabilities documents. - * - ******************************************************************************/ - -public class Capabilities { - - - //************************************************************************** - //** Constructor - //************************************************************************** - /** Creates a new instance of Capabilities. */ - - public Capabilities(){ - - } - - /* - def __init__(self, server_md, layer_md): - self.service = server_md - self.layers = layer_md - - def render(self, _map_request): - return self._render_template(_map_request.capabilities_template) - - def _render_template(self, template): - template = env.get_template(template) - server_... [truncated message content] |
From: <pbo...@us...> - 2011-03-31 23:40:14
|
Revision: 22 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=22&view=rev Author: pborissow Date: 2011-03-31 23:40:08 +0000 (Thu, 31 Mar 2011) Log Message: ----------- Bug fixes related to reprojecting wms requests. Still need to fix ArcGIS MapServer responses for non geographic image requests. Modified Paths: -------------- arcgis/server/MapServer.java core/SRS.java server/RequestProcessor.java Modified: arcgis/server/MapServer.java =================================================================== --- arcgis/server/MapServer.java 2011-03-31 14:13:27 UTC (rev 21) +++ arcgis/server/MapServer.java 2011-03-31 23:40:08 UTC (rev 22) @@ -1,6 +1,11 @@ package mapproxy.arcgis.server; import mapproxy.core.Service; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.MathTransform; +import org.geotools.referencing.operation.DefaultCoordinateOperationFactory; +import org.geotools.referencing.CRS; + //****************************************************************************** //** MapService Class //****************************************************************************** @@ -150,15 +155,34 @@ } - public String getExportMapImageResponse(javaxt.utils.URL url, String layers, String bbox, String srs, String width, String height, String format, String returnType){ - //System.out.println(returnType); + + //************************************************************************** + //** getExportMapImageResponse + //************************************************************************** + /** Contructs an XML response to an ExportMap image request. The document + * contains a link to a WMS service. + */ + public String getExportMapImageResponse(javaxt.utils.URL url, String layers, String bbox, String wkt, String width, String height, String format, String returnType){ + + String srs = "EPSG:4326"; + try{ + CoordinateReferenceSystem crs = CRS.parseWKT(wkt); + srs = CRS.lookupIdentifier( crs, true ); + //System.out.println(crs.getName()); + //System.out.println("SRS: " + srs); + } + catch(Exception e){ + e.printStackTrace(); + } + + url.setParameter("BBOX", bbox); url.setParameter("SERVICE", "WMS"); url.setParameter("REQUEST", "GetMap"); url.setParameter("VERSION", "1.1.1"); - url.setParameter("SRS", "EPSG:" + srs); + url.setParameter("SRS", srs); url.setParameter("WIDTH", width); url.setParameter("HEIGHT", height); url.setParameter("LAYERS", layers); @@ -180,26 +204,16 @@ String[] arr = bbox.split(","); xml.append("<XMin>" + arr[0] + "</XMin><YMin>" + arr[1] + "</YMin><XMax>" + arr[2] + "</XMax><YMax>" + arr[3] + "</YMax>"); - xml.append("<SpatialReference xsi:type=\"tns:GeographicCoordinateSystem\">"); - xml.append("<WKT>" + wgs84.replace("\"", """) + "</WKT>"); - /* - xml.append("<XOrigin>-399.99999999999989</XOrigin>"); - xml.append("<YOrigin>-399.99999999999989</YOrigin>"); - xml.append("<XYScale>11258999068426.24</XYScale>"); - xml.append("<ZOrigin>-100000</ZOrigin>"); - xml.append("<ZScale>10000</ZScale>"); - xml.append("<MOrigin>-100000</MOrigin>"); - xml.append("<MScale>10000</MScale>"); - xml.append("<XYTolerance>8.9831528411952199e-009</XYTolerance>"); - xml.append("<ZTolerance>0.00020000000000000001</ZTolerance>"); - xml.append("<MTolerance>0.00020000000000000001</MTolerance>"); - xml.append("<HighPrecision>true</HighPrecision>"); - xml.append("<LeftLongitude>-180</LeftLongitude>"); - xml.append("<WKID>" + srs + "</WKID>"); - * - */ - - xml.append("</SpatialReference>"); + if (srs.equalsIgnoreCase("EPSG:4326")){ + xml.append("<SpatialReference xsi:type=\"tns:GeographicCoordinateSystem\">"); + xml.append("<WKT>" + wgs84.replace("\"", """) + "</WKT>"); + xml.append("</SpatialReference>"); + } + else{ + xml.append("<SpatialReference xsi:type=\"tns:ProjectedCoordinateSystem\">"); + xml.append("<WKT>" + wkt.replace("\"", """) + "</WKT>"); + xml.append("</SpatialReference>"); + } xml.append("</Extent>"); @@ -230,4 +244,4 @@ } -} +} \ No newline at end of file Modified: core/SRS.java =================================================================== --- core/SRS.java 2011-03-31 14:13:27 UTC (rev 21) +++ core/SRS.java 2011-03-31 23:40:08 UTC (rev 22) @@ -28,7 +28,7 @@ int epsg = 4326; try{ - get_epsg_num(srs_code); + epsg = get_epsg_num(srs_code); } catch(Exception e){ e.printStackTrace(); Modified: server/RequestProcessor.java =================================================================== --- server/RequestProcessor.java 2011-03-31 14:13:27 UTC (rev 21) +++ server/RequestProcessor.java 2011-03-31 23:40:08 UTC (rev 22) @@ -362,7 +362,7 @@ WMS111MapRequest req = new WMS111MapRequest(param, host); req.params.size(new int[]{width, height}); //req.params.set("format", format); - req.params.set("srs", srs); + req.params.set("srs", srs); if (!format.toLowerCase().startsWith("image/")) format = "image/" + format; @@ -533,10 +533,16 @@ String url = request.getURL().toString(); if (url.contains("?")) url = url.substring(0, url.indexOf("?")); + if (!url.endsWith("/")) url += "/"; + if (!url.toLowerCase().endsWith("/wms/")) url += "wms/"; //Get Capabilities - System.out.println(getMapProxy().getURL() + " <-- MapProxy URL"); - byte[] rsp = getMapProxy().getCapabilities().toString("WMS").getBytes(); + + mapproxy.core.Service service = getMapProxy(); + String orgURL = service.getURL(); + service.setURL(url); + byte[] rsp = service.getCapabilities().toString("WMS").getBytes(); + service.setURL(orgURL); //Create a custom ETag @@ -820,8 +826,7 @@ String width = getNodeValue("ImageWidth", XMLDoc); String height = getNodeValue("ImageHeight", XMLDoc); String format = getNodeValue("ImageFormat", XMLDoc); - if (format.startsWith("esriImage")) format = format.substring("esriImage".length()); - if (format.equalsIgnoreCase("PNG24")) format = "jpeg"; //<-- This is crazy! If I return a 24 bit PNG, ArcMap doesn't display anything. If I return a JPEG, works like a champ + String layers = ""; NodeList nodeList = XMLDoc.getElementsByTagName("LayerID"); @@ -842,14 +847,17 @@ String maxX = getNodeValue("XMax", XMLDoc); String maxY = getNodeValue("YMax", XMLDoc); String bbox = minX + "," + minY + "," + maxX + "," + maxY; - - String wkt = getNodeValue("WKT", XMLDoc); //<-- Need to convert this into an EPSG + String wkt = getNodeValue("WKT", XMLDoc); + //Update the request URL to point to the WMS endpoint + String wms = request.getURL().toString(); + wms = wms.substring(0, wms.indexOf(request.getURL().getPath())) + "/wms"; - javaxt.utils.URL url = new javaxt.utils.URL(request.getURL()); - rsp = arcgis.getExportMapImageResponse(url, layers, bbox, "4326", width, height, format, returnType).getBytes("UTF-8"); + //Get the ExportImage SOAP Response + rsp = arcgis.getExportMapImageResponse(new javaxt.utils.URL(wms), layers, bbox, wkt, width, height, format, returnType).getBytes("UTF-8"); + /* * * msg = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tns=\"http://www.esri.com/schemas/ArcGIS/9.0\">" + msg; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-03-31 14:13:36
|
Revision: 21 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=21&view=rev Author: pborissow Date: 2011-03-31 14:13:27 +0000 (Thu, 31 Mar 2011) Log Message: ----------- Removed references to the SRSCache Modified Paths: -------------- Main.java core/Capabilities.java core/SRS.java core/cache/Cache.java core/grid/MetaGrid.java core/grid/TileGrid.java core/image/ImageTransformer.java core/request/RequestParams.java server/HttpServer.java server/RequestProcessor.java wms/client/WMSClient.java Removed Paths: ------------- core/SRSCache.java Modified: Main.java =================================================================== --- Main.java 2011-03-29 11:38:16 UTC (rev 20) +++ Main.java 2011-03-31 14:13:27 UTC (rev 21) @@ -43,7 +43,11 @@ */ - + + + + + String url = "http://localhost:6277/cgi-bin/mapserv.exe?map=/data/world.map&" + "layers=grid,polboundaries&" + @@ -57,10 +61,11 @@ //url = "http://data1.geoposer.com:443/server/services/request.php?jname=/wms.img&service=WMS&srs=EPSG:4326&width=683&styles=&height=330&bbox=-107.05227272727272,40.75,-103.94772727272728,42.25&request=GetMap&layers=osm&version=1.1.1&format=image/png"; - testCache(url); + //testCache(url); + //testSRS(); - //startServer(args); + startServer(args); //testWebServices(); //testArcWebServices(); @@ -69,7 +74,57 @@ } + private void testSRS(){ + /* + + >>> srs1 = SRS(4326) + >>> srs2 = SRS(900913) + >>> [str(round(x, 5)) for x in srs1.transform_to(srs2, (8.22, 53.15))] + ['915046.21432', '7010792.20171'] + >>> srs1.transform_to(srs1, (8.25, 53.5)) + (8.25, 53.5) + >>> [(str(round(x, 5)), str(round(y, 5))) for x, y in + ... srs1.transform_to(srs2, [(8.2, 53.1), (8.22, 53.15), (8.3, 53.2)])] + ... #doctest: +NORMALIZE_WHITESPACE + [('912819.8245', '7001516.67745'), + ('915046.21432', '7010792.20171'), + ('923951.77358', '7020078.53264')] + + */ + mapproxy.core.SRS srs1 = new mapproxy.core.SRS(4326); + mapproxy.core.SRS srs2 = new mapproxy.core.SRS(900913); + + java.util.ArrayList<mapproxy.core.Point> points = new java.util.ArrayList<mapproxy.core.Point>(); + //points.add(new mapproxy.core.Point(53.15, 8.22)); + points.add(new mapproxy.core.Point(8.22, 53.15)); + points = srs1.transform_to(srs2, points); + for (mapproxy.core.Point point : points){ + System.out.println(point); + } + + points = new java.util.ArrayList<mapproxy.core.Point>(); + points.add(new mapproxy.core.Point(915046.21432, 7010792.20171)); + points = srs2.transform_to(srs1, points); + for (mapproxy.core.Point point : points){ + System.out.println(point); + } + + + //967478.5103, 110223.1030, 2749590.4261, 740927.1811 + + srs2 = new mapproxy.core.SRS(2238); + points = new java.util.ArrayList<mapproxy.core.Point>(); + points.add(new mapproxy.core.Point(967478.5103, 110223.1030)); + points.add(new mapproxy.core.Point(2749590.4261, 740927.1811)); + points = srs2.transform_to(srs1, points); + for (mapproxy.core.Point point : points){ + System.out.println(point); + } + + } + + private void testWebServices() throws Exception { String url = "http://services.arcgisonline.com/ArcGIS/services/USA_Topo_Maps/MapServer"; Modified: core/Capabilities.java =================================================================== --- core/Capabilities.java 2011-03-29 11:38:16 UTC (rev 20) +++ core/Capabilities.java 2011-03-31 14:13:27 UTC (rev 21) @@ -69,7 +69,7 @@ StringBuffer xml = new StringBuffer(); xml.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\"?>"); - xml.append("<!DOCTYPE WMT_MS_Capabilities SYSTEM \"http://schemas.opengeospatial.net//wms/1.1.1/capabilities_1_1_1.dtd\" ["); + xml.append("<!DOCTYPE WMT_MS_Capabilities SYSTEM \"http://schemas.opengeospatial.net/wms/1.1.1/capabilities_1_1_1.dtd\" ["); xml.append(" <!ELEMENT VendorSpecificCapabilities EMPTY>"); xml.append(" ]>"); xml.append("<WMT_MS_Capabilities version=\"1.1.1\">"); Modified: core/SRS.java =================================================================== --- core/SRS.java 2011-03-29 11:38:16 UTC (rev 20) +++ core/SRS.java 2011-03-31 14:13:27 UTC (rev 21) @@ -26,7 +26,13 @@ public SRS(String srs_code){ - int epsg = get_epsg_num(srs_code); + int epsg = 4326; + try{ + get_epsg_num(srs_code); + } + catch(Exception e){ + e.printStackTrace(); + } this.proj = "epsg:" + epsg; Deleted: core/SRSCache.java =================================================================== --- core/SRSCache.java 2011-03-29 11:38:16 UTC (rev 20) +++ core/SRSCache.java 2011-03-31 14:13:27 UTC (rev 21) @@ -1,57 +0,0 @@ -package mapproxy.core; - -//****************************************************************************** -//** SRSCache Class -//****************************************************************************** -/** - * Enter class description here - * - ******************************************************************************/ - -public class SRSCache { - - - private static java.util.HashMap<String, SRS> _srs_cache = new java.util.HashMap<String, SRS>(); - - - //************************************************************************** - //** Constructor - //************************************************************************** - /** Creates a new instance of SRS. */ - - private SRSCache(){} - - public static SRS getSRS(Object srs_code) { - - - String _srs_code = _clean_srs_code(srs_code); - - if (_srs_cache.containsKey(_srs_code)){ - return _srs_cache.get(srs_code); - } - else{ - SRS srs = new SRS(_srs_code); - _srs_cache.put(_srs_code, srs);//_srs_cache[srs_code] = srs; - return srs; - } - - } - - //************************************************************************** - //** _clean_srs_code - //************************************************************************** - /** - * _clean_srs_code(4326) returns 'EPSG:4326' - * _clean_srs_code('31466') returns 'EPSG:31466' - * _clean_srs_code('crs:84') returns 'CRS:84' - */ - private static String _clean_srs_code(Object code){ - if (code instanceof String && ((String) code).contains(":")){ - return ((String) code).toUpperCase(); - } - else{ - return "EPSG:" + code; - } - } - -} \ No newline at end of file Modified: core/cache/Cache.java =================================================================== --- core/cache/Cache.java 2011-03-29 11:38:16 UTC (rev 20) +++ core/cache/Cache.java 2011-03-31 14:13:27 UTC (rev 21) @@ -34,8 +34,6 @@ this.grid = grid; this.transparent = transparent; - System.out.println("srs is null = " + this.grid.srs==null); - } public Cache(CacheManager cache_mgr, TileGrid grid){ @@ -144,4 +142,4 @@ } -} +} \ No newline at end of file Modified: core/grid/MetaGrid.java =================================================================== --- core/grid/MetaGrid.java 2011-03-29 11:38:16 UTC (rev 20) +++ core/grid/MetaGrid.java 2011-03-31 14:13:27 UTC (rev 21) @@ -172,8 +172,8 @@ @Override public void run() { - System.out.println(y0+(meta_size[1]-1) + "," + (y0-1) + "," + -1); - System.out.println(x0 + "," + (x0+meta_size[0])); + //System.out.println(y0+(meta_size[1]-1) + "," + (y0-1) + "," + -1); + //System.out.println(x0 + "," + (x0+meta_size[0])); int i = 0; for (int y : (Python.range(y0+(meta_size[1]-1), y0-1, -1)) ){ int j = 0; Modified: core/grid/TileGrid.java =================================================================== --- core/grid/TileGrid.java 2011-03-29 11:38:16 UTC (rev 20) +++ core/grid/TileGrid.java 2011-03-31 14:13:27 UTC (rev 21) @@ -1,5 +1,4 @@ package mapproxy.core.grid; -import mapproxy.core.SRSCache; import mapproxy.core.SRS; import mapproxy.core.Python; @@ -55,7 +54,7 @@ public TileGrid(int epsg, double[] bbox, int[] tile_size, String res, boolean is_geodetic, Integer levels){ - this.srs = SRSCache.getSRS(epsg); + this.srs = new SRS(epsg); //SRSCache.getSRS(epsg); this.tile_size = tile_size; this.is_geodetic = is_geodetic; Modified: core/image/ImageTransformer.java =================================================================== --- core/image/ImageTransformer.java 2011-03-29 11:38:16 UTC (rev 20) +++ core/image/ImageTransformer.java 2011-03-31 14:13:27 UTC (rev 21) @@ -173,17 +173,17 @@ double w = 0; if (x1>x2) w = x1-x2; else w = x2-x1; - System.out.println(x1 + " to " + x2 + " = " + (w)); + //System.out.println(x1 + " to " + x2 + " = " + (w)); double y1 = y(src_bbox[1]); double y2 = y(src_bbox[3]); double h = 0; if (y1>y2) h = y1-y2; else h = y2-y1; - System.out.println(y1 + " to " + y2 + " = " + (h)); + //System.out.println(y1 + " to " + y2 + " = " + (h)); - System.out.println(src_bbox[0] + ", " + src_bbox[1] + ", " + src_bbox[2] + ", " + src_bbox[3]); + //System.out.println(src_bbox[0] + ", " + src_bbox[1] + ", " + src_bbox[2] + ", " + src_bbox[3]); Envelope2D envelope = new Envelope2D(this.src_srs.crs, src_bbox[0], src_bbox[1], w, h); Modified: core/request/RequestParams.java =================================================================== --- core/request/RequestParams.java 2011-03-29 11:38:16 UTC (rev 20) +++ core/request/RequestParams.java 2011-03-31 14:13:27 UTC (rev 21) @@ -128,7 +128,7 @@ n.set(key, value, false, true); //n.set(key, value, unpack=True) } } - System.out.println(n.get("bbox", null)); + //System.out.println(n.get("bbox", null)); return n; /* new = self.copy() Modified: server/HttpServer.java =================================================================== --- server/HttpServer.java 2011-03-29 11:38:16 UTC (rev 20) +++ server/HttpServer.java 2011-03-31 14:13:27 UTC (rev 21) @@ -119,7 +119,7 @@ RequestProcessor.processRequest(request); } else{ - System.err.println(key.toString()); + //System.err.println(key.toString()); } } catch (IOException e) { Modified: server/RequestProcessor.java =================================================================== --- server/RequestProcessor.java 2011-03-29 11:38:16 UTC (rev 20) +++ server/RequestProcessor.java 2011-03-31 14:13:27 UTC (rev 21) @@ -535,6 +535,7 @@ if (url.contains("?")) url = url.substring(0, url.indexOf("?")); //Get Capabilities + System.out.println(getMapProxy().getURL() + " <-- MapProxy URL"); byte[] rsp = getMapProxy().getCapabilities().toString("WMS").getBytes(); Modified: wms/client/WMSClient.java =================================================================== --- wms/client/WMSClient.java 2011-03-29 11:38:16 UTC (rev 20) +++ wms/client/WMSClient.java 2011-03-31 14:13:27 UTC (rev 21) @@ -1,7 +1,5 @@ package mapproxy.wms.client; import mapproxy.wms.request.*; -import mapproxy.core.SRS; -import mapproxy.core.SRSCache; //****************************************************************************** //** WMSClient This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-03-29 11:38:22
|
Revision: 20 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=20&view=rev Author: pborissow Date: 2011-03-29 11:38:16 +0000 (Tue, 29 Mar 2011) Log Message: ----------- Added reprojection support. Mapproxy can now respond to wms requests in a variety of projections. Modified Paths: -------------- core/SRS.java core/image/ImageTransformer.java wms/cache/WMSTileSource.java Modified: core/SRS.java =================================================================== --- core/SRS.java 2011-03-28 11:17:02 UTC (rev 19) +++ core/SRS.java 2011-03-29 11:38:16 UTC (rev 20) @@ -1,27 +1,9 @@ package mapproxy.core; -//import mapproxy.core.Python; - -import org.geotools.coverage.grid.*; -import org.geotools.geometry.Envelope2D; -import org.geotools.referencing.CRS; -import org.geotools.coverage.processing.Operations; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.MathTransform; import org.geotools.referencing.operation.DefaultCoordinateOperationFactory; -//import org.geotools.metadata.iso.extent.GeographicBoundingBoxImpl; -import org.opengis.referencing.crs.*; - -import org.geotools.coverage.grid.GridCoverage2D; -import org.geotools.coverage.grid.GridCoverageFactory; -import org.geotools.coverage.grid.GridEnvelope2D; -import org.geotools.coverage.grid.GridGeometry2D; -import org.geotools.coverage.processing.Operations; -import org.geotools.factory.Hints; -import org.geotools.geometry.Envelope2D; -import org.geotools.image.ImageWorker; import org.geotools.referencing.CRS; -import org.opengis.geometry.Envelope; -import org.opengis.referencing.operation.MathTransform; - //****************************************************************************** //** SRS Class //****************************************************************************** @@ -33,9 +15,8 @@ public class SRS { - private java.util.HashMap<String, String> proj_init; - //private String srs_code; private String proj; + public CoordinateReferenceSystem crs; //<-- GeoTools CRS (Added to support ImageTransformer) //************************************************************************** @@ -44,24 +25,18 @@ /** Create a new SRS with the given `srs_code` code. */ public SRS(String srs_code){ - // http://trac.openlayers.org/wiki/SphericalMercator - proj_init = new java.util.HashMap<String, String>(); - proj_init.put("EPSG:900913", - "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 " + - "+lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m " + - "+nadgrids=@null +no_defs"); - proj_init.put("CRS:84", "epsg:4326"); + int epsg = get_epsg_num(srs_code); + this.proj = "epsg:" + epsg; - //this.srs_code = srs_code; - String init = proj_init.get(srs_code); - if (init==null){ - int epsg_num = get_epsg_num(srs_code); - this.proj = "epsg:" + epsg_num; + //Set GeoTools CRS (Added to support ImageTransformer) + try{ + if (epsg == 4326) crs = CRS.decode(this.proj, true); + else crs = CRS.decode(this.proj); } - else{ - this.proj = init; + catch(Exception e){ + e.printStackTrace(); } } @@ -89,9 +64,12 @@ public static int get_epsg_num(Object epsg_code){ if (epsg_code instanceof String){ - if (epsg_code.toString().toLowerCase().startsWith("epsg:")){ - return cint(epsg_code.toString().split(":")[1]); + String epsg = (String) epsg_code; + epsg = epsg.trim(); + if (epsg.toLowerCase().startsWith("epsg:")){ + epsg = epsg.substring(5); } + return cint(epsg); } return cint(epsg_code); } @@ -103,7 +81,7 @@ //** transform_to //************************************************************************** /** - :type points: ``(x, y)`` or ``[(x1, y1), (x2, y2), …]`` + :type points: ``(x, y)`` or ``[(x1, y1), (x2, y2), etc]`` >>> srs1 = SRS(4326) >>> srs2 = SRS(900913) @@ -129,14 +107,10 @@ try{ //Define Input CoordinateReferenceSystem - CoordinateReferenceSystem sourceCS; - if (this.equals(4326)) sourceCS = CRS.decode(this.proj, true); - else sourceCS = CRS.decode(this.proj); - + CoordinateReferenceSystem sourceCS = this.crs; + //Define Output CoordinateReferenceSystem - CoordinateReferenceSystem targetCS; - if (other_srs.equals(4326)) targetCS = CRS.decode(other_srs.proj, true); - else targetCS = CRS.decode(other_srs.proj); + CoordinateReferenceSystem targetCS = other_srs.crs; //Initialize Transformation DefaultCoordinateOperationFactory trFactory = new DefaultCoordinateOperationFactory(); @@ -246,7 +220,7 @@ </pre> */ public double[] align_bbox(double[] bbox){ - if (this.equals("EPSG:4326")){ //if (this.srs_code.equalsIgnoreCase("EPSG:4326")){ + if (this.equals("EPSG:4326")){ double delta = 0.00000001; //(minx, miny, maxx, maxy) = bbox double minx = bbox[0]; Modified: core/image/ImageTransformer.java =================================================================== --- core/image/ImageTransformer.java 2011-03-28 11:17:02 UTC (rev 19) +++ core/image/ImageTransformer.java 2011-03-29 11:38:16 UTC (rev 20) @@ -4,6 +4,14 @@ import mapproxy.core.Python; import mapproxy.core.SRS; +import java.awt.image.BufferedImage; +import java.awt.image.RenderedImage; + +import org.geotools.coverage.grid.GridCoverage2D; +import org.geotools.coverage.grid.GridCoverageFactory; +import org.geotools.coverage.processing.Operations; +import org.geotools.geometry.Envelope2D; + //****************************************************************************** //** ImageTransformer Class //****************************************************************************** @@ -156,6 +164,48 @@ /** Do a 'real' transformation with a transformed mesh (see above). */ private javaxt.io.Image _transform(javaxt.io.Image src_img, double[] src_bbox, int[] dst_size, double[] dst_bbox){ + //Use GeoTools to reproject src_img to the output projection. + try{ + + //Compute geodetic w/h in degrees (used to specify the Envelope2D) + double x1 = x(src_bbox[0]); + double x2 = x(src_bbox[2]); + double w = 0; + if (x1>x2) w = x1-x2; + else w = x2-x1; + System.out.println(x1 + " to " + x2 + " = " + (w)); + + double y1 = y(src_bbox[1]); + double y2 = y(src_bbox[3]); + double h = 0; + if (y1>y2) h = y1-y2; + else h = y2-y1; + System.out.println(y1 + " to " + y2 + " = " + (h)); + + + System.out.println(src_bbox[0] + ", " + src_bbox[1] + ", " + src_bbox[2] + ", " + src_bbox[3]); + + Envelope2D envelope = + new Envelope2D(this.src_srs.crs, src_bbox[0], src_bbox[1], w, h); + + GridCoverage2D gc2d = + new GridCoverageFactory().create("BMImage", src_img.getBufferedImage(), envelope); + + GridCoverage2D gc2dProj = + (GridCoverage2D)Operations.DEFAULT.resample(gc2d, this.dst_srs.crs); + + + src_img = new javaxt.io.Image(convertRenderedImage(gc2dProj.getRenderedImage())); + src_img.resize(dst_size[0], dst_size[1], false); + + } + catch (Exception e){ + e.printStackTrace(); + } + + + /* + //Start port of original python code... src_bbox = this.src_srs.align_bbox(src_bbox); dst_bbox = this.dst_srs.align_bbox(dst_bbox); int[] src_size = new int[]{src_img.getWidth(), src_img.getHeight()}; //src_img.size @@ -164,8 +214,9 @@ SRS.transf to_src_px = SRS.make_lin_transf(src_bbox, src_quad); SRS.transf to_dst_w = SRS.make_lin_transf(dst_quad, dst_bbox); - //meshes = []; - /* + + //This segment still needs to be ported to java + meshes = []; def dst_quad_to_src(quad): src_quad = [] for dst_px in [(quad[0], quad[1]), (quad[0], quad[3]), @@ -203,9 +254,56 @@ return quad, src_quad; } */ + + //************************************************************************** + //** X + //************************************************************************** + /** Used to convert longitude to pixel coordinates */ + private double x(double pt){ + pt += 180; + return pt; + } + //************************************************************************** + //** Y + //************************************************************************** + /** Used to convert latitude to pixel coordinates */ + + private double y(double pt){ + pt = -pt; + if (pt<=0) pt = 90 + -pt; + else pt = 90 - pt; + + pt = 180-pt; + return pt; + } + + public BufferedImage convertRenderedImage(RenderedImage img) { + if (img instanceof BufferedImage) { + return (BufferedImage)img; + } + java.awt.image.ColorModel cm = img.getColorModel(); + int width = img.getWidth(); + int height = img.getHeight(); + java.awt.image.WritableRaster raster = + cm.createCompatibleWritableRaster(width, height); + boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); + java.util.Hashtable properties = new java.util.Hashtable(); + String[] keys = img.getPropertyNames(); + if (keys!=null) { + for (int i = 0; i < keys.length; i++) { + properties.put(keys[i], img.getProperty(keys[i])); + } + } + BufferedImage result = new BufferedImage(cm, raster, isAlphaPremultiplied, properties); + img.copyData(raster); + return result; + } + + + //************************************************************************** //** _no_transformation_needed //************************************************************************** /** @@ -298,4 +396,4 @@ private int cint(double d){ return javaxt.utils.string.cint(d); } -} +} \ No newline at end of file Modified: wms/cache/WMSTileSource.java =================================================================== --- wms/cache/WMSTileSource.java 2011-03-28 11:17:02 UTC (rev 19) +++ wms/cache/WMSTileSource.java 2011-03-29 11:38:16 UTC (rev 20) @@ -150,7 +150,7 @@ WMSMapRequest request = new WMSMapRequest(); request.params.bbox(bbox); request.params.size(size); - request.params.set("srs", grid.srs.toString()); //<-- Had to add this. Not sure if this was in the original python code... + request.params.set("srs", grid.srs.toString()); //<-- Had to add this. Not sure why this isn't in the original python code... javaxt.io.Image img = client.get_map(request); responses.add(img); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-03-28 11:17:08
|
Revision: 19 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=19&view=rev Author: pborissow Date: 2011-03-28 11:17:02 +0000 (Mon, 28 Mar 2011) Log Message: ----------- Fixed bug in the _get_meta_tile method. Request srs was not being set to the grid srs. Modified Paths: -------------- core/Point.java wms/cache/WMSTileSource.java Modified: core/Point.java =================================================================== --- core/Point.java 2011-03-28 10:51:48 UTC (rev 18) +++ core/Point.java 2011-03-28 11:17:02 UTC (rev 19) @@ -26,7 +26,7 @@ @Override public String toString(){ - return x + "," + y; + return x + ", " + y; } @Override Modified: wms/cache/WMSTileSource.java =================================================================== --- wms/cache/WMSTileSource.java 2011-03-28 10:51:48 UTC (rev 18) +++ wms/cache/WMSTileSource.java 2011-03-28 11:17:02 UTC (rev 19) @@ -150,6 +150,7 @@ WMSMapRequest request = new WMSMapRequest(); request.params.bbox(bbox); request.params.size(size); + request.params.set("srs", grid.srs.toString()); //<-- Had to add this. Not sure if this was in the original python code... javaxt.io.Image img = client.get_map(request); responses.add(img); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-03-28 10:51:54
|
Revision: 18 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=18&view=rev Author: pborissow Date: 2011-03-28 10:51:48 +0000 (Mon, 28 Mar 2011) Log Message: ----------- Added logic to flip coordinate axis in case of EPSG:4326 Modified Paths: -------------- core/SRS.java Modified: core/SRS.java =================================================================== --- core/SRS.java 2011-03-27 15:51:15 UTC (rev 17) +++ core/SRS.java 2011-03-28 10:51:48 UTC (rev 18) @@ -124,22 +124,35 @@ return points; } + + //Use GeoTools to transform the points try{ - //Use GeoTools to transform the points - CoordinateReferenceSystem sourceCS = CRS.decode(this.proj); - CoordinateReferenceSystem targetCS = CRS.decode(other_srs.proj); + //Define Input CoordinateReferenceSystem + CoordinateReferenceSystem sourceCS; + if (this.equals(4326)) sourceCS = CRS.decode(this.proj, true); + else sourceCS = CRS.decode(this.proj); + + //Define Output CoordinateReferenceSystem + CoordinateReferenceSystem targetCS; + if (other_srs.equals(4326)) targetCS = CRS.decode(other_srs.proj, true); + else targetCS = CRS.decode(other_srs.proj); + + //Initialize Transformation DefaultCoordinateOperationFactory trFactory = new DefaultCoordinateOperationFactory(); MathTransform mt = trFactory.createOperation(sourceCS, targetCS).getMathTransform(); boolean flipPoints = !sourceCS.getCoordinateSystem().getAxis(0).getDirection().equals(targetCS.getCoordinateSystem().getAxis(0).getDirection()); - + + + //Convert the points int i = 0; for (Point point : points){ double[] pt = new double[2]; pt[0] = point.x; pt[1] = point.y; + mt.transform(pt, 0, pt, 0, 1); if (flipPoints){ point = new Point(pt[1],pt[0]); @@ -477,6 +490,9 @@ else if (obj instanceof String){ return this.proj.equalsIgnoreCase( new SRS((String) obj).proj ); } + else if (obj instanceof Integer){ + return this.proj.equalsIgnoreCase( new SRS((Integer) obj).proj ); + } else{ return this.proj.equalsIgnoreCase( new SRS(obj + "").proj ); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pbo...@us...> - 2011-03-27 15:51:23
|
Revision: 17 http://mapproxy.svn.sourceforge.net/mapproxy/?rev=17&view=rev Author: pborissow Date: 2011-03-27 15:51:15 +0000 (Sun, 27 Mar 2011) Log Message: ----------- Implemented coordinate transformation in the SRS class (see transform_to method). Introduced dependency on GeoTools. Modified Paths: -------------- Main.java core/Point.java core/SRS.java wms/cache/WMSTileSource.java Modified: Main.java =================================================================== --- Main.java 2011-03-16 10:48:55 UTC (rev 16) +++ Main.java 2011-03-27 15:51:15 UTC (rev 17) @@ -9,10 +9,6 @@ import mapproxy.config.Config; import mapproxy.server.HttpServer; - -import org.w3c.dom.*; -import javaxt.xml.DOM; - //****************************************************************************** //** Main Application //****************************************************************************** @@ -43,21 +39,28 @@ Config.base_config().set("cache.max_tile_limit", 500); Config.base_config().set("image.resampling_method", "bicubic"); - /* - String url = "http://localhost:6277/cgi-bin/mapserv.exe?map=/data/world.map&height=256&bbox=-95.625,-5.625,-78.75,11.25&layers=grid,polboundaries&request=GetMap&width=256&service=WMS&styles=&srs=EPSG:4326&format=image/png&version=1.1.1"; - //url = args[0]; - url = "https://ewdemo.spadac.com/earthwhere/cgi-bin/mapserv.exe?map=D:\\Program%20Files\\Earthwhere\\Data\\BaseMap\\world.map&styles=&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=grid,polboundaries,hydro,drylakes&STYLES=&SRS=EPSG:4326&BBOX=-81.97626683405774,41.4175387977413,-81.9755288715459,41.417918443195376&WIDTH=692&HEIGHT=356&FORMAT=image/jpeg"; - url = "https://ewdemo.spadac.com/earthwhere/cgi-bin/mapserv.exe?map=D:\\Program%20Files\\Earthwhere\\Data\\BaseMap\\world.map&styles=&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=grid,polboundaries,hydro,drylakes&STYLES=&SRS=EPSG:4326&BBOX=-110.0912132306527,3.28651685393259,-65.86384294912258,26.039325842696634&WIDTH=692&HEIGHT=356&FORMAT=image/jpeg"; - //testWMSClient(url); - url = "http://ewdemo.spadac.com/earthwhere/wms?&height=332&bbox=-81.99628476172565,41.404924571118,-81.95369308905316,41.42562799033801&layers=NextMap_ORRI&request=GetMap&width=683&service=WMS&styles=&srs=EPSG:4326&format=image/png&version=1.1.1"; - url = "http://data1.geoposer.com:443/server/services/request.php?jname=/wms.img&service=WMS&srs=EPSG:4326&width=683&styles=&height=330&bbox=-107.05227272727272,40.75,-103.94772727272728,42.25&request=GetMap&layers=osm&version=1.1.1&format=image/png"; + */ + + String url = + "http://localhost:6277/cgi-bin/mapserv.exe?map=/data/world.map&" + + "layers=grid,polboundaries&" + + "request=GetMap&service=WMS&version=1.1.1&" + + //"srs=EPSG:3395&" + //3857, 3395, 900913 (Mercator Projections) + //"bbox=-25,63,-13,67&" + //"bbox=-95.625,-5.625,-78.75,11.25&" + + "srs=EPSG:2238&" + + "bbox=967478.5103,110223.1030,2749590.4261,740927.1811&"+ + "height=256&width=256&" + + "format=image/png"; + + //url = "http://data1.geoposer.com:443/server/services/request.php?jname=/wms.img&service=WMS&srs=EPSG:4326&width=683&styles=&height=330&bbox=-107.05227272727272,40.75,-103.94772727272728,42.25&request=GetMap&layers=osm&version=1.1.1&format=image/png"; + testCache(url); - */ + - startServer(args); + //startServer(args); //testWebServices(); //testArcWebServices(); Modified: core/Point.java =================================================================== --- core/Point.java 2011-03-16 10:48:55 UTC (rev 16) +++ core/Point.java 2011-03-27 15:51:15 UTC (rev 17) @@ -24,4 +24,19 @@ this.y = y; } + @Override + public String toString(){ + return x + "," + y; + } + + @Override + public boolean equals(Object obj){ + if (obj instanceof Point){ + Point point = (Point) obj; + return (this.x == point.x && this.y == point.y); + } + return false; + } + + } Modified: core/SRS.java =================================================================== --- core/SRS.java 2011-03-16 10:48:55 UTC (rev 16) +++ core/SRS.java 2011-03-27 15:51:15 UTC (rev 17) @@ -1,6 +1,27 @@ package mapproxy.core; -import mapproxy.core.Python; +//import mapproxy.core.Python; +import org.geotools.coverage.grid.*; +import org.geotools.geometry.Envelope2D; +import org.geotools.referencing.CRS; +import org.geotools.coverage.processing.Operations; +import org.geotools.referencing.operation.DefaultCoordinateOperationFactory; +//import org.geotools.metadata.iso.extent.GeographicBoundingBoxImpl; +import org.opengis.referencing.crs.*; + +import org.geotools.coverage.grid.GridCoverage2D; +import org.geotools.coverage.grid.GridCoverageFactory; +import org.geotools.coverage.grid.GridEnvelope2D; +import org.geotools.coverage.grid.GridGeometry2D; +import org.geotools.coverage.processing.Operations; +import org.geotools.factory.Hints; +import org.geotools.geometry.Envelope2D; +import org.geotools.image.ImageWorker; +import org.geotools.referencing.CRS; +import org.opengis.geometry.Envelope; + +import org.opengis.referencing.operation.MathTransform; + //****************************************************************************** //** SRS Class //****************************************************************************** @@ -13,7 +34,7 @@ private java.util.HashMap<String, String> proj_init; - private String srs_code; + //private String srs_code; private String proj; @@ -32,7 +53,7 @@ proj_init.put("CRS:84", "epsg:4326"); - this.srs_code = srs_code; + //this.srs_code = srs_code; String init = proj_init.get(srs_code); if (init==null){ @@ -54,9 +75,9 @@ } - + //************************************************************************** //** get_epsg_num //************************************************************************** @@ -99,7 +120,45 @@ */ public java.util.ArrayList<Point> transform_to(SRS other_srs, java.util.ArrayList<Point> points){ + if (other_srs.equals(this)){ + return points; + } + try{ + + //Use GeoTools to transform the points + CoordinateReferenceSystem sourceCS = CRS.decode(this.proj); + CoordinateReferenceSystem targetCS = CRS.decode(other_srs.proj); + DefaultCoordinateOperationFactory trFactory = new DefaultCoordinateOperationFactory(); + MathTransform mt = trFactory.createOperation(sourceCS, targetCS).getMathTransform(); + + boolean flipPoints = !sourceCS.getCoordinateSystem().getAxis(0).getDirection().equals(targetCS.getCoordinateSystem().getAxis(0).getDirection()); + + int i = 0; + for (Point point : points){ + double[] pt = new double[2]; + pt[0] = point.x; + pt[1] = point.y; + + mt.transform(pt, 0, pt, 0, 1); + if (flipPoints){ + point = new Point(pt[1],pt[0]); + } + else{ + point = new Point(pt[0],pt[1]); + } + + points.set(i, point); + i++; + } + + + } + catch (Exception e){ + e.printStackTrace(); + } + + /* if self == other_srs: @@ -140,8 +199,7 @@ */ public double[] transform_bbox_to(SRS other_srs, double[] bbox, int with_points){ //with_points=16 - if (this.equals(other_srs)) - return bbox; + if (this.equals(other_srs)) return bbox; bbox = this.align_bbox(bbox); java.util.ArrayList<Point> points = generate_envelope_points(bbox, with_points); java.util.ArrayList<Point> transf_pts = this.transform_to(other_srs, points); @@ -175,7 +233,7 @@ </pre> */ public double[] align_bbox(double[] bbox){ - if (this.srs_code.equalsIgnoreCase("EPSG:4326")){ + if (this.equals("EPSG:4326")){ //if (this.srs_code.equalsIgnoreCase("EPSG:4326")){ double delta = 0.00000001; //(minx, miny, maxx, maxy) = bbox double minx = bbox[0]; @@ -398,6 +456,7 @@ } + @Override //************************************************************************** //** equals //************************************************************************** @@ -409,16 +468,34 @@ >>> SRS(4326) == SRS(900913) False */ - public boolean equals(Object obj){ + public boolean equals(Object obj){ if (obj instanceof SRS){ + return this.proj.equalsIgnoreCase(((SRS) obj).proj); //return self.proj.srs == other.proj.srs - return true; } - return false; + else if (obj instanceof String){ + return this.proj.equalsIgnoreCase( new SRS((String) obj).proj ); + } + else{ + return this.proj.equalsIgnoreCase( new SRS(obj + "").proj ); + } + + //return false; } + @Override + //************************************************************************** + //** toString + //************************************************************************** + /** Used to return the srs_code used to instantiate this class. */ + + public String toString(){ + return this.proj; + } + + private static int cint(Object obj){ return Integer.valueOf((String) obj).intValue(); } Modified: wms/cache/WMSTileSource.java =================================================================== --- wms/cache/WMSTileSource.java 2011-03-16 10:48:55 UTC (rev 16) +++ wms/cache/WMSTileSource.java 2011-03-27 15:51:15 UTC (rev 17) @@ -141,10 +141,10 @@ private javaxt.io.Image _get_meta_tile(_Tile tile){ double[] bbox = meta_grid.meta_bbox(tile.coord); - System.out.println("tile.coord: " + mapproxy.core.Python.cstr(tile.coord)); - System.out.println("bbox: " + mapproxy.core.Python.cstr(bbox)); int[] size = meta_grid.tile_size(tile.coord[2]); - System.out.println("size: " + mapproxy.core.Python.cstr(size)); + //System.out.println("tile.coord: " + mapproxy.core.Python.cstr(tile.coord)); + //System.out.println("bbox: " + mapproxy.core.Python.cstr(bbox)); + //System.out.println("size: " + mapproxy.core.Python.cstr(size)); java.util.List<javaxt.io.Image> responses = new java.util.ArrayList<javaxt.io.Image>(); for (WMSClient client : this.clients){ //for client in self.clients: WMSMapRequest request = new WMSMapRequest(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |