Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/utils/MapfileGenerator.java @ 1190:f514894ec2fd
merged flys-artifacts/2.5
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:17 +0200 |
parents | bcf70a452646 |
children | 6c0b79efd2c9 |
comparison
equal
deleted
inserted
replaced
917:b48c36076e17 | 1190:f514894ec2fd |
---|---|
1 package de.intevation.flys.utils; | |
2 | |
3 import java.io.File; | |
4 import java.io.FileNotFoundException; | |
5 import java.io.FileWriter; | |
6 import java.io.IOException; | |
7 import java.io.StringWriter; | |
8 import java.io.Writer; | |
9 | |
10 import java.util.ArrayList; | |
11 import java.util.Date; | |
12 import java.util.List; | |
13 | |
14 import org.apache.log4j.Logger; | |
15 | |
16 import org.apache.velocity.Template; | |
17 import org.apache.velocity.VelocityContext; | |
18 import org.apache.velocity.app.VelocityEngine; | |
19 | |
20 import de.intevation.flys.artifacts.model.LayerInfo; | |
21 | |
22 /** | |
23 * This class iterates over a bunch of directories, searches for meta | |
24 * information coresponding to shapefiles and creates a mapfile which is used by | |
25 * a <i>MapServer</i>. | |
26 * | |
27 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> | |
28 */ | |
29 public class MapfileGenerator | |
30 extends Thread | |
31 { | |
32 public static final String WSPLGEN_RESULT_SHAPE = "wsplgen.shp"; | |
33 public static final String WSPLGEN_LINES_SHAPE = "barrier_lines.shp"; | |
34 public static final String WSPLGEN_POLYGONS_SHAPE = "barrier_polygons.shp"; | |
35 | |
36 public static final String MS_WSPLGEN_POSTFIX = "-wsplgen"; | |
37 public static final String MS_BARRIERS_POSTFIX = "-barriers"; | |
38 public static final String MS_LINE_POSTFIX = "-lines"; | |
39 public static final String MS_POLYGONS_POSTFIX = "-polygons"; | |
40 | |
41 protected static final long SLEEPTIME = 10 * 1000L; // 10 seconds | |
42 | |
43 private static Logger logger = Logger.getLogger(MapfileGenerator.class); | |
44 | |
45 private static MapfileGenerator instance; | |
46 | |
47 private File mapfile; | |
48 private File shapefileDirectory; | |
49 | |
50 private String mapServerUrl; | |
51 private String templatePath; | |
52 private String velocityLogfile; | |
53 | |
54 private VelocityEngine velocityEngine; | |
55 private boolean lock[]; | |
56 | |
57 | |
58 | |
59 private MapfileGenerator() { | |
60 lock = new boolean[1]; | |
61 } | |
62 | |
63 | |
64 /** | |
65 * A main method which can be used to create a mapfile without a running | |
66 * artifact server.<br> | |
67 * <b>NOTE:</b> This method is not implemented yet! | |
68 * | |
69 * @param args Arguments. | |
70 */ | |
71 public static void main(String[] args) { | |
72 throw new Error("MapfileGenerator.main() is CURRENTLY NOT IMPLEMENTED!"); | |
73 } | |
74 | |
75 | |
76 /** | |
77 * Returns the instance of this generator. | |
78 * | |
79 * @return the instance. | |
80 */ | |
81 public static synchronized MapfileGenerator getInstance() { | |
82 if (instance == null) { | |
83 instance = new MapfileGenerator(); | |
84 instance.setDaemon(true); | |
85 instance.start(); | |
86 } | |
87 | |
88 return instance; | |
89 } | |
90 | |
91 | |
92 /** | |
93 * Triggers the mapfile generation process. | |
94 */ | |
95 public void update() { | |
96 synchronized (lock) { | |
97 logger.debug("update"); | |
98 lock[0] = true; | |
99 lock.notify(); | |
100 } | |
101 } | |
102 | |
103 | |
104 /** | |
105 * Thread to generate a mapfile. | |
106 */ | |
107 @Override | |
108 public void run() { | |
109 logger.debug("Start MapfileGenerator thread..."); | |
110 try { | |
111 for (;;) { | |
112 synchronized (lock) { | |
113 while (!lock[0]) { | |
114 lock.wait(SLEEPTIME); | |
115 } | |
116 lock[0] = false; | |
117 } | |
118 | |
119 logger.debug("Start sync process now..."); | |
120 generate(); | |
121 } | |
122 } | |
123 catch (InterruptedException ie) { | |
124 logger.debug("MapfileGenerator thread got an interrupt."); | |
125 } | |
126 catch (FileNotFoundException fnfe) { | |
127 logger.debug("Error while mapfile creation: " + fnfe.getMessage()); | |
128 } | |
129 finally { | |
130 logger.debug("THREAD END"); | |
131 } | |
132 } | |
133 | |
134 /** | |
135 * Method to check the existance of a template file. | |
136 * | |
137 * @param templateID The name of a template. | |
138 * @return true, of the template exists - otherwise false. | |
139 */ | |
140 public boolean templateExists(String templateID){ | |
141 Template template = getTemplateByName(templateID); | |
142 return template != null; | |
143 } | |
144 | |
145 | |
146 /** | |
147 * Method which starts searching for meta information file and mapfile | |
148 * generation. | |
149 */ | |
150 protected void generate() | |
151 throws FileNotFoundException | |
152 { | |
153 File[] userDirs = getUserDirs(); | |
154 List<LayerInfo> layers = parseLayers(userDirs); | |
155 | |
156 logger.info("Found " + layers.size() + " layers for user mapfile."); | |
157 | |
158 writeMapfile(layers); | |
159 } | |
160 | |
161 | |
162 /** | |
163 * Returns the VelocityEngine used for the template mechanism. | |
164 * | |
165 * @return the velocity engine. | |
166 */ | |
167 protected VelocityEngine getVelocityEngine() { | |
168 if (velocityEngine == null) { | |
169 velocityEngine = new VelocityEngine(); | |
170 try { | |
171 setupVelocity(velocityEngine); | |
172 } | |
173 catch (Exception e) { | |
174 logger.error(e, e); | |
175 return null; | |
176 } | |
177 } | |
178 return velocityEngine; | |
179 } | |
180 | |
181 | |
182 /** | |
183 * Initialize velocity. | |
184 * | |
185 * @param engine Velocity engine. | |
186 * @throws Exception if an error occured while initializing velocity. | |
187 */ | |
188 protected void setupVelocity(VelocityEngine engine) | |
189 throws Exception | |
190 { | |
191 engine.setProperty( | |
192 "input.encoding", | |
193 "UTF-8"); | |
194 | |
195 engine.setProperty( | |
196 VelocityEngine.RUNTIME_LOG, | |
197 FLYSUtils.getXPathString(FLYSUtils.XPATH_VELOCITY_LOGFILE)); | |
198 | |
199 engine.setProperty( | |
200 "resource.loader", | |
201 "file"); | |
202 | |
203 engine.setProperty( | |
204 "file.resource.loader.path", | |
205 FLYSUtils.getXPathString(FLYSUtils.XPATH_MAPSERVER_TEMPLATE_PATH)); | |
206 | |
207 engine.init(); | |
208 } | |
209 | |
210 | |
211 /** | |
212 * Returns a template specified by <i>model</i>. | |
213 * | |
214 * @param model The name of the template. | |
215 * @return a template. | |
216 */ | |
217 protected Template getTemplateByName(String model) { | |
218 if (model.indexOf(".vm") < 0) { | |
219 model = model.concat(".vm"); | |
220 } | |
221 | |
222 try { | |
223 VelocityEngine engine = getVelocityEngine(); | |
224 if (engine == null) { | |
225 logger.error("Error while fetching VelocityEngine."); | |
226 return null; | |
227 } | |
228 | |
229 return engine.getTemplate(model); | |
230 } | |
231 catch (Exception e) { | |
232 logger.warn(e, e); | |
233 } | |
234 | |
235 return null; | |
236 } | |
237 | |
238 | |
239 /** | |
240 * Returns the mapfile template. | |
241 * | |
242 * @return the mapfile template. | |
243 * @throws Exception if an error occured while reading the configuration. | |
244 */ | |
245 protected Template getMapfileTemplate() | |
246 throws Exception | |
247 { | |
248 String mapfileName = FLYSUtils.getXPathString( | |
249 FLYSUtils.XPATH_MAPFILE_TEMPLATE); | |
250 | |
251 return getTemplateByName(mapfileName); | |
252 } | |
253 | |
254 | |
255 /** | |
256 * Returns the base directory storing the shapefiles. | |
257 * | |
258 * @return the shapefile base directory. | |
259 * | |
260 * @throws FileNotFoundException if no shapefile path is found or | |
261 * configured. | |
262 */ | |
263 protected File getShapefileBaseDir() | |
264 throws FileNotFoundException | |
265 { | |
266 if (shapefileDirectory == null) { | |
267 String path = FLYSUtils.getXPathString( | |
268 FLYSUtils.XPATH_SHAPEFILE_DIR); | |
269 | |
270 if (path != null) { | |
271 shapefileDirectory = new File(path); | |
272 } | |
273 | |
274 if (shapefileDirectory == null || !shapefileDirectory.exists()) { | |
275 throw new FileNotFoundException("No shapefile directory given"); | |
276 } | |
277 } | |
278 | |
279 return shapefileDirectory; | |
280 } | |
281 | |
282 | |
283 protected File[] getUserDirs() | |
284 throws FileNotFoundException | |
285 { | |
286 File baseDir = getShapefileBaseDir(); | |
287 File[] artifactDirs = baseDir.listFiles(); | |
288 | |
289 // TODO ONLY RETURN DIRECTORIES OF THE SPECIFIED USER | |
290 | |
291 return artifactDirs; | |
292 } | |
293 | |
294 | |
295 | |
296 protected List<LayerInfo> parseLayers(File[] dirs) { | |
297 List<LayerInfo> layers = new ArrayList<LayerInfo>(); | |
298 | |
299 for (File dir: dirs) { | |
300 LayerInfo layer = parseUeskLayer(dir); | |
301 if (layer != null && layer.getData() != null) { | |
302 logger.debug(" Add WSPLGEN layer."); | |
303 layers.add(layer); | |
304 } | |
305 | |
306 List<LayerInfo> barriers = parseBarriersLayers(dir); | |
307 int num = barriers != null ? barriers.size() : 0; | |
308 if (num > 0) { | |
309 if (barriers.get(0).getData() != null) { | |
310 logger.debug(" Add " + num + " BARRIERS layers."); | |
311 layers.addAll(barriers); | |
312 } | |
313 } | |
314 } | |
315 | |
316 return layers; | |
317 } | |
318 | |
319 | |
320 protected LayerInfo parseUeskLayer(File dir) { | |
321 File uesk = new File(dir, WSPLGEN_RESULT_SHAPE); | |
322 | |
323 if (!uesk.exists() || !uesk.isFile()) { | |
324 return null; | |
325 } | |
326 | |
327 return new LayerInfo( | |
328 dir.getName() + MS_WSPLGEN_POSTFIX, | |
329 "POLYGON", | |
330 dir.getName(), | |
331 WSPLGEN_RESULT_SHAPE, | |
332 "I18N_WSPLGEN_RESULT"); | |
333 } | |
334 | |
335 | |
336 protected List<LayerInfo> parseBarriersLayers(File dir) { | |
337 List<LayerInfo> barriers = new ArrayList<LayerInfo>(2); | |
338 | |
339 String group = dir.getName() + MS_BARRIERS_POSTFIX; | |
340 String groupTitle = "I18N_BARRIERS_TITLE"; | |
341 | |
342 File lines = new File(dir, WSPLGEN_LINES_SHAPE); | |
343 File polygons = new File(dir, WSPLGEN_POLYGONS_SHAPE); | |
344 | |
345 if (lines.exists() || lines.isFile()) { | |
346 barriers.add( | |
347 new LayerInfo( | |
348 dir.getName() + MS_LINE_POSTFIX, | |
349 "LINE", | |
350 dir.getName(), | |
351 WSPLGEN_LINES_SHAPE, | |
352 "I18N_LINE_SHAPE", | |
353 group, | |
354 groupTitle)); | |
355 } | |
356 | |
357 if (polygons.exists() || polygons.isFile()) { | |
358 barriers.add( | |
359 new LayerInfo( | |
360 dir.getName() + MS_POLYGONS_POSTFIX, | |
361 "POLYGON", | |
362 dir.getName(), | |
363 WSPLGEN_POLYGONS_SHAPE, | |
364 "I18N_POLYGON_SHAPE", | |
365 group, | |
366 groupTitle)); | |
367 } | |
368 | |
369 return barriers; | |
370 } | |
371 | |
372 | |
373 /** | |
374 * Creates a mapfile with the layer information stored in <i>layers</i>. | |
375 * | |
376 * @param layers Layer information. | |
377 */ | |
378 protected void writeMapfile(List<LayerInfo> layers) { | |
379 String tmpMapName = "mapfile" + new Date().getTime(); | |
380 | |
381 File mapfile = new File( | |
382 FLYSUtils.getXPathString(FLYSUtils.XPATH_MAPFILE_PATH)); | |
383 | |
384 File tmp = null; | |
385 Writer writer = null; | |
386 | |
387 try { | |
388 tmp = new File(mapfile.getParent(), tmpMapName); | |
389 tmp.createNewFile(); | |
390 | |
391 writer = new FileWriter(tmp); | |
392 | |
393 VelocityContext context = new VelocityContext(); | |
394 context.put("MAPSERVERURL", | |
395 FLYSUtils.getXPathString(FLYSUtils.XPATH_MAPSERVER_URL)); | |
396 context.put("SHAPEFILEPATH", | |
397 FLYSUtils.getXPathString(FLYSUtils.XPATH_SHAPEFILE_DIR)); | |
398 context.put("LAYERS", fillLayerTemplates(layers)); | |
399 | |
400 Template mapTemplate = getMapfileTemplate(); | |
401 if (mapTemplate == null) { | |
402 logger.warn("No mapfile template found."); | |
403 return; | |
404 } | |
405 | |
406 mapTemplate.merge(context, writer); | |
407 | |
408 // we need to create a temporary mapfile first und rename it into | |
409 // real mapfile because we don't run into race conditions on this | |
410 // way. (iw) | |
411 tmp.renameTo(mapfile); | |
412 } | |
413 catch (FileNotFoundException fnfe) { | |
414 logger.error(fnfe, fnfe); | |
415 } | |
416 catch (IOException ioe) { | |
417 logger.error(ioe, ioe); | |
418 } | |
419 catch (Exception e) { | |
420 logger.error(e, e); | |
421 } | |
422 finally { | |
423 try { | |
424 if (writer != null) { | |
425 writer.close(); | |
426 } | |
427 | |
428 if (tmp.exists()) { | |
429 tmp.delete(); | |
430 } | |
431 } | |
432 catch (IOException ioe) { | |
433 logger.debug(ioe, ioe); | |
434 } | |
435 } | |
436 } | |
437 | |
438 | |
439 protected List<String> fillLayerTemplates(List<LayerInfo> layers) { | |
440 List<String> evaluated = new ArrayList<String>(layers.size()); | |
441 | |
442 for (LayerInfo layer: layers) { | |
443 StringWriter writer = new StringWriter(); | |
444 | |
445 VelocityContext context = new VelocityContext(); | |
446 context.put("LAYER", layer); | |
447 | |
448 Template t = getTemplateByName("layer.vm"); | |
449 if (t == null) { | |
450 logger.warn("No 'layer.vm' template found."); | |
451 return evaluated; | |
452 } | |
453 | |
454 t.merge(context, writer); | |
455 | |
456 evaluated.add(writer.toString()); | |
457 } | |
458 | |
459 return evaluated; | |
460 } | |
461 } | |
462 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |