# HG changeset patch # User Raimund Renkert # Date 1335339900 0 # Node ID a78dafdd85901dc9a141effc4c9ce5ca15169f87 # Parent ccad7a6ddaa4fd9800ff6e377e08d628365b7dc7 Issue 657. Added file upload service to load a user defined shapefile. User the shapefile for wsplgen calculation and display a new layer. flys-artifacts/trunk@4292 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r ccad7a6ddaa4 -r a78dafdd8590 flys-artifacts/ChangeLog --- a/flys-artifacts/ChangeLog Thu Apr 19 11:49:57 2012 +0000 +++ b/flys-artifacts/ChangeLog Wed Apr 25 07:45:00 2012 +0000 @@ -1,3 +1,42 @@ +2012-04-18 Raimund Renkert + + Issue 657. + + * src/main/java/de/intevation/flys/artifacts/services/FileUploadService.java: + New. Service to upload a file as base64 string embedded in xml structure. + + * src/main/java/de/intevation/flys/artifacts/states/FloodMapState.java: + Extract shape files from zip archive and move them to artifact directory. + Add the user shapefile as parameter for wsplgen calculation. + + * src/main/java/de/intevation/flys/artifacts/states/ScenarioSelect.java: + Remove the artifact directory on step back. + + * src/main/java/de/intevation/flys/utils/MapfileGenerator.java, + src/main/java/de/intevation/flys/exports/MapGenerator.java: + Create layer to display the uploaded shapefile. + + * src/main/java/de/intevation/flys/wsplgen/FacetCreator.java: + Create a facet to output the user defined layer. + + * src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java: + Added type for user shape file. + + * src/main/java/de/intevation/flys/artifacts/model/WSPLGENJob.java: + Resized array for '-lin' parameter. + + * doc/conf/artifacts/winfo.xml: + Added facet to diplay user defined shapefile. + + * doc/conf/conf.xml: + Added file upload service. + + * src/main/resources/messages.properties, + src/main/resources/messages_de_DE.properties, + src/main/resources/messages_en.properties, + src/main/resources/messages_de.properties: + Added i18n string. + 2012-04-18 Raimund Renkert Issue 560. diff -r ccad7a6ddaa4 -r a78dafdd8590 flys-artifacts/doc/conf/artifacts/winfo.xml --- a/flys-artifacts/doc/conf/artifacts/winfo.xml Thu Apr 19 11:49:57 2012 +0000 +++ b/flys-artifacts/doc/conf/artifacts/winfo.xml Wed Apr 25 07:45:00 2012 +0000 @@ -458,6 +458,7 @@ + diff -r ccad7a6ddaa4 -r a78dafdd8590 flys-artifacts/doc/conf/conf.xml --- a/flys-artifacts/doc/conf/conf.xml Thu Apr 19 11:49:57 2012 +0000 +++ b/flys-artifacts/doc/conf/conf.xml Wed Apr 25 07:45:00 2012 +0000 @@ -135,6 +135,10 @@ name="gaugeinfo" service="de.intevation.flys.artifacts.services.GaugeInfoService" description="Returns an overview of the fixings of a given river.">de.intevation.artifactdatabase.DefaultServiceFactory + de.intevation.artifactdatabase.DefaultServiceFactory diff -r ccad7a6ddaa4 -r a78dafdd8590 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java Thu Apr 19 11:49:57 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java Wed Apr 25 07:45:00 2012 +0000 @@ -65,6 +65,7 @@ String FLOODMAP_WSPLGEN = "floodmap.wsplgen"; String FLOODMAP_BARRIERS = "floodmap.barriers"; + String FLOODMAP_USERSHAPE = "floodmap.usershape"; String FLOODMAP_RIVERAXIS = "floodmap.riveraxis"; String FLOODMAP_WMSBACKGROUND = "floodmap.wmsbackground"; String FLOODMAP_KMS = "floodmap.kms"; diff -r ccad7a6ddaa4 -r a78dafdd8590 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WSPLGENJob.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WSPLGENJob.java Thu Apr 19 11:49:57 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WSPLGENJob.java Wed Apr 25 07:45:00 2012 +0000 @@ -72,7 +72,7 @@ to = Double.NaN; diff = Double.NaN; dist = Double.NaN; - lin = new ArrayList(2); + lin = new ArrayList(3); } diff -r ccad7a6ddaa4 -r a78dafdd8590 flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/FileUploadService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/FileUploadService.java Wed Apr 25 07:45:00 2012 +0000 @@ -0,0 +1,100 @@ +package de.intevation.flys.artifacts.services; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.FileNotFoundException; + +import org.apache.log4j.Logger; + +import org.apache.commons.codec.binary.Base64; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import de.intevation.artifacts.common.ArtifactNamespaceContext; +import de.intevation.artifacts.common.utils.XMLUtils; +import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; +import de.intevation.artifacts.common.utils.FileTools; + +import de.intevation.artifacts.CallMeta; +import de.intevation.artifacts.GlobalContext; + +import de.intevation.flys.utils.FLYSUtils; + +/** + * @author Raimund Renkert + */ +public class FileUploadService extends FLYSService { + + /** The logger used in this service.*/ + private static Logger logger = Logger.getLogger(FileUploadService.class); + + /** XPath that points to the artifact uuid.*/ + public static final String XPATH_ARTIFACT_UUID = + "/upload/artifact-uuid/text()"; + + /** XPath that points to the base64 encoded data.*/ + public static final String XPATH_DATA = "/upload/data/text()"; + + public FileUploadService() { + } + + + @Override + protected Document doProcess( + Document data, + GlobalContext context, + CallMeta callMeta + ) { + logger.debug("FileUploadService.process"); + + String uuid = extractUuid(data); + + byte[] fileData = extractData(data); + if (fileData != null) { + try { + String shapePath = FLYSUtils.getXPathString( + FLYSUtils.XPATH_SHAPEFILE_DIR); + + File artifactDir = FileTools.getDirectory(shapePath, uuid); + FileOutputStream fos = + new FileOutputStream(artifactDir.getCanonicalPath() + + "/user-rgd.zip"); + fos.write(fileData); + fos.close(); + } + catch (IOException ioe) { + logger.warn(ioe, ioe); + } + } + else { + logger.debug("No data in uploaded xml.") + } + + Document doc = XMLUtils.newDocument(); + ElementCreator ec = new ElementCreator(doc, null, null); + Element resp = ec.create("response"); + doc.appendChild(resp); + + return doc; + } + + + protected String extractUuid(Document data) { + return XMLUtils.xpathString( + data, XPATH_ARTIFACT_UUID, ArtifactNamespaceContext.INSTANCE); + } + + + protected byte[] extractData(Document data) { + String b64Data = XMLUtils.xpathString( + data, XPATH_DATA, ArtifactNamespaceContext.INSTANCE); + + if (b64Data != null && b64Data != "") { + byte[] fileData = Base64.decodeBase64(b64Data); + return fileData; + } + return null; + } +} diff -r ccad7a6ddaa4 -r a78dafdd8590 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/FloodMapState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/FloodMapState.java Thu Apr 19 11:49:57 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/FloodMapState.java Wed Apr 25 07:45:00 2012 +0000 @@ -82,6 +82,9 @@ public static final String WSPLGEN_FLOODPLAIN = "talaue.shp"; public static final String WSPLGEN_WSP_FILE = "waterlevel.wst"; public static final String WSPLGEN_OUTPUT_FILE = "wsplgen.shp"; + public static final String WSPLGEN_USER_SHAPE = "user-rgd.shp"; + public static final String WSPLGEN_USER_ZIP = "user-rgd.zip"; + public static final String WSPLGEN_USER_FILENAME = "user-rgd"; public static final int WSPLGEN_DEFAULT_OUTPUT = 0; @@ -265,7 +268,6 @@ logger.info("FloodMapState.endOfLife: " + artifact.identifier()); FLYSArtifact flys = (FLYSArtifact) artifact; - removeDirectory(flys); Scheduler scheduler = Scheduler.getInstance(); scheduler.cancelJob(flys.identifier()); @@ -298,6 +300,7 @@ setGel(artifact, job); setDist(artifact, job); setLine(artifact, facetCreator, artifactDir, job); + setUserShape(artifact, facetCreator, artifactDir, job); setAxis(artifact, artifactDir, job); setPro(artifact, artifactDir, job); setDgm(artifact, job); @@ -471,6 +474,31 @@ } + protected void setUserShape( + FLYSArtifact artifact, + FacetCreator facetCreator, + File dir, + WSPLGENJob job + ) { + File archive = new File(dir, WSPLGEN_USER_ZIP); + boolean exists = archive.exists(); + logger.debug("Zip file exists: " + exists); + if (exists) { + try { + File tmpDir = new File(dir, "usr_tmp"); + FileTools.extractArchive(archive, tmpDir); + moveFiles(tmpDir, dir); + } + catch (IOException ioe) { + logger.warn("Zip archive " + dir + "/" + WSPLGEN_USER_ZIP + " could not be extracted."); + return; + } + + job.addLin(dir + "/" + WSPLGEN_USER_SHAPE); + facetCreator.createUserShapeFacet(); + } + } + protected SimpleFeatureType getBarriersFeatureType( String name, String srs, @@ -808,5 +836,42 @@ } } } + + + protected void moveFiles(File source, final File target) + throws IOException + { + if (!source.exists()) { + return; + } + if (!target.exists()) { + target.mkdir(); + } + FileTools.walkTree(source, new FileTools.FileVisitor() { + public boolean visit(File file) { + if (!file.isDirectory()) { + String name = file.getName(); + String suffix = ""; + int pos = name.lastIndexOf('.'); + if (pos > 0 && pos < name.length() - 1) { + suffix = name.substring(pos + 1); + } + else { + return true; + } + try { + FileTools.copyFile(file, new File(target, WSPLGEN_USER_FILENAME + "." + suffix)); + } + catch (IOException ioe) { + logger.warn ("Error while copying file " + file.getName()); + return true; + } + } + return true; + } + }); + + FileTools.deleteRecursive(source); + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r ccad7a6ddaa4 -r a78dafdd8590 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ScenarioSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ScenarioSelect.java Thu Apr 19 11:49:57 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/ScenarioSelect.java Wed Apr 25 07:45:00 2012 +0000 @@ -1,5 +1,8 @@ package de.intevation.flys.artifacts.states; +import java.util.List; +import java.io.File; + import org.apache.log4j.Logger; import org.w3c.dom.Element; @@ -10,11 +13,14 @@ import de.intevation.artifacts.common.utils.XMLUtils; import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; +import de.intevation.artifacts.common.utils.FileTools; import de.intevation.artifactdatabase.ProtocolUtils; +import de.intevation.artifactdatabase.state.Facet; import de.intevation.flys.artifacts.FLYSArtifact; import de.intevation.flys.artifacts.resources.Resources; +import de.intevation.flys.utils.FLYSUtils; /** * @author Ingo Weinzierl @@ -116,5 +122,38 @@ return item; } + + + + @Override + public void endOfLife(Artifact artifact, Object callContext) { + super.endOfLife(artifact, callContext); + logger.info("ScenarioSelect.endOfLife: " + artifact.identifier()); + + FLYSArtifact flys = (FLYSArtifact) artifact; + removeDirectory(flys); + } + + + /** + * Removes the directory and all its content where the required data and the + * results of WSPLGEN are stored. Should be called in endOfLife(). + */ + protected void removeDirectory(FLYSArtifact artifact) { + String shapePath = FLYSUtils.getXPathString( + FLYSUtils.XPATH_SHAPEFILE_DIR); + + File artifactDir = new File(shapePath, artifact.identifier()); + + if (artifactDir.exists()) { + logger.info("Delete directory: " + artifactDir.getAbsolutePath()); + boolean success = FileTools.deleteRecursive(artifactDir); + } + else { + logger.debug("There is no directory to remove."); + } + } + + } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r ccad7a6ddaa4 -r a78dafdd8590 flys-artifacts/src/main/java/de/intevation/flys/exports/MapGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/MapGenerator.java Thu Apr 19 11:49:57 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/MapGenerator.java Wed Apr 25 07:45:00 2012 +0000 @@ -110,6 +110,9 @@ else if (FLOODMAP_BARRIERS.equals(name)) { createBarriersLayer(flys, wms); } + else if (FLOODMAP_USERSHAPE.equals(name)) { + createUserShapeLayer(flys, wms); + } else { createDatabaseLayer(flys, wms, attr); } @@ -160,6 +163,21 @@ } + protected void createUserShapeLayer(FLYSArtifact flys, WMSLayerFacet wms) { + MapfileGenerator mfg = MapfileGenerator.getInstance(); + + try { + mfg.createUserShapeLayer(flys, wms); + } + catch (FileNotFoundException fnfe) { + logger.error(fnfe, fnfe); + } + catch (IOException ioe) { + logger.error(ioe, ioe); + } + } + + protected void createDatabaseLayer( FLYSArtifact flys, WMSLayerFacet wms, diff -r ccad7a6ddaa4 -r a78dafdd8590 flys-artifacts/src/main/java/de/intevation/flys/utils/MapfileGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/utils/MapfileGenerator.java Thu Apr 19 11:49:57 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/utils/MapfileGenerator.java Wed Apr 25 07:45:00 2012 +0000 @@ -13,6 +13,10 @@ import org.apache.log4j.Logger; +import org.geotools.data.shapefile.ShpFiles; +import org.geotools.data.shapefile.shp.ShapefileReader; +import org.geotools.data.shapefile.shp.ShapefileHeader; + import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; @@ -40,16 +44,18 @@ 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 WSPLGEN_USER_SHAPE = "user-rgd.shp"; public static final String WSPLGEN_LAYER_TEMPLATE = "wsplgen_layer.vm"; public static final String SHP_LAYER_TEMPLATE = "shapefile_layer.vm"; public static final String DB_LAYER_TEMPLATE = "db_layer.vm"; - public static final String MS_WSPLGEN_PREFIX = "wsplgen-"; - public static final String MS_BARRIERS_PREFIX = "barriers-"; - public static final String MS_LINE_PREFIX = "lines-"; - public static final String MS_POLYGONS_PREFIX = "polygons-"; - public static final String MS_LAYER_PREFIX = "ms_layer-"; + public static final String MS_WSPLGEN_PREFIX = "wsplgen-"; + public static final String MS_BARRIERS_PREFIX = "barriers-"; + public static final String MS_LINE_PREFIX = "lines-"; + public static final String MS_POLYGONS_PREFIX = "polygons-"; + public static final String MS_LAYER_PREFIX = "ms_layer-"; + public static final String MS_USERSHAPE_PREFIX = "user-"; protected static final long SLEEPTIME = 10 * 1000L; // 10 seconds @@ -517,6 +523,71 @@ /** + * Creates a layer file used for Mapserver's mapfile which represents the + * shape files uploaded by the user. + * + * @param flys The FLYSArtifact that owns wms. + * @param wms The WMSLayerFacet that contains information for the layer. + */ + public void createUserShapeLayer(FLYSArtifact flys, WMSLayerFacet wms) + throws FileNotFoundException, IOException + { + logger.debug("createUserShapeLayer"); + + String uuid = flys.identifier(); + File dir = new File(getShapefileBaseDir(), uuid); + File test = new File(dir, WSPLGEN_USER_SHAPE); + + if (!test.exists() || !test.canRead()) { + logger.debug("No user layer existing."); + return; + } + + File userShape = new File(dir, WSPLGEN_USER_SHAPE); + ShpFiles sf = new ShpFiles(userShape); + ShapefileReader sfr = new ShapefileReader(sf, true, false, null); + ShapefileHeader sfh = sfr.getHeader(); + + String group = uuid + MS_USERSHAPE_PREFIX; + String groupTitle = "I18N_USER_SHAPE_TITLE"; + + LayerInfo info = new LayerInfo(); + info.setName(MS_USERSHAPE_PREFIX + uuid); + if (sfh.getShapeType().isLineType()) { + info.setType("LINE"); + } + else if (sfh.getShapeType().isPolygonType()) { + info.setType("POLYGON"); + } + else { + return; + } + info.setDirectory(uuid); + info.setData(WSPLGEN_USER_SHAPE); + info.setTitle("I18N_USER_SHAPE"); + info.setGroup(group); + info.setGroupTitle(groupTitle); + + String nameUser = MS_LAYER_PREFIX + wms.getName(); + + Template tpl = getTemplateByName(SHP_LAYER_TEMPLATE); + if (tpl == null) { + logger.warn("Template '" + SHP_LAYER_TEMPLATE + "' found."); + return; + } + + try { + writeLayer(info, dir, nameUser, tpl); + } + catch (FileNotFoundException fnfe) { + logger.error(fnfe, fnfe); + logger.warn("Unable to write layer: " + nameUser); + } + + } + + + /** * Creates a layer file used for Mapserver's mapfile which represents * geometries from database. * diff -r ccad7a6ddaa4 -r a78dafdd8590 flys-artifacts/src/main/java/de/intevation/flys/wsplgen/FacetCreator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/wsplgen/FacetCreator.java Thu Apr 19 11:49:57 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/wsplgen/FacetCreator.java Wed Apr 25 07:45:00 2012 +0000 @@ -26,10 +26,12 @@ public class FacetCreator implements FacetTypes { - public static final String I18N_WSPLGEN_RESULT = "floodmap.uesk"; - public static final String I18N_WSPLGEN_DEFAULT = "floodmap.uesk"; - public static final String I18N_BARRIERS = "floodmap.barriers"; - public static final String I18N_BARRIERS_DEFAULT = "floodmap.barriers"; + public static final String I18N_WSPLGEN_RESULT = "floodmap.uesk"; + public static final String I18N_WSPLGEN_DEFAULT = "floodmap.uesk"; + public static final String I18N_BARRIERS = "floodmap.barriers"; + public static final String I18N_BARRIERS_DEFAULT = "floodmap.barriers"; + public static final String I18N_USERSHAPE = "floodmap.usershape"; + public static final String I18N_USERSHAPE_DEFAULT = "floodmap.usershape"; protected FLYSArtifact artifact; @@ -158,6 +160,28 @@ } + public void createUserShapeFacet() { + WMSLayerFacet shape = new WMSLayerFacet( + 1, + FLOODMAP_USERSHAPE, + Resources.getMsg( + cc.getMeta(), + I18N_USERSHAPE, + I18N_USERSHAPE_DEFAULT), + ComputeType.ADVANCE, + stateId, + hash, + getUrl()); + + shape.addLayer( + MapfileGenerator.MS_USERSHAPE_PREFIX + artifact.identifier()); + shape.setSrid(getSrid()); + shape.setExtent(getBounds()); + + tmpFacets.add(shape); + } + + public void finish() { facets.addAll(getFacets()); } diff -r ccad7a6ddaa4 -r a78dafdd8590 flys-artifacts/src/main/resources/messages.properties --- a/flys-artifacts/src/main/resources/messages.properties Thu Apr 19 11:49:57 2012 +0000 +++ b/flys-artifacts/src/main/resources/messages.properties Wed Apr 25 07:45:00 2012 +0000 @@ -174,6 +174,7 @@ floodmap.buildings = Buildings floodmap.fixpoints = Fixpoints floodmap.floodmaps = Floodmaps +floodmap.usershape = User data wsplgen.job.queued = WSPLGEN job in queue. wsplgen.job.error = An unexpected error while starting WSPLGEN occured. diff -r ccad7a6ddaa4 -r a78dafdd8590 flys-artifacts/src/main/resources/messages_de.properties --- a/flys-artifacts/src/main/resources/messages_de.properties Thu Apr 19 11:49:57 2012 +0000 +++ b/flys-artifacts/src/main/resources/messages_de.properties Wed Apr 25 07:45:00 2012 +0000 @@ -174,6 +174,7 @@ floodmap.buildings = Bauwerke floodmap.fixpoints = Festpunkte floodmap.floodmaps = \u00dcberschwemmungsfl\u00e4che +floodmap.usershape = Benutzerdaten wsplgen.job.queued = WSPLGEN Berechnung befindet sich in Warteschlange. wsplgen.job.error = Ein unerwarteter Fehler beim Starten von WSPLGEN ist aufgetreten. diff -r ccad7a6ddaa4 -r a78dafdd8590 flys-artifacts/src/main/resources/messages_de_DE.properties --- a/flys-artifacts/src/main/resources/messages_de_DE.properties Thu Apr 19 11:49:57 2012 +0000 +++ b/flys-artifacts/src/main/resources/messages_de_DE.properties Wed Apr 25 07:45:00 2012 +0000 @@ -173,6 +173,7 @@ floodmap.buildings = Bauwerke floodmap.fixpoints = Festpunkte floodmap.floodmaps = \u00dcberschwemmungsfl\u00e4che +floodmap.usershape = Benutzerdaten wsplgen.job.queued = WSPLGEN Berechnung befindet sich in Warteschlange. wsplgen.job.error = Ein unerwarteter Fehler beim Starten von WSPLGEN ist aufgetreten. diff -r ccad7a6ddaa4 -r a78dafdd8590 flys-artifacts/src/main/resources/messages_en.properties --- a/flys-artifacts/src/main/resources/messages_en.properties Thu Apr 19 11:49:57 2012 +0000 +++ b/flys-artifacts/src/main/resources/messages_en.properties Wed Apr 25 07:45:00 2012 +0000 @@ -173,6 +173,7 @@ floodmap.buildings = Buildings floodmap.fixpoints = Fixpoints floodmap.floodmaps = Floodmaps +floodmap.usershape = User data wsplgen.job.queued = WSPLGEN job in queue. wsplgen.job.error = An unexpected error while starting WSPLGEN occured.