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 :

http://dive4elements.wald.intevation.org