Mercurial > dive4elements > gnv-client
comparison gnv-artifacts/src/main/java/de/intevation/gnv/utils/MapfileGenerator.java @ 657:af3f56758f59
merged gnv-artifacts/0.5
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:13:53 +0200 |
parents | 40ead2d2a08d |
children | 9ba6bb85d6dd |
comparison
equal
deleted
inserted
replaced
590:5f5f273c8566 | 657:af3f56758f59 |
---|---|
1 package de.intevation.gnv.utils; | |
2 | |
3 import de.intevation.artifactdatabase.Config; | |
4 import de.intevation.artifactdatabase.XMLUtils; | |
5 import de.intevation.artifacts.ArtifactNamespaceContext; | |
6 import de.intevation.gnv.wms.LayerInfo; | |
7 | |
8 import java.io.File; | |
9 import java.io.FileNotFoundException; | |
10 import java.io.FileWriter; | |
11 import java.io.IOException; | |
12 import java.io.StringWriter; | |
13 import java.io.Writer; | |
14 import java.util.ArrayList; | |
15 import java.util.Date; | |
16 import java.util.List; | |
17 | |
18 import javax.xml.xpath.XPathConstants; | |
19 | |
20 import org.apache.log4j.Logger; | |
21 | |
22 import org.apache.velocity.Template; | |
23 import org.apache.velocity.VelocityContext; | |
24 import org.apache.velocity.app.VelocityEngine; | |
25 | |
26 import org.w3c.dom.Document; | |
27 import org.w3c.dom.Node; | |
28 import org.w3c.dom.NodeList; | |
29 | |
30 | |
31 /** | |
32 * @author Ingo Weinzierl (ingo.weinzierl@intevation.de) | |
33 */ | |
34 public class MapfileGenerator | |
35 extends Thread | |
36 { | |
37 public static final String TEMPLATE_PATH = | |
38 "/artifact-database/gnv/map-generator/templates/path/text()"; | |
39 | |
40 public static final String TEMPLATE_MAPFILE = | |
41 "/artifact-database/gnv/map-generator/templates/maptemplate/text()"; | |
42 | |
43 public static final String MAPFILE_PATH = | |
44 "/artifact-database/gnv/map-generator/mapfile/@path"; | |
45 | |
46 public static final String SHAPEFILE_BASE_DIR = | |
47 "/artifact-database/gnv/shapefile-directory/@path"; | |
48 | |
49 public static final String VELOCITY_LOGFILE = | |
50 "/artifact-database/velocity/logfile/@path"; | |
51 | |
52 public static final String META_FILE_NAME = "meta.xml"; | |
53 | |
54 public static final String XPATH_LAYER = "/art:meta/art:layer"; | |
55 public static final String XPATH_LAYER_NAME = "art:name"; | |
56 public static final String XPATH_LAYER_TYPE = "art:type"; | |
57 public static final String XPATH_LAYER_DATA = "art:data"; | |
58 public static final String XPATH_LAYER_STATUS = "art:status"; | |
59 public static final String XPATH_LAYER_MODEL = "art:model"; | |
60 | |
61 protected static final long SLEEPTIME = 10 * 1000L; // 10 seconds | |
62 | |
63 private static Logger logger = Logger.getLogger(MapfileGenerator.class); | |
64 | |
65 private static MapfileGenerator instance; | |
66 | |
67 private File mapfile; | |
68 private String shapefileDirectory; | |
69 private String templatePath; | |
70 private String velocityLogfile; | |
71 | |
72 private VelocityEngine velocityEngine; | |
73 private boolean lock[]; | |
74 | |
75 | |
76 | |
77 private MapfileGenerator() { | |
78 lock = new boolean[1]; | |
79 } | |
80 | |
81 | |
82 public static void main(String[] args) { | |
83 // TODO IMPLEMENT ME | |
84 } | |
85 | |
86 | |
87 public static synchronized MapfileGenerator getInstance() { | |
88 if (instance == null) { | |
89 instance = new MapfileGenerator(); | |
90 instance.setDaemon(true); | |
91 instance.start(); | |
92 } | |
93 | |
94 return instance; | |
95 } | |
96 | |
97 | |
98 public void update() { | |
99 synchronized (lock) { | |
100 logger.debug("update"); | |
101 lock[0] = true; | |
102 lock.notify(); | |
103 } | |
104 } | |
105 | |
106 | |
107 public void run() { | |
108 logger.debug("Start MapfileGenerator thread..."); | |
109 try { | |
110 for (;;) { | |
111 synchronized (lock) { | |
112 while (!lock[0]) { | |
113 lock.wait(SLEEPTIME); | |
114 } | |
115 lock[0] = false; | |
116 } | |
117 | |
118 logger.debug("Start sync process now..."); | |
119 generate(); | |
120 } | |
121 } | |
122 catch (InterruptedException ie) { | |
123 logger.debug("MapfileGenerator thread got an interrupt."); | |
124 } | |
125 finally { | |
126 logger.debug("THREAD END"); | |
127 } | |
128 } | |
129 | |
130 | |
131 protected void generate() { | |
132 File basedir = new File(getShapefileBaseDir()); | |
133 List layers = new ArrayList(); | |
134 searchMetaInformation(basedir, layers); | |
135 writeMapfile(layers); | |
136 } | |
137 | |
138 | |
139 protected VelocityEngine getVelocityEngine() { | |
140 if (velocityEngine == null) { | |
141 velocityEngine = new VelocityEngine(); | |
142 try { | |
143 setupVelocity(velocityEngine); | |
144 } | |
145 catch (Exception e) { | |
146 logger.error(e, e); | |
147 return null; | |
148 } | |
149 } | |
150 return velocityEngine; | |
151 } | |
152 | |
153 | |
154 protected void setupVelocity(VelocityEngine engine) | |
155 throws Exception | |
156 { | |
157 engine.setProperty( | |
158 "input.encoding", | |
159 "UTF-8"); | |
160 | |
161 engine.setProperty( | |
162 VelocityEngine.RUNTIME_LOG, | |
163 getVelocityLogfile()); | |
164 | |
165 engine.setProperty( | |
166 "resource.loader", | |
167 "file"); | |
168 | |
169 engine.setProperty( | |
170 "file.resource.loader.path", | |
171 getTemplateBaseDir()); | |
172 | |
173 engine.init(); | |
174 } | |
175 | |
176 | |
177 protected String getVelocityLogfile() { | |
178 if (velocityLogfile == null) | |
179 velocityLogfile = Config.getStringXPath(VELOCITY_LOGFILE); | |
180 | |
181 return velocityLogfile; | |
182 } | |
183 | |
184 | |
185 protected String getTemplateBaseDir() { | |
186 if (templatePath == null) { | |
187 templatePath = Config.getStringXPath(TEMPLATE_PATH); | |
188 templatePath = Config.replaceConfigDir(templatePath); | |
189 } | |
190 | |
191 return templatePath; | |
192 } | |
193 | |
194 | |
195 protected Template getTemplateByName(String model) { | |
196 if (model.indexOf(".vm") < 0) { | |
197 model = model.concat(".vm"); | |
198 } | |
199 | |
200 try { | |
201 VelocityEngine engine = getVelocityEngine(); | |
202 if (engine == null) { | |
203 logger.error("Error while fetching VelocityEngine."); | |
204 return null; | |
205 } | |
206 | |
207 return engine.getTemplate(model); | |
208 } | |
209 catch (Exception e) { | |
210 logger.warn(e, e); | |
211 } | |
212 | |
213 return null; | |
214 } | |
215 | |
216 | |
217 protected Template getMapfileTemplate() | |
218 throws Exception | |
219 { | |
220 String mapfileName = Config.getStringXPath(TEMPLATE_MAPFILE); | |
221 return getTemplateByName(mapfileName); | |
222 } | |
223 | |
224 | |
225 protected String getShapefileBaseDir() { | |
226 if (shapefileDirectory == null) { | |
227 shapefileDirectory = Config.getStringXPath(SHAPEFILE_BASE_DIR); | |
228 shapefileDirectory = Config.replaceConfigDir(shapefileDirectory); | |
229 } | |
230 | |
231 return shapefileDirectory; | |
232 } | |
233 | |
234 | |
235 protected File getMapfile() { | |
236 if (mapfile == null) { | |
237 String tmp = Config.getStringXPath(MAPFILE_PATH); | |
238 tmp = Config.replaceConfigDir(tmp); | |
239 mapfile = new File(tmp); | |
240 } | |
241 | |
242 return mapfile; | |
243 } | |
244 | |
245 | |
246 protected void searchMetaInformation(File file, List store) { | |
247 if (file.isDirectory()) { | |
248 File[] files = file.listFiles(); | |
249 | |
250 if (files != null && files.length != 0) { | |
251 int size = files.length; | |
252 for (File tmp: files) { | |
253 searchMetaInformation(tmp, store); | |
254 } | |
255 } | |
256 } | |
257 else if (file.getName().equals(META_FILE_NAME)) { | |
258 LayerInfo[] info = parseMeta(file); | |
259 | |
260 int infoSize = info.length; | |
261 for (int j = 0; j < infoSize; j++) { | |
262 if (info[j] != null) { | |
263 store.add(info[j]); | |
264 } | |
265 } | |
266 } | |
267 } | |
268 | |
269 | |
270 protected LayerInfo[] parseMeta(File file) { | |
271 Document meta = XMLUtils.parseDocument(file); | |
272 List layers = new ArrayList(); | |
273 | |
274 NodeList layerset = (NodeList) XMLUtils.xpath( | |
275 meta, | |
276 XPATH_LAYER, | |
277 XPathConstants.NODESET, | |
278 ArtifactNamespaceContext.INSTANCE); | |
279 | |
280 int size = layerset.getLength(); | |
281 for (int i = 0; i < size; i++) { | |
282 LayerInfo info = parseLayer(layerset.item(i)); | |
283 | |
284 if (info != null && !info.isEmpty() && !info.isBroken()) { | |
285 layers.add(info); | |
286 } | |
287 else { | |
288 logger.warn("Found broken LayerInfo object."); | |
289 } | |
290 } | |
291 | |
292 return (LayerInfo[]) layers.toArray(new LayerInfo[layers.size()]); | |
293 } | |
294 | |
295 | |
296 protected LayerInfo parseLayer(Node layer) { | |
297 LayerInfo info = new LayerInfo(); | |
298 | |
299 String name = parseLayerAttr(layer, XPATH_LAYER_NAME); | |
300 if (name != null && !name.equals("")) { | |
301 info.setName(name); | |
302 } | |
303 | |
304 String model = parseLayerAttr(layer, XPATH_LAYER_MODEL); | |
305 if (model != null && !model.equals("")) { | |
306 info.setModel(model); | |
307 } | |
308 | |
309 String type = parseLayerAttr(layer, XPATH_LAYER_TYPE); | |
310 if (type != null && !type.equals("")) { | |
311 info.setType(type); | |
312 } | |
313 | |
314 String data = parseLayerAttr(layer, XPATH_LAYER_DATA); | |
315 if (data != null && !data.equals("")) { | |
316 info.setData(data); | |
317 } | |
318 | |
319 String status = parseLayerAttr(layer, XPATH_LAYER_STATUS); | |
320 if (status != null && !status.equals("")) { | |
321 info.setStatus(status); | |
322 } | |
323 | |
324 return info; | |
325 } | |
326 | |
327 | |
328 protected String parseLayerAttr(Node node, String xpath) { | |
329 return (String) XMLUtils.xpath( | |
330 node, | |
331 xpath, | |
332 XPathConstants.STRING, | |
333 ArtifactNamespaceContext.INSTANCE); | |
334 } | |
335 | |
336 | |
337 protected void writeMapfile(List layers) { | |
338 String tmpMapName = "mapfile" + new Date().getTime(); | |
339 | |
340 int layersize = layers.size(); | |
341 StringBuilder sb = new StringBuilder(); | |
342 StringWriter sw = null; | |
343 LayerInfo info = null; | |
344 | |
345 for (int i = 0; i < layersize; i++) { | |
346 sw = new StringWriter(); | |
347 info = (LayerInfo) layers.get(i); | |
348 | |
349 Template layerTemplate = getTemplateByName(info.getModel()); | |
350 VelocityContext context = new VelocityContext(); | |
351 context.put("info", info); | |
352 | |
353 try { | |
354 layerTemplate.merge(context, sw); | |
355 sb.append(sw.toString()); | |
356 } | |
357 catch (IOException ioe) { | |
358 logger.warn("Error while filling layer template."); | |
359 logger.warn(ioe, ioe); | |
360 } | |
361 } | |
362 | |
363 File map = getMapfile(); | |
364 Writer writer = null; | |
365 File tmp = null; | |
366 | |
367 try { | |
368 tmp = new File(map.getParent(), tmpMapName); | |
369 | |
370 tmp.createNewFile(); | |
371 writer = new FileWriter(tmp); | |
372 | |
373 VelocityContext context = new VelocityContext(); | |
374 context.put("LAYERS", sb.toString()); | |
375 | |
376 Template mapTemplate = getMapfileTemplate(); | |
377 if (mapTemplate == null) { | |
378 logger.warn("No mapfile template found."); | |
379 return; | |
380 } | |
381 | |
382 mapTemplate.merge(context, writer); | |
383 | |
384 // we need to create a temporary mapfile first und rename it into | |
385 // real mapfile because we don't run into race conditions on this | |
386 // way. (iw) | |
387 tmp.renameTo(map); | |
388 } | |
389 catch (FileNotFoundException fnfe) { | |
390 logger.error(fnfe, fnfe); | |
391 } | |
392 catch (IOException ioe) { | |
393 logger.error(ioe, ioe); | |
394 } | |
395 catch (Exception e) { | |
396 logger.error(e, e); | |
397 } | |
398 finally { | |
399 try { | |
400 // close file writer | |
401 if (writer != null) { | |
402 writer.close(); | |
403 } | |
404 | |
405 // remove temporary mapfile if an error occured and it still | |
406 // exists | |
407 if (tmp.exists()) { | |
408 tmp.delete(); | |
409 } | |
410 } | |
411 catch (IOException ioe) { | |
412 logger.debug(ioe, ioe); | |
413 } | |
414 } | |
415 } | |
416 } | |
417 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: |