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