christian@5022: package de.intevation.flys.mapserver; christian@5022: christian@5022: import de.intevation.artifacts.common.utils.Config; christian@5022: import de.intevation.flys.artifacts.model.LayerInfo; christian@5022: import de.intevation.flys.utils.FLYSUtils; christian@5022: christian@5022: import java.io.File; christian@5022: import java.io.FileNotFoundException; christian@5022: import java.io.FileWriter; christian@5022: import java.io.FilenameFilter; christian@5022: import java.io.IOException; christian@5022: import java.io.Writer; christian@5022: import java.util.ArrayList; christian@5022: import java.util.Date; christian@5022: import java.util.List; christian@5022: christian@5022: import org.apache.log4j.Logger; christian@5022: import org.apache.velocity.Template; christian@5022: import org.apache.velocity.VelocityContext; christian@5022: import org.apache.velocity.app.VelocityEngine; christian@5022: import org.apache.velocity.runtime.RuntimeConstants; christian@5022: christian@5022: /** christian@5022: * This class iterates over a bunch of directories, searches for meta christian@5022: * information coresponding to shapefiles and creates a mapfile which is used by christian@5022: * a MapServer. christian@5022: * christian@5022: * @author Ingo Weinzierl christian@5022: */ christian@5022: public abstract class MapfileGenerator christian@5022: { christian@5022: public static final String WSPLGEN_RESULT_SHAPE = "wsplgen.shp"; christian@5022: public static final String WSPLGEN_LINES_SHAPE = "barrier_lines.shp"; christian@5022: public static final String WSPLGEN_POLYGONS_SHAPE = "barrier_polygons.shp"; christian@5022: public static final String WSPLGEN_USER_SHAPE = "user-rgd.shp"; christian@5022: christian@5022: public static final String WSPLGEN_LAYER_TEMPLATE = "wsplgen_layer.vm"; christian@5022: public static final String SHP_LAYER_TEMPLATE = "shapefile_layer.vm"; christian@5022: public static final String DB_LAYER_TEMPLATE = "db_layer.vm"; christian@5022: public static final String RIVERAXIS_LAYER_TEMPLATE = "riveraxis-layer.vm"; christian@5022: christian@5023: public static final String MS_PREFIX_WSPLGEN = "wsplgen-"; christian@5023: public static final String MS_PREFIX_BARRIERS = "barriers-"; christian@5023: // public static final String MS_LINE_PREFIX = "lines-"; christian@5023: // public static final String MS_POLYGONS_PREFIX = "polygons-"; christian@5023: // public static final String MS_LAYER_PREFIX = "ms_layer-"; christian@5023: public static final String MS_PREFIX_USER = "user-"; christian@5022: christian@5022: private static Logger logger = Logger.getLogger(MapfileGenerator.class); christian@5022: christian@5022: private File shapefileDirectory; christian@5022: christian@5022: private VelocityEngine velocityEngine; christian@5022: christian@5022: christian@5022: protected MapfileGenerator() { christian@5022: } christian@5022: christian@5022: christian@5022: /** christian@5022: * Method to check the existance of a template file. christian@5022: * christian@5022: * @param templateID The name of a template. christian@5022: * @return true, of the template exists - otherwise false. christian@5022: */ christian@5023: protected boolean templateExists(String templateID){ christian@5022: Template template = getTemplateByName(templateID); christian@5022: return template != null; christian@5022: } christian@5022: christian@5022: christian@5023: /** christian@5023: * Starts the mapfile generation. This is the main entry point for christian@5023: * the mapfile generation, all other methods of this class/package christian@5023: * *should* be non-public. christian@5023: * @throws Exception christian@5023: */ christian@5022: public abstract void generate() throws Exception; christian@5022: christian@5022: christian@5022: /** christian@5022: * Returns the VelocityEngine used for the template mechanism. christian@5022: * christian@5022: * @return the velocity engine. christian@5022: */ christian@5022: protected VelocityEngine getVelocityEngine() { christian@5022: if (velocityEngine == null) { christian@5022: velocityEngine = new VelocityEngine(); christian@5022: try { christian@5022: setupVelocity(velocityEngine); christian@5022: } christian@5022: catch (Exception e) { christian@5022: logger.error(e, e); christian@5022: return null; christian@5022: } christian@5022: } christian@5022: return velocityEngine; christian@5022: } christian@5022: christian@5022: christian@5022: /** christian@5022: * Initialize velocity. christian@5022: * christian@5022: * @param engine Velocity engine. christian@5022: * @throws Exception if an error occured while initializing velocity. christian@5022: */ christian@5022: protected void setupVelocity(VelocityEngine engine) christian@5022: throws Exception christian@5022: { christian@5022: engine.setProperty( christian@5022: "input.encoding", christian@5022: "UTF-8"); christian@5022: christian@5022: engine.setProperty( christian@5022: RuntimeConstants.RUNTIME_LOG, christian@5022: getVelocityLogfile()); christian@5022: christian@5022: engine.setProperty( christian@5022: "resource.loader", christian@5022: "file"); christian@5022: christian@5022: engine.setProperty( christian@5022: "file.resource.loader.path", christian@5022: getMapserverTemplatePath()); christian@5022: christian@5022: engine.init(); christian@5022: } christian@5022: christian@5022: protected abstract String getVelocityLogfile(); christian@5022: christian@5022: protected abstract String getMapserverTemplatePath(); christian@5022: christian@5022: protected abstract String getMapserverUrl(); christian@5022: christian@5022: protected VelocityContext getVelocityContext() { christian@5022: VelocityContext context = new VelocityContext(); christian@5022: christian@5022: try { christian@5022: context.put("MAPSERVERURL", christian@5022: getMapserverUrl()); christian@5022: context.put("SHAPEFILEPATH", christian@5022: getShapefileBaseDir().getCanonicalPath()); christian@5022: context.put("CONFIGDIR", christian@5022: Config.getConfigDirectory().getCanonicalPath()); christian@5022: } christian@5022: catch (FileNotFoundException fnfe) { christian@5022: // this is bad christian@5022: logger.warn(fnfe, fnfe); christian@5022: } christian@5022: catch (IOException ioe) { christian@5022: // this is also bad christian@5022: logger.warn(ioe, ioe); christian@5022: } christian@5022: christian@5022: return context; christian@5022: } christian@5022: christian@5022: christian@5022: /** christian@5022: * Returns a template specified by model. christian@5022: * christian@5022: * @param model The name of the template. christian@5022: * @return a template. christian@5022: */ christian@5022: protected Template getTemplateByName(String model) { christian@5022: if (model.indexOf(".vm") < 0) { christian@5022: model = model.concat(".vm"); christian@5022: } christian@5022: christian@5022: try { christian@5022: VelocityEngine engine = getVelocityEngine(); christian@5022: if (engine == null) { christian@5022: logger.error("Error while fetching VelocityEngine."); christian@5022: return null; christian@5022: } christian@5022: christian@5022: return engine.getTemplate(model); christian@5022: } christian@5022: catch (Exception e) { christian@5022: logger.warn(e, e); christian@5022: } christian@5022: christian@5022: return null; christian@5022: } christian@5022: christian@5022: christian@5022: /** christian@5022: * Returns the mapfile template. christian@5022: * christian@5022: * @return the mapfile template. christian@5022: * @throws Exception if an error occured while reading the configuration. christian@5022: */ christian@5022: protected Template getMapfileTemplateObj() christian@5022: throws Exception christian@5022: { christian@5022: String mapfileName = getMapfileTemplate(); christian@5022: return getTemplateByName(mapfileName); christian@5022: } christian@5022: christian@5022: protected abstract String getMapfilePath(); christian@5022: christian@5022: protected abstract String getMapfileTemplate(); christian@5022: christian@5022: christian@5022: /** christian@5022: * Returns the base directory storing the shapefiles. christian@5022: * christian@5022: * @return the shapefile base directory. christian@5022: * christian@5022: * @throws FileNotFoundException if no shapefile path is found or christian@5022: * configured. christian@5022: */ christian@5022: public File getShapefileBaseDir() christian@5022: throws FileNotFoundException, IOException christian@5022: { christian@5022: if (shapefileDirectory == null) { christian@5022: String path = FLYSUtils.getXPathString( christian@5022: FLYSUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); christian@5022: christian@5022: if (path != null) { christian@5022: shapefileDirectory = new File(path); christian@5022: } christian@5022: christian@5022: if (shapefileDirectory == null) { christian@5022: throw new FileNotFoundException("No shapefile directory given"); christian@5022: } christian@5022: christian@5022: if (!shapefileDirectory.exists()) { christian@5022: shapefileDirectory.mkdirs(); christian@5022: } christian@5022: } christian@5022: christian@5022: return shapefileDirectory; christian@5022: } christian@5022: christian@5022: christian@5023: protected File[] getProjectDirs() christian@5022: throws FileNotFoundException, IOException christian@5022: { christian@5022: File baseDir = getShapefileBaseDir(); christian@5022: File[] artifactDirs = baseDir.listFiles(); christian@5022: christian@5022: return artifactDirs; christian@5022: } christian@5022: christian@5022: christian@5023: /** christian@5023: * Search in all given directories for shapefiles that can be used christian@5023: * as barrier, user oder wsplgen layers. christian@5023: * @param dirs christian@5023: * @return christian@5023: */ christian@5023: protected List searchForLayerShapes(File[] dirs) { christian@5023: List shapes = new ArrayList(); christian@5022: christian@5022: for (File dir: dirs) { christian@5022: File[] layerFiles = dir.listFiles(new FilenameFilter() { christian@5022: @Override christian@5022: public boolean accept(File directory, String name) { christian@5023: return name.startsWith(MS_PREFIX_BARRIERS) || christian@5023: name.startsWith(MS_PREFIX_USER) || christian@5023: name.startsWith(MS_PREFIX_WSPLGEN); christian@5022: } christian@5022: }); christian@5022: christian@5022: for (File layer: layerFiles) { christian@5023: shapes.add(layer); christian@5022: } christian@5022: } christian@5022: christian@5023: return shapes; christian@5022: } christian@5022: christian@5022: christian@5022: /** christian@5022: * Creates a layer snippet which might be included in the mapfile. christian@5022: * christian@5022: * @param layerinfo A LayerInfo object that contains all necessary christian@5022: * information to build a Mapserver LAYER section. christian@5022: * @param dir The base dir for the LAYER snippet. christian@5022: * @param filename The name of the file that is written. christian@5022: * @param tpl The Velocity template which is used to create the LAYER christian@5022: * section. christian@5022: */ christian@5022: protected void writeLayer( christian@5022: LayerInfo layerInfo, christian@5022: File layerFile, christian@5022: Template tpl christian@5022: ) christian@5022: throws FileNotFoundException christian@5022: { christian@5022: if (logger.isDebugEnabled()) { christian@5022: logger.debug("Write layer for:"); christian@5022: logger.debug(" directory/file: " + layerFile.getName()); christian@5022: } christian@5022: christian@5022: Writer writer = null; christian@5022: christian@5022: try { christian@5022: writer = new FileWriter(layerFile); christian@5022: christian@5022: VelocityContext context = getVelocityContext(); christian@5022: context.put("LAYER", layerInfo); christian@5022: christian@5022: tpl.merge(context, writer); christian@5022: } christian@5022: catch (FileNotFoundException fnfe) { christian@5022: logger.error(fnfe, fnfe); christian@5022: } christian@5022: catch (IOException ioe) { christian@5022: logger.error(ioe, ioe); christian@5022: } christian@5022: catch (Exception e) { christian@5022: logger.error(e, e); christian@5022: } christian@5022: finally { christian@5022: try { christian@5022: if (writer != null) { christian@5022: writer.close(); christian@5022: } christian@5022: } christian@5022: catch (IOException ioe) { christian@5022: logger.debug(ioe, ioe); christian@5022: } christian@5022: } christian@5022: } christian@5022: christian@5022: christian@5022: /** christian@5022: * Creates a mapfile with the layer information stored in layers. christian@5022: * christian@5022: * @param layers Layer information. christian@5022: */ christian@5022: protected void writeMapfile(List layers) { christian@5022: String tmpMapName = "mapfile" + new Date().getTime(); christian@5022: christian@5022: File mapfile = new File(getMapfilePath()); christian@5022: christian@5022: File tmp = null; christian@5022: Writer writer = null; christian@5022: christian@5022: try { christian@5022: tmp = new File(mapfile.getParent(), tmpMapName); christian@5022: tmp.createNewFile(); christian@5022: christian@5022: writer = new FileWriter(tmp); christian@5022: christian@5022: VelocityContext context = getVelocityContext(); christian@5022: context.put("LAYERS", layers); christian@5022: christian@5022: Template mapTemplate = getMapfileTemplateObj(); christian@5022: if (mapTemplate == null) { christian@5022: logger.warn("No mapfile template found."); christian@5022: return; christian@5022: } christian@5022: christian@5022: mapTemplate.merge(context, writer); christian@5022: christian@5022: // we need to create a temporary mapfile first und rename it into christian@5022: // real mapfile because we don't run into race conditions on this christian@5022: // way. (iw) christian@5022: tmp.renameTo(mapfile); christian@5022: } christian@5022: catch (FileNotFoundException fnfe) { christian@5022: logger.error(fnfe, fnfe); christian@5022: } christian@5022: catch (IOException ioe) { christian@5022: logger.error(ioe, ioe); christian@5022: } christian@5022: catch (Exception e) { christian@5022: logger.error(e, e); christian@5022: } christian@5022: finally { christian@5022: try { christian@5022: if (writer != null) { christian@5022: writer.close(); christian@5022: } christian@5022: christian@5022: if (tmp.exists()) { christian@5022: tmp.delete(); christian@5022: } christian@5022: } christian@5022: catch (IOException ioe) { christian@5022: logger.debug(ioe, ioe); christian@5022: } christian@5022: } christian@5022: } christian@5022: } christian@5022: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :