1 /******************************************************************************
2  * $Id$
3  *
4  * Project:  MapServer
5  * Purpose:  MapCache tile caching support file: high level configuration file parser
6  * Author:   Thomas Bonfort and the MapServer team.
7  *
8  ******************************************************************************
9  * Copyright (c) 1996-2011 Regents of the University of Minnesota.
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies of this Software or works derived from this Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  *****************************************************************************/
29 
30 #include "mapcache.h"
31 #include <apr_file_info.h>
32 #include <apr_strings.h>
33 #include <apr_file_io.h>
34 #include <math.h>
35 
mapcache_configuration_parse(mapcache_context * ctx,const char * filename,mapcache_cfg * config,int cgi)36 void mapcache_configuration_parse(mapcache_context *ctx, const char *filename, mapcache_cfg *config, int cgi)
37 {
38   char *url;
39 
40   mapcache_configuration_parse_xml(ctx,filename,config);
41 
42   GC_CHECK_ERROR(ctx);
43 
44   /* if we were suppplied with an onlineresource, make sure it ends with a / */
45   if(NULL != (url = (char*)apr_table_get(config->metadata,"url"))) {
46     char *urlend = url + strlen(url)-1;
47     if(*urlend != '/') {
48       url = apr_pstrcat(ctx->pool,url,"/",NULL);
49       apr_table_setn(config->metadata,"url",url);
50     }
51   }
52 }
53 
mapcache_configuration_post_config(mapcache_context * ctx,mapcache_cfg * config)54 void mapcache_configuration_post_config(mapcache_context *ctx, mapcache_cfg *config)
55 {
56   apr_hash_index_t *cachei = apr_hash_first(ctx->pool,config->caches);
57   while(cachei) {
58     mapcache_cache *cache;
59     const void *key;
60     apr_ssize_t keylen;
61     apr_hash_this(cachei,&key,&keylen,(void**)&cache);
62     cache->configuration_post_config(ctx,cache,config);
63     GC_CHECK_ERROR(ctx);
64     cachei = apr_hash_next(cachei);
65   }
66 }
67 
68 
mapcache_configuration_create(apr_pool_t * pool)69 mapcache_cfg* mapcache_configuration_create(apr_pool_t *pool)
70 {
71   mapcache_grid *grid;
72   int i;
73   double wgs84_resolutions[18]= {
74     0.703125000000000,
75     0.351562500000000,
76     0.175781250000000,
77     8.78906250000000e-2,
78     4.39453125000000e-2,
79     2.19726562500000e-2,
80     1.09863281250000e-2,
81     5.49316406250000e-3,
82     2.74658203125000e-3,
83     1.37329101562500e-3,
84     6.86645507812500e-4,
85     3.43322753906250e-4,
86     1.71661376953125e-4,
87     8.58306884765625e-5,
88     4.29153442382812e-5,
89     2.14576721191406e-5,
90     1.07288360595703e-5,
91     5.36441802978516e-6
92   };
93 
94   double google_resolutions[19] = {
95     156543.0339280410,
96     78271.51696402048,
97     39135.75848201023,
98     19567.87924100512,
99     9783.939620502561,
100     4891.969810251280,
101     2445.984905125640,
102     1222.992452562820,
103     611.4962262814100,
104     305.7481131407048,
105     152.8740565703525,
106     76.43702828517624,
107     38.21851414258813,
108     19.10925707129406,
109     9.554628535647032,
110     4.777314267823516,
111     2.388657133911758,
112     1.194328566955879,
113     0.5971642834779395
114   };
115 
116 
117 
118 
119   mapcache_extent wgs84_extent= {-180,-90,180,90};
120   mapcache_extent google_extent= {-20037508.3427892480,-20037508.3427892480,20037508.3427892480,20037508.3427892480};
121   double unitwidth,unitheight;
122 
123   mapcache_cfg *cfg = (mapcache_cfg*)apr_pcalloc(pool, sizeof(mapcache_cfg));
124   cfg->caches = apr_hash_make(pool);
125   cfg->sources = apr_hash_make(pool);
126   cfg->tilesets = apr_hash_make(pool);
127   cfg->grids = apr_hash_make(pool);
128   cfg->image_formats = apr_hash_make(pool);
129   cfg->metadata = apr_table_make(pool,3);
130   cfg->rulesets = apr_hash_make(pool);
131 
132   mapcache_configuration_add_image_format(cfg,
133           mapcache_imageio_create_png_format(pool,"PNG",MAPCACHE_COMPRESSION_FAST),
134           "PNG");
135   mapcache_configuration_add_image_format(cfg,
136           mapcache_imageio_create_png_q_format(pool,"PNG8",MAPCACHE_COMPRESSION_FAST,256),
137           "PNG8");
138   mapcache_configuration_add_image_format(cfg,
139           mapcache_imageio_create_jpeg_format(pool,"JPEG",90,MAPCACHE_PHOTOMETRIC_YCBCR,MAPCACHE_OPTIMIZE_YES),
140           "JPEG");
141   mapcache_configuration_add_image_format(cfg,
142           mapcache_imageio_create_mixed_format(pool,"mixed",
143                     mapcache_configuration_get_image_format(cfg,"PNG"),
144                     mapcache_configuration_get_image_format(cfg,"JPEG"), 255),
145           "mixed");
146   cfg->default_image_format = mapcache_configuration_get_image_format(cfg,"mixed");
147   cfg->reporting = MAPCACHE_REPORT_MSG;
148 
149   grid = mapcache_grid_create(pool);
150   grid->name = apr_pstrdup(pool,"WGS84");
151   apr_table_add(grid->metadata,"title","GoogleCRS84Quad");
152   apr_table_add(grid->metadata,"wellKnownScaleSet","urn:ogc:def:wkss:OGC:1.0:GoogleCRS84Quad");
153   apr_table_add(grid->metadata,"profile","global-geodetic");
154   grid->srs = apr_pstrdup(pool,"EPSG:4326");
155   grid->unit = MAPCACHE_UNIT_DEGREES;
156   grid->tile_sx = grid->tile_sy = 256;
157   grid->nlevels = 18;
158   grid->extent = wgs84_extent;
159   grid->levels = (mapcache_grid_level**)apr_pcalloc(pool,
160                  grid->nlevels*sizeof(mapcache_grid_level*));
161   for(i=0; i<grid->nlevels; i++) {
162     mapcache_grid_level *level = (mapcache_grid_level*)apr_pcalloc(pool,sizeof(mapcache_grid_level));
163     level->resolution = wgs84_resolutions[i];
164     unitheight = grid->tile_sy * level->resolution;
165     unitwidth = grid->tile_sx * level->resolution;
166 
167     level->maxy = ceil((grid->extent.maxy-grid->extent.miny - 0.01* unitheight)/unitheight);
168     level->maxx = ceil((grid->extent.maxx-grid->extent.minx - 0.01* unitwidth)/unitwidth);
169     grid->levels[i] = level;
170   }
171   mapcache_configuration_add_grid(cfg,grid,"WGS84");
172 
173   grid = mapcache_grid_create(pool);
174   grid->name = apr_pstrdup(pool,"GoogleMapsCompatible");
175   grid->srs = apr_pstrdup(pool,"EPSG:3857");
176   APR_ARRAY_PUSH(grid->srs_aliases,char*) = apr_pstrdup(pool,"EPSG:900913");
177   apr_table_add(grid->metadata,"title","GoogleMapsCompatible");
178   apr_table_add(grid->metadata,"profile","global-mercator");
179   apr_table_add(grid->metadata,"wellKnownScaleSet","urn:ogc:def:wkss:OGC:1.0:GoogleMapsCompatible");
180   grid->tile_sx = grid->tile_sy = 256;
181   grid->nlevels = 19;
182   grid->unit = MAPCACHE_UNIT_METERS;
183   grid->extent = google_extent;
184   grid->levels = (mapcache_grid_level**)apr_pcalloc(pool,
185                  grid->nlevels*sizeof(mapcache_grid_level*));
186   for(i=0; i<grid->nlevels; i++) {
187     mapcache_grid_level *level = (mapcache_grid_level*)apr_pcalloc(pool,sizeof(mapcache_grid_level));
188     level->resolution = google_resolutions[i];
189     unitheight = grid->tile_sy * level->resolution;
190     unitwidth = grid->tile_sx * level->resolution;
191 
192     level->maxy = ceil((grid->extent.maxy-grid->extent.miny - 0.01* unitheight)/unitheight);
193     level->maxx = ceil((grid->extent.maxx-grid->extent.minx - 0.01* unitwidth)/unitwidth);
194     grid->levels[i] = level;
195   }
196   mapcache_configuration_add_grid(cfg,grid,"GoogleMapsCompatible");
197 
198   grid = mapcache_grid_create(pool);
199   grid->name = apr_pstrdup(pool,"g");
200   grid->srs = apr_pstrdup(pool,"EPSG:900913");
201   APR_ARRAY_PUSH(grid->srs_aliases,char*) = apr_pstrdup(pool,"EPSG:3857");
202   apr_table_add(grid->metadata,"title","GoogleMapsCompatible");
203   apr_table_add(grid->metadata,"profile","global-mercator");
204   apr_table_add(grid->metadata,"wellKnownScaleSet","urn:ogc:def:wkss:OGC:1.0:GoogleMapsCompatible");
205   grid->tile_sx = grid->tile_sy = 256;
206   grid->nlevels = 19;
207   grid->unit = MAPCACHE_UNIT_METERS;
208   grid->extent = google_extent;
209   grid->levels = (mapcache_grid_level**)apr_pcalloc(pool,
210                  grid->nlevels*sizeof(mapcache_grid_level*));
211   for(i=0; i<grid->nlevels; i++) {
212     mapcache_grid_level *level = (mapcache_grid_level*)apr_pcalloc(pool,sizeof(mapcache_grid_level));
213     level->resolution = google_resolutions[i];
214     unitheight = grid->tile_sy * level->resolution;
215     unitwidth = grid->tile_sx * level->resolution;
216 
217     level->maxy = ceil((grid->extent.maxy-grid->extent.miny - 0.01* unitheight)/unitheight);
218     level->maxx = ceil((grid->extent.maxx-grid->extent.minx - 0.01* unitwidth)/unitwidth);
219     grid->levels[i] = level;
220   }
221   mapcache_configuration_add_grid(cfg,grid,"g");
222 
223 
224   cfg->loglevel = MAPCACHE_WARN;
225   cfg->autoreload = 0;
226 
227   return cfg;
228 }
229 
mapcache_configuration_get_source(mapcache_cfg * config,const char * key)230 mapcache_source *mapcache_configuration_get_source(mapcache_cfg *config, const char *key)
231 {
232   return (mapcache_source*)apr_hash_get(config->sources, (void*)key, APR_HASH_KEY_STRING);
233 }
234 
mapcache_configuration_get_cache(mapcache_cfg * config,const char * key)235 mapcache_cache *mapcache_configuration_get_cache(mapcache_cfg *config, const char *key)
236 {
237   return (mapcache_cache*)apr_hash_get(config->caches, (void*)key, APR_HASH_KEY_STRING);
238 }
239 
mapcache_configuration_get_grid(mapcache_cfg * config,const char * key)240 mapcache_grid *mapcache_configuration_get_grid(mapcache_cfg *config, const char *key)
241 {
242   return (mapcache_grid*)apr_hash_get(config->grids, (void*)key, APR_HASH_KEY_STRING);
243 }
244 
mapcache_configuration_get_ruleset(mapcache_cfg * config,const char * key)245 mapcache_ruleset *mapcache_configuration_get_ruleset(mapcache_cfg *config, const char *key)
246 {
247   return (mapcache_ruleset*)apr_hash_get(config->rulesets, (void*)key, APR_HASH_KEY_STRING);
248 }
249 
mapcache_configuration_get_tileset(mapcache_cfg * config,const char * key)250 mapcache_tileset *mapcache_configuration_get_tileset(mapcache_cfg *config, const char *key)
251 {
252   if(config->mode == MAPCACHE_MODE_NORMAL) {
253     return (mapcache_tileset*)apr_hash_get(config->tilesets, (void*)key, APR_HASH_KEY_STRING);
254   } else {
255     return (mapcache_tileset*)apr_hash_get(config->tilesets, (void*)"mirror", APR_HASH_KEY_STRING);
256   }
257 }
258 
mapcache_configuration_get_image_format(mapcache_cfg * config,const char * key)259 mapcache_image_format *mapcache_configuration_get_image_format(mapcache_cfg *config, const char *key)
260 {
261   return (mapcache_image_format*)apr_hash_get(config->image_formats, (void*)key, APR_HASH_KEY_STRING);
262 }
263 
mapcache_configuration_add_source(mapcache_cfg * config,mapcache_source * source,const char * key)264 void mapcache_configuration_add_source(mapcache_cfg *config, mapcache_source *source, const char * key)
265 {
266   apr_hash_set(config->sources, key, APR_HASH_KEY_STRING, (void*)source);
267 }
268 
mapcache_configuration_add_grid(mapcache_cfg * config,mapcache_grid * grid,const char * key)269 void mapcache_configuration_add_grid(mapcache_cfg *config, mapcache_grid *grid, const char * key)
270 {
271   apr_hash_set(config->grids, key, APR_HASH_KEY_STRING, (void*)grid);
272 }
273 
mapcache_configuration_add_ruleset(mapcache_cfg * config,mapcache_ruleset * ruleset,const char * key)274 void mapcache_configuration_add_ruleset(mapcache_cfg *config, mapcache_ruleset *ruleset, const char * key)
275 {
276   apr_hash_set(config->rulesets, key, APR_HASH_KEY_STRING, (void*)ruleset);
277 }
278 
mapcache_configuration_add_tileset(mapcache_cfg * config,mapcache_tileset * tileset,const char * key)279 void mapcache_configuration_add_tileset(mapcache_cfg *config, mapcache_tileset *tileset, const char * key)
280 {
281   tileset->config = config;
282   apr_hash_set(config->tilesets, key, APR_HASH_KEY_STRING, (void*)tileset);
283 }
284 
mapcache_configuration_add_cache(mapcache_cfg * config,mapcache_cache * cache,const char * key)285 void mapcache_configuration_add_cache(mapcache_cfg *config, mapcache_cache *cache, const char * key)
286 {
287   apr_hash_set(config->caches, key, APR_HASH_KEY_STRING, (void*)cache);
288 }
289 
mapcache_configuration_add_image_format(mapcache_cfg * config,mapcache_image_format * format,const char * key)290 void mapcache_configuration_add_image_format(mapcache_cfg *config, mapcache_image_format *format, const char * key)
291 {
292   apr_hash_set(config->image_formats, key, APR_HASH_KEY_STRING, (void*)format);
293 }
294