teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5863: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5863: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.utils; ingo@1129: teichmann@5831: import org.dive4elements.artifacts.common.utils.Config; teichmann@5831: import org.dive4elements.river.artifacts.model.LayerInfo; christian@3303: ingo@1129: import java.io.File; ingo@1129: import java.io.FileNotFoundException; ingo@1129: import java.io.FileWriter; ingo@3302: import java.io.FilenameFilter; ingo@1129: import java.io.IOException; ingo@1129: import java.io.Writer; ingo@1129: import java.util.ArrayList; ingo@1129: import java.util.Date; ingo@1129: import java.util.List; ingo@1129: ingo@1129: import org.apache.log4j.Logger; ingo@1129: import org.apache.velocity.Template; ingo@1129: import org.apache.velocity.VelocityContext; ingo@1129: import org.apache.velocity.app.VelocityEngine; christian@4656: import org.apache.velocity.runtime.RuntimeConstants; ingo@1129: ingo@1129: /** ingo@1129: * This class iterates over a bunch of directories, searches for meta ingo@1129: * information coresponding to shapefiles and creates a mapfile which is used by ingo@1129: * a MapServer. ingo@1129: * ingo@1129: * @author Ingo Weinzierl ingo@1129: */ christian@4654: public abstract class MapfileGenerator ingo@1129: { ingo@1134: public static final String WSPLGEN_RESULT_SHAPE = "wsplgen.shp"; ingo@1134: public static final String WSPLGEN_LINES_SHAPE = "barrier_lines.shp"; ingo@1134: public static final String WSPLGEN_POLYGONS_SHAPE = "barrier_polygons.shp"; raimund@2639: public static final String WSPLGEN_USER_SHAPE = "user-rgd.shp"; ingo@1134: raimund@2637: public static final String WSPLGEN_LAYER_TEMPLATE = "wsplgen_layer.vm"; ingo@1775: public static final String SHP_LAYER_TEMPLATE = "shapefile_layer.vm"; ingo@1792: public static final String DB_LAYER_TEMPLATE = "db_layer.vm"; christian@4648: public static final String RIVERAXIS_LAYER_TEMPLATE = "riveraxis-layer.vm"; ingo@1775: raimund@2639: public static final String MS_WSPLGEN_PREFIX = "wsplgen-"; raimund@2639: public static final String MS_BARRIERS_PREFIX = "barriers-"; raimund@2639: public static final String MS_LINE_PREFIX = "lines-"; raimund@2639: public static final String MS_POLYGONS_PREFIX = "polygons-"; raimund@2639: public static final String MS_LAYER_PREFIX = "ms_layer-"; raimund@2639: public static final String MS_USERSHAPE_PREFIX = "user-"; ingo@1129: ingo@1129: private static Logger logger = Logger.getLogger(MapfileGenerator.class); ingo@1129: ingo@1129: private File shapefileDirectory; ingo@1129: ingo@1129: private VelocityEngine velocityEngine; ingo@1129: ingo@1129: christian@4654: protected MapfileGenerator() { ingo@1129: } ingo@1129: ingo@1129: ingo@1129: /** ingo@1129: * Method to check the existance of a template file. ingo@1129: * ingo@1129: * @param templateID The name of a template. ingo@1129: * @return true, of the template exists - otherwise false. ingo@1129: */ ingo@1129: public boolean templateExists(String templateID){ ingo@1129: Template template = getTemplateByName(templateID); ingo@1129: return template != null; ingo@1129: } ingo@1129: ingo@1129: christian@4656: public abstract void generate() throws Exception; christian@4648: christian@4648: christian@4648: /** ingo@1129: * Returns the VelocityEngine used for the template mechanism. ingo@1129: * ingo@1129: * @return the velocity engine. ingo@1129: */ ingo@1129: protected VelocityEngine getVelocityEngine() { ingo@1129: if (velocityEngine == null) { ingo@1129: velocityEngine = new VelocityEngine(); ingo@1129: try { ingo@1129: setupVelocity(velocityEngine); ingo@1129: } ingo@1129: catch (Exception e) { ingo@1129: logger.error(e, e); ingo@1129: return null; ingo@1129: } ingo@1129: } ingo@1129: return velocityEngine; ingo@1129: } ingo@1129: ingo@1129: ingo@1129: /** ingo@1129: * Initialize velocity. ingo@1129: * ingo@1129: * @param engine Velocity engine. ingo@1129: * @throws Exception if an error occured while initializing velocity. ingo@1129: */ ingo@1129: protected void setupVelocity(VelocityEngine engine) ingo@1129: throws Exception ingo@1129: { ingo@1129: engine.setProperty( ingo@1129: "input.encoding", ingo@1129: "UTF-8"); ingo@1129: ingo@1129: engine.setProperty( christian@4656: RuntimeConstants.RUNTIME_LOG, christian@4656: getVelocityLogfile()); ingo@1129: ingo@1129: engine.setProperty( ingo@1129: "resource.loader", ingo@1129: "file"); ingo@1129: ingo@1129: engine.setProperty( ingo@1129: "file.resource.loader.path", christian@4656: getMapserverTemplatePath()); ingo@1129: ingo@1129: engine.init(); ingo@1129: } ingo@1129: christian@4656: protected abstract String getVelocityLogfile(); christian@4656: christian@4656: protected abstract String getMapserverTemplatePath(); christian@4656: rrenkert@5309: public abstract String getMapserverUrl(); ingo@1129: ingo@1792: protected VelocityContext getVelocityContext() { ingo@1792: VelocityContext context = new VelocityContext(); ingo@1792: ingo@1792: try { ingo@1792: context.put("MAPSERVERURL", christian@4656: getMapserverUrl()); ingo@1792: context.put("SHAPEFILEPATH", ingo@1792: getShapefileBaseDir().getCanonicalPath()); ingo@1792: context.put("CONFIGDIR", ingo@1792: Config.getConfigDirectory().getCanonicalPath()); ingo@1792: } ingo@1792: catch (FileNotFoundException fnfe) { ingo@1792: // this is bad christian@4633: logger.warn(fnfe, fnfe); ingo@1792: } ingo@1792: catch (IOException ioe) { ingo@1792: // this is also bad christian@4633: logger.warn(ioe, ioe); ingo@1792: } ingo@1792: ingo@1792: return context; ingo@1792: } ingo@1792: ingo@1792: ingo@1129: /** ingo@1129: * Returns a template specified by model. ingo@1129: * ingo@1129: * @param model The name of the template. ingo@1129: * @return a template. ingo@1129: */ rrenkert@5309: public Template getTemplateByName(String model) { ingo@1129: if (model.indexOf(".vm") < 0) { ingo@1129: model = model.concat(".vm"); ingo@1129: } ingo@1129: ingo@1129: try { ingo@1129: VelocityEngine engine = getVelocityEngine(); ingo@1129: if (engine == null) { ingo@1129: logger.error("Error while fetching VelocityEngine."); ingo@1129: return null; ingo@1129: } ingo@1129: ingo@1129: return engine.getTemplate(model); ingo@1129: } ingo@1129: catch (Exception e) { ingo@1129: logger.warn(e, e); ingo@1129: } ingo@1129: ingo@1129: return null; ingo@1129: } ingo@1129: ingo@1129: ingo@1129: /** ingo@1129: * Returns the mapfile template. ingo@1129: * ingo@1129: * @return the mapfile template. ingo@1129: * @throws Exception if an error occured while reading the configuration. ingo@1129: */ christian@4656: protected Template getMapfileTemplateObj() ingo@1129: throws Exception ingo@1129: { christian@4703: String mapfileName = getMapfileTemplate(); ingo@1129: return getTemplateByName(mapfileName); ingo@1129: } ingo@1129: christian@4656: protected abstract String getMapfilePath(); christian@4656: christian@4656: protected abstract String getMapfileTemplate(); christian@4656: ingo@1129: ingo@1129: /** ingo@1129: * Returns the base directory storing the shapefiles. ingo@1129: * ingo@1129: * @return the shapefile base directory. ingo@1129: * ingo@1129: * @throws FileNotFoundException if no shapefile path is found or ingo@1129: * configured. ingo@1129: */ ingo@1792: public File getShapefileBaseDir() christian@3306: throws FileNotFoundException, IOException ingo@1129: { ingo@1129: if (shapefileDirectory == null) { teichmann@5865: String path = RiverUtils.getXPathString( teichmann@5865: RiverUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); ingo@1129: ingo@1129: if (path != null) { ingo@1129: shapefileDirectory = new File(path); ingo@1129: } ingo@1129: ingo@1775: if (shapefileDirectory == null) { ingo@1129: throw new FileNotFoundException("No shapefile directory given"); ingo@1129: } ingo@1775: ingo@1775: if (!shapefileDirectory.exists()) { christian@3306: shapefileDirectory.mkdirs(); ingo@1775: } ingo@1129: } ingo@1129: ingo@1129: return shapefileDirectory; ingo@1129: } ingo@1129: ingo@1129: ingo@1129: protected File[] getUserDirs() christian@3306: throws FileNotFoundException, IOException ingo@1129: { ingo@1129: File baseDir = getShapefileBaseDir(); ingo@1129: File[] artifactDirs = baseDir.listFiles(); ingo@1129: ingo@1129: // TODO ONLY RETURN DIRECTORIES OF THE SPECIFIED USER ingo@1129: ingo@1129: return artifactDirs; ingo@1129: } ingo@1129: ingo@1129: ingo@1129: ingo@1781: protected List parseLayers(File[] dirs) { ingo@1781: List layers = new ArrayList(); ingo@1129: ingo@1129: for (File dir: dirs) { ingo@1781: File[] layerFiles = dir.listFiles(new FilenameFilter() { ingo@1781: @Override ingo@1781: public boolean accept(File directory, String name) { ingo@1781: return name.startsWith(MS_LAYER_PREFIX); ingo@1781: } ingo@1781: }); ingo@1129: ingo@1781: for (File layer: layerFiles) { ingo@1781: try { ingo@1781: layers.add(layer.getCanonicalPath()); ingo@1781: } ingo@1781: catch (IOException ioe) { ingo@1781: logger.warn(ioe, ioe); ingo@1134: } ingo@1129: } ingo@1129: } ingo@1129: ingo@1129: return layers; ingo@1129: } ingo@1129: ingo@1129: ingo@1792: ingo@1792: ingo@1792: /** ingo@1781: * Creates a layer snippet which might be included in the mapfile. ingo@1781: * ingo@1781: * @param layerinfo A LayerInfo object that contains all necessary ingo@1781: * information to build a Mapserver LAYER section. ingo@1781: * @param dir The base dir for the LAYER snippet. ingo@1781: * @param filename The name of the file that is written. ingo@1781: * @param tpl The Velocity template which is used to create the LAYER ingo@1781: * section. ingo@1781: */ rrenkert@5309: public void writeLayer( christian@4656: LayerInfo layerInfo, christian@4656: File layerFile, ingo@1775: Template tpl ingo@1775: ) ingo@1775: throws FileNotFoundException ingo@1775: { ingo@1775: if (logger.isDebugEnabled()) { ingo@1775: logger.debug("Write layer for:"); christian@4656: logger.debug(" directory/file: " + layerFile.getName()); ingo@1775: } ingo@1775: ingo@1775: Writer writer = null; ingo@1775: ingo@1775: try { christian@4656: writer = new FileWriter(layerFile); ingo@1775: ingo@1792: VelocityContext context = getVelocityContext(); christian@4656: context.put("LAYER", layerInfo); ingo@1775: ingo@1775: tpl.merge(context, writer); ingo@1775: } ingo@1775: catch (FileNotFoundException fnfe) { ingo@1775: logger.error(fnfe, fnfe); ingo@1775: } ingo@1775: catch (IOException ioe) { ingo@1775: logger.error(ioe, ioe); ingo@1775: } ingo@1775: catch (Exception e) { ingo@1775: logger.error(e, e); ingo@1775: } ingo@1775: finally { ingo@1775: try { ingo@1775: if (writer != null) { ingo@1775: writer.close(); ingo@1775: } ingo@1775: } ingo@1775: catch (IOException ioe) { ingo@1775: logger.debug(ioe, ioe); ingo@1775: } ingo@1775: } ingo@1775: } ingo@1775: ingo@1775: ingo@1129: /** ingo@1129: * Creates a mapfile with the layer information stored in layers. ingo@1129: * ingo@1129: * @param layers Layer information. ingo@1129: */ rrenkert@5309: public void writeMapfile(List layers) { ingo@1129: String tmpMapName = "mapfile" + new Date().getTime(); ingo@1129: christian@4656: File mapfile = new File(getMapfilePath()); ingo@1129: ingo@1129: File tmp = null; ingo@1129: Writer writer = null; ingo@1129: ingo@1129: try { ingo@1129: tmp = new File(mapfile.getParent(), tmpMapName); ingo@1129: tmp.createNewFile(); ingo@1129: ingo@1129: writer = new FileWriter(tmp); ingo@1129: ingo@1792: VelocityContext context = getVelocityContext(); ingo@1781: context.put("LAYERS", layers); ingo@1129: christian@4656: Template mapTemplate = getMapfileTemplateObj(); ingo@1129: if (mapTemplate == null) { ingo@1129: logger.warn("No mapfile template found."); ingo@1129: return; ingo@1129: } ingo@1129: ingo@1129: mapTemplate.merge(context, writer); ingo@1129: ingo@1129: // we need to create a temporary mapfile first und rename it into ingo@1129: // real mapfile because we don't run into race conditions on this ingo@1129: // way. (iw) ingo@1129: tmp.renameTo(mapfile); ingo@1129: } ingo@1129: catch (FileNotFoundException fnfe) { ingo@1129: logger.error(fnfe, fnfe); ingo@1129: } ingo@1129: catch (IOException ioe) { ingo@1129: logger.error(ioe, ioe); ingo@1129: } ingo@1129: catch (Exception e) { ingo@1129: logger.error(e, e); ingo@1129: } ingo@1129: finally { ingo@1129: try { ingo@1129: if (writer != null) { ingo@1129: writer.close(); ingo@1129: } ingo@1129: ingo@1129: if (tmp.exists()) { ingo@1129: tmp.delete(); ingo@1129: } ingo@1129: } ingo@1129: catch (IOException ioe) { ingo@1129: logger.debug(ioe, ioe); ingo@1129: } ingo@1129: } ingo@1129: } ingo@1129: } ingo@1129: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :