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 :

http://dive4elements.wald.intevation.org