Mercurial > dive4elements > river
view flys-artifacts/src/main/java/de/intevation/flys/utils/MapfileGenerator.java @ 1135:c8c753931514
Added a fallback mechanism to style mapserver layers as long as the theme mechanism is not implemented for maps (as it is for charts).
flys-artifacts/trunk@2656 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Ingo Weinzierl <ingo.weinzierl@intevation.de> |
---|---|
date | Tue, 06 Sep 2011 17:41:07 +0000 |
parents | bcf70a452646 |
children | 6c0b79efd2c9 |
line wrap: on
line source
package de.intevation.flys.utils; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.log4j.Logger; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import de.intevation.flys.artifacts.model.LayerInfo; /** * This class iterates over a bunch of directories, searches for meta * information coresponding to shapefiles and creates a mapfile which is used by * a <i>MapServer</i>. * * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> */ public class MapfileGenerator extends Thread { public static final String WSPLGEN_RESULT_SHAPE = "wsplgen.shp"; public static final String WSPLGEN_LINES_SHAPE = "barrier_lines.shp"; public static final String WSPLGEN_POLYGONS_SHAPE = "barrier_polygons.shp"; public static final String MS_WSPLGEN_POSTFIX = "-wsplgen"; public static final String MS_BARRIERS_POSTFIX = "-barriers"; public static final String MS_LINE_POSTFIX = "-lines"; public static final String MS_POLYGONS_POSTFIX = "-polygons"; protected static final long SLEEPTIME = 10 * 1000L; // 10 seconds private static Logger logger = Logger.getLogger(MapfileGenerator.class); private static MapfileGenerator instance; private File mapfile; private File shapefileDirectory; private String mapServerUrl; private String templatePath; private String velocityLogfile; private VelocityEngine velocityEngine; private boolean lock[]; private MapfileGenerator() { lock = new boolean[1]; } /** * A main method which can be used to create a mapfile without a running * artifact server.<br> * <b>NOTE:</b> This method is not implemented yet! * * @param args Arguments. */ public static void main(String[] args) { throw new Error("MapfileGenerator.main() is CURRENTLY NOT IMPLEMENTED!"); } /** * Returns the instance of this generator. * * @return the instance. */ public static synchronized MapfileGenerator getInstance() { if (instance == null) { instance = new MapfileGenerator(); instance.setDaemon(true); instance.start(); } return instance; } /** * Triggers the mapfile generation process. */ public void update() { synchronized (lock) { logger.debug("update"); lock[0] = true; lock.notify(); } } /** * Thread to generate a mapfile. */ @Override public void run() { logger.debug("Start MapfileGenerator thread..."); try { for (;;) { synchronized (lock) { while (!lock[0]) { lock.wait(SLEEPTIME); } lock[0] = false; } logger.debug("Start sync process now..."); generate(); } } catch (InterruptedException ie) { logger.debug("MapfileGenerator thread got an interrupt."); } catch (FileNotFoundException fnfe) { logger.debug("Error while mapfile creation: " + fnfe.getMessage()); } finally { logger.debug("THREAD END"); } } /** * Method to check the existance of a template file. * * @param templateID The name of a template. * @return true, of the template exists - otherwise false. */ public boolean templateExists(String templateID){ Template template = getTemplateByName(templateID); return template != null; } /** * Method which starts searching for meta information file and mapfile * generation. */ protected void generate() throws FileNotFoundException { File[] userDirs = getUserDirs(); List<LayerInfo> layers = parseLayers(userDirs); logger.info("Found " + layers.size() + " layers for user mapfile."); writeMapfile(layers); } /** * Returns the VelocityEngine used for the template mechanism. * * @return the velocity engine. */ protected VelocityEngine getVelocityEngine() { if (velocityEngine == null) { velocityEngine = new VelocityEngine(); try { setupVelocity(velocityEngine); } catch (Exception e) { logger.error(e, e); return null; } } return velocityEngine; } /** * Initialize velocity. * * @param engine Velocity engine. * @throws Exception if an error occured while initializing velocity. */ protected void setupVelocity(VelocityEngine engine) throws Exception { engine.setProperty( "input.encoding", "UTF-8"); engine.setProperty( VelocityEngine.RUNTIME_LOG, FLYSUtils.getXPathString(FLYSUtils.XPATH_VELOCITY_LOGFILE)); engine.setProperty( "resource.loader", "file"); engine.setProperty( "file.resource.loader.path", FLYSUtils.getXPathString(FLYSUtils.XPATH_MAPSERVER_TEMPLATE_PATH)); engine.init(); } /** * Returns a template specified by <i>model</i>. * * @param model The name of the template. * @return a template. */ protected Template getTemplateByName(String model) { if (model.indexOf(".vm") < 0) { model = model.concat(".vm"); } try { VelocityEngine engine = getVelocityEngine(); if (engine == null) { logger.error("Error while fetching VelocityEngine."); return null; } return engine.getTemplate(model); } catch (Exception e) { logger.warn(e, e); } return null; } /** * Returns the mapfile template. * * @return the mapfile template. * @throws Exception if an error occured while reading the configuration. */ protected Template getMapfileTemplate() throws Exception { String mapfileName = FLYSUtils.getXPathString( FLYSUtils.XPATH_MAPFILE_TEMPLATE); return getTemplateByName(mapfileName); } /** * Returns the base directory storing the shapefiles. * * @return the shapefile base directory. * * @throws FileNotFoundException if no shapefile path is found or * configured. */ protected File getShapefileBaseDir() throws FileNotFoundException { if (shapefileDirectory == null) { String path = FLYSUtils.getXPathString( FLYSUtils.XPATH_SHAPEFILE_DIR); if (path != null) { shapefileDirectory = new File(path); } if (shapefileDirectory == null || !shapefileDirectory.exists()) { throw new FileNotFoundException("No shapefile directory given"); } } return shapefileDirectory; } protected File[] getUserDirs() throws FileNotFoundException { File baseDir = getShapefileBaseDir(); File[] artifactDirs = baseDir.listFiles(); // TODO ONLY RETURN DIRECTORIES OF THE SPECIFIED USER return artifactDirs; } protected List<LayerInfo> parseLayers(File[] dirs) { List<LayerInfo> layers = new ArrayList<LayerInfo>(); for (File dir: dirs) { LayerInfo layer = parseUeskLayer(dir); if (layer != null && layer.getData() != null) { logger.debug(" Add WSPLGEN layer."); layers.add(layer); } List<LayerInfo> barriers = parseBarriersLayers(dir); int num = barriers != null ? barriers.size() : 0; if (num > 0) { if (barriers.get(0).getData() != null) { logger.debug(" Add " + num + " BARRIERS layers."); layers.addAll(barriers); } } } return layers; } protected LayerInfo parseUeskLayer(File dir) { File uesk = new File(dir, WSPLGEN_RESULT_SHAPE); if (!uesk.exists() || !uesk.isFile()) { return null; } return new LayerInfo( dir.getName() + MS_WSPLGEN_POSTFIX, "POLYGON", dir.getName(), WSPLGEN_RESULT_SHAPE, "I18N_WSPLGEN_RESULT"); } protected List<LayerInfo> parseBarriersLayers(File dir) { List<LayerInfo> barriers = new ArrayList<LayerInfo>(2); String group = dir.getName() + MS_BARRIERS_POSTFIX; String groupTitle = "I18N_BARRIERS_TITLE"; File lines = new File(dir, WSPLGEN_LINES_SHAPE); File polygons = new File(dir, WSPLGEN_POLYGONS_SHAPE); if (lines.exists() || lines.isFile()) { barriers.add( new LayerInfo( dir.getName() + MS_LINE_POSTFIX, "LINE", dir.getName(), WSPLGEN_LINES_SHAPE, "I18N_LINE_SHAPE", group, groupTitle)); } if (polygons.exists() || polygons.isFile()) { barriers.add( new LayerInfo( dir.getName() + MS_POLYGONS_POSTFIX, "POLYGON", dir.getName(), WSPLGEN_POLYGONS_SHAPE, "I18N_POLYGON_SHAPE", group, groupTitle)); } return barriers; } /** * Creates a mapfile with the layer information stored in <i>layers</i>. * * @param layers Layer information. */ protected void writeMapfile(List<LayerInfo> layers) { String tmpMapName = "mapfile" + new Date().getTime(); File mapfile = new File( FLYSUtils.getXPathString(FLYSUtils.XPATH_MAPFILE_PATH)); File tmp = null; Writer writer = null; try { tmp = new File(mapfile.getParent(), tmpMapName); tmp.createNewFile(); writer = new FileWriter(tmp); VelocityContext context = new VelocityContext(); context.put("MAPSERVERURL", FLYSUtils.getXPathString(FLYSUtils.XPATH_MAPSERVER_URL)); context.put("SHAPEFILEPATH", FLYSUtils.getXPathString(FLYSUtils.XPATH_SHAPEFILE_DIR)); context.put("LAYERS", fillLayerTemplates(layers)); Template mapTemplate = getMapfileTemplate(); if (mapTemplate == null) { logger.warn("No mapfile template found."); return; } mapTemplate.merge(context, writer); // we need to create a temporary mapfile first und rename it into // real mapfile because we don't run into race conditions on this // way. (iw) tmp.renameTo(mapfile); } catch (FileNotFoundException fnfe) { logger.error(fnfe, fnfe); } catch (IOException ioe) { logger.error(ioe, ioe); } catch (Exception e) { logger.error(e, e); } finally { try { if (writer != null) { writer.close(); } if (tmp.exists()) { tmp.delete(); } } catch (IOException ioe) { logger.debug(ioe, ioe); } } } protected List<String> fillLayerTemplates(List<LayerInfo> layers) { List<String> evaluated = new ArrayList<String>(layers.size()); for (LayerInfo layer: layers) { StringWriter writer = new StringWriter(); VelocityContext context = new VelocityContext(); context.put("LAYER", layer); Template t = getTemplateByName("layer.vm"); if (t == null) { logger.warn("No 'layer.vm' template found."); return evaluated; } t.merge(context, writer); evaluated.add(writer.toString()); } return evaluated; } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :