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