Java tutorial
/* * Copyright (C) 2011-2013 B3Partners B.V. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package nl.b3p.viewer.admin.stripes; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.StringReader; import java.io.StringWriter; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Queue; import javax.annotation.security.RolesAllowed; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import net.sourceforge.stripes.action.*; import net.sourceforge.stripes.validation.*; import nl.b3p.viewer.config.ClobElement; import nl.b3p.viewer.config.app.Application; import nl.b3p.viewer.config.app.ApplicationLayer; import nl.b3p.viewer.config.security.Group; import nl.b3p.viewer.config.services.ArcGISService; import nl.b3p.viewer.config.services.ArcIMSService; import nl.b3p.viewer.config.services.AttributeDescriptor; import nl.b3p.viewer.config.services.BoundingBox; import nl.b3p.viewer.config.services.Category; import nl.b3p.viewer.config.services.CoordinateReferenceSystem; import nl.b3p.viewer.config.services.FeatureSource; import nl.b3p.viewer.config.services.GeoService; import nl.b3p.viewer.config.services.Layer; import nl.b3p.viewer.config.services.StyleLibrary; import nl.b3p.viewer.config.services.TileService; import nl.b3p.viewer.config.services.TileSet; import nl.b3p.viewer.config.services.Updatable; import nl.b3p.viewer.config.services.UpdateResult; import nl.b3p.viewer.config.services.WMSService; import nl.b3p.viewer.util.SelectedContentCache; import nl.b3p.web.WaitPageStatus; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.logging.*; import org.geotools.filter.FilterTransformer; import org.geotools.filter.text.cql2.CQL; import org.json.*; import org.opengis.filter.Filter; import org.stripesstuff.plugin.waitpage.WaitPage; import org.stripesstuff.stripersist.Stripersist; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; import org.xml.sax.SAXParseException; /** * * @author Jytte Schaeffer */ @StrictBinding @UrlBinding("/action/geoservice/{service}") @RolesAllowed({ Group.ADMIN, Group.REGISTRY_ADMIN }) public class GeoServiceActionBean implements ActionBean { private static final Log log = LogFactory.getLog(GeoServiceActionBean.class); private static final String JSP = "/WEB-INF/jsp/services/geoservice.jsp"; private static final String JSP_EDIT_SLD = "/WEB-INF/jsp/services/editsld.jsp"; private ActionBeanContext context; @Validate(on = { "add" }, required = true) private Category category; @Validate(on = { "edit" }, required = true) private GeoService service; @Validate(on = "add", required = true) private String url; @Validate(on = "add", required = true) private String protocol; /** * Whether the service was succesfully deleted. Use in view JSP to update * tree. */ private boolean serviceDeleted; @Validate private String name; @Validate private String username; @Validate private String password; @Validate private boolean overrideUrl; @Validate private String serviceName; @Validate private String agsVersion; @Validate private Integer tileSize; @Validate private String tilingProtocol; @Validate private String resolutions; @Validate private String serviceBbox; @Validate private String imageExtension; @Validate private String crs; @Validate private Boolean useIntersect; private WaitPageStatus status; private JSONObject newService; private JSONObject updatedService; @Validate @ValidateNestedProperties({ @Validate(on = "saveSld", field = "title", required = true), @Validate(on = "saveSld", field = "defaultStyle"), @Validate(on = "saveSld", field = "externalUrl"), @Validate(on = "saveSld", field = "sldBody"), @Validate(on = "saveSld", field = "extraLegendParameters") }) private StyleLibrary sld; @Validate private String sldType = "external"; @Validate(on = "cqlToFilter") private String cql; private String generatedSld; private boolean updatable; //<editor-fold defaultstate="collapsed" desc="getters and setters"> public ActionBeanContext getContext() { return context; } public void setContext(ActionBeanContext context) { this.context = context; } public String getServiceName() { return serviceName; } public void setServiceName(String serviceName) { this.serviceName = serviceName; } public GeoService getService() { return service; } public void setService(GeoService service) { this.service = service; } public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getProtocol() { return protocol; } public void setProtocol(String protocol) { this.protocol = protocol; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public WaitPageStatus getStatus() { return status; } public void setStatus(WaitPageStatus status) { this.status = status; } public boolean isOverrideUrl() { return overrideUrl; } public void setOverrideUrl(boolean overrideUrl) { this.overrideUrl = overrideUrl; } public String getAgsVersion() { return agsVersion; } public void setAgsVersion(String agsVersion) { this.agsVersion = agsVersion; } public JSONObject getNewService() { return newService; } public void setNewService(JSONObject newService) { this.newService = newService; } public JSONObject getUpdatedService() { return updatedService; } public void setUpdatedService(JSONObject updatedService) { this.updatedService = updatedService; } public boolean isServiceDeleted() { return serviceDeleted; } public void setServiceDeleted(boolean serviceDeleted) { this.serviceDeleted = serviceDeleted; } public Integer getTileSize() { return tileSize; } public void setTileSize(Integer tileSize) { this.tileSize = tileSize; } public String getTilingProtocol() { return tilingProtocol; } public void setTilingProtocol(String tilingProtocol) { this.tilingProtocol = tilingProtocol; } public String getResolutions() { return resolutions; } public void setResolutions(String resolutions) { this.resolutions = resolutions; } public String getServiceBbox() { return serviceBbox; } public void setServiceBbox(String serviceBbox) { this.serviceBbox = serviceBbox; } public String getImageExtension() { return imageExtension; } public void setImageExtension(String imageExtension) { this.imageExtension = imageExtension; } public String getCrs() { return crs; } public void setCrs(String crs) { this.crs = crs; } public boolean isUpdatable() { return updatable; } public void setUpdatable(boolean updatable) { this.updatable = updatable; } public StyleLibrary getSld() { return sld; } public void setSld(StyleLibrary sld) { this.sld = sld; } public String getSldType() { return sldType; } public void setSldType(String sldType) { this.sldType = sldType; } public String getGeneratedSld() { return generatedSld; } public void setGeneratedSld(String generatedSld) { this.generatedSld = generatedSld; } public String getCql() { return cql; } public void setCql(String cql) { this.cql = cql; } public boolean isUseIntersect() { return useIntersect; } public void setUseIntersect(boolean useIntersect) { this.useIntersect = useIntersect; } //</editor-fold> @DefaultHandler public Resolution edit() { if (service != null) { protocol = service.getProtocol(); url = service.getUrl(); if (protocol.equals(ArcIMSService.PROTOCOL)) { ArcIMSService ser = (ArcIMSService) service; serviceName = ser.getServiceName(); } else if (protocol.equals(ArcGISService.PROTOCOL)) { ClobElement assumeVersion = service.getDetails().get(ArcGISService.DETAIL_ASSUME_VERSION); agsVersion = assumeVersion == null ? null : assumeVersion.getValue(); } else if (protocol.equals(TileService.PROTOCOL)) { TileService ser = (TileService) service; tilingProtocol = ser.getTilingProtocol(); //tiling service has 1 layer with that has the settings. Layer layer = ser.getTilingLayer(); //set the resolutions TileSet tileSet = layer.getTileset(); if (tileSet != null) { String res = ""; for (Double resolution : tileSet.getResolutions()) { if (res.length() > 0) { res += ","; } res += resolution.toString(); } resolutions = res; //set the tilesize tileSize = tileSet.getHeight(); } //set the service Bbox if (layer.getBoundingBoxes().size() == 1) { BoundingBox bb = layer.getBoundingBoxes().values().iterator().next(); serviceBbox = "" + bb.getMinx() + "," + bb.getMiny() + "," + bb.getMaxx() + "," + bb.getMaxy(); crs = bb.getCrs().getName(); } serviceName = layer.getName(); if (layer.getDetails().containsKey("image_extension")) { ClobElement ce = layer.getDetails().get("image_extension"); imageExtension = ce != null ? ce.getValue() : null; } } else if (protocol.equals(WMSService.PROTOCOL)) { overrideUrl = ((WMSService) service).getOverrideUrl(); } if (service.getDetails().containsKey(GeoService.DETAIL_USE_INTERSECT)) { ClobElement ce = service.getDetails().get(GeoService.DETAIL_USE_INTERSECT); useIntersect = Boolean.parseBoolean(ce.getValue()); } name = service.getName(); username = service.getUsername(); password = service.getPassword(); } return new ForwardResolution(JSP); } public Resolution save() { if (name != null) { service.setName(name); } if (service instanceof TileService) { TileService ser = (TileService) service; if (tilingProtocol != null) { ((TileService) service).setTilingProtocol(tilingProtocol); } if (url != null) { ((TileService) service).setUrl(url); } Layer l = ser.getTilingLayer(); if (tileSize != null) { l.getTileset().setWidth(tileSize); l.getTileset().setHeight(tileSize); } if (resolutions != null) { l.getTileset().setResolutions(resolutions); } if (crs != null && serviceBbox != null) { BoundingBox bb = new BoundingBox(); bb.setBounds(serviceBbox); bb.setCrs(new CoordinateReferenceSystem(crs)); l.getBoundingBoxes().clear(); l.getBoundingBoxes().put(bb.getCrs(), bb); } if (StringUtils.isNotBlank(imageExtension)) { l.getDetails().put("image_extension", new ClobElement(imageExtension)); } else if (l.getDetails().containsKey("image_extension")) { l.getDetails().remove("image_extension"); } } if (service instanceof WMSService) { ((WMSService) service).setOverrideUrl(overrideUrl); } if (useIntersect != null) { service.getDetails().put(GeoService.DETAIL_USE_INTERSECT, new ClobElement(useIntersect.toString())); } service.setUsername(username); service.setPassword(password); Stripersist.getEntityManager().persist(service); Stripersist.getEntityManager().getTransaction().commit(); getContext().getMessages().add(new SimpleMessage("De service is opgeslagen")); return edit(); } private List<Application> findApplications() { List<Application> apps = new ArrayList(); List<ApplicationLayer> applicationLayers = Stripersist.getEntityManager() .createQuery("from ApplicationLayer where service = :service").setParameter("service", service) .getResultList(); for (ApplicationLayer appLayer : applicationLayers) { /* * The parent level of the applicationLayer is needed to find out in * which application the Layer is used. This solution is not good * when there are many levels. */ List<Application> applications = Stripersist.getEntityManager().createQuery("from Application") .getResultList(); for (Application app : applications) { if (app.getRoot().containsLayerInSubtree(appLayer)) { apps.add(app); } } } return apps; } public Resolution delete() { /* * XXX Als een service layers heeft die toegevoegd zijn aan een * applicatie mag de service niet verwijderd worden */ List<ApplicationLayer> applicationLayers = Stripersist.getEntityManager() .createQuery("from ApplicationLayer where service = :service").setParameter("service", service) .getResultList(); if (applicationLayers.size() > 0) { serviceDeleted = false; getContext().getValidationErrors().addGlobalError(new SimpleError( "Fout bij het verwijderen van de service. De service heeft kaartlagen geconfigureerd in {2} applicaties.", applicationLayers.size())); return edit(); } else { Category c = service.getCategory(); c.getServices().remove(service); List<FeatureSource> linkedSources = Stripersist.getEntityManager() .createQuery("from FeatureSource where linkedService = :service") .setParameter("service", service).getResultList(); for (FeatureSource fs : linkedSources) { fs.setLinkedService(null); getContext().getMessages().add(new SimpleMessage( "De bij deze service automatisch aangemaakte attribuutbron \"{0}\" moet apart worden verwijderd", fs.getName())); } if (TileService.PROTOCOL.equals(service.getProtocol())) { if (service.getTopLayer() != null && service.getTopLayer().getTileset() != null) { TileSet ts = service.getTopLayer().getTileset(); Stripersist.getEntityManager().remove(ts); } } Stripersist.getEntityManager().remove(service); Stripersist.getEntityManager().getTransaction().commit(); serviceDeleted = true; getContext().getMessages().add(new SimpleMessage("De service is verwijderd")); return new ForwardResolution(JSP); } } @Before public void setUpdatable() { updatable = service instanceof Updatable; } public Resolution update() throws JSONException { if (!isUpdatable()) { getContext().getMessages().add(new SimpleMessage( "Services van protocol {0} kunnen niet worden geupdate", service.getProtocol())); return new ForwardResolution(JSP); } UpdateResult result = ((Updatable) service).update(); if (result.getStatus() == UpdateResult.Status.FAILED) { getContext().getValidationErrors().addGlobalError(new SimpleError(result.getMessage())); return new ForwardResolution(JSP); } Map<UpdateResult.Status, List<String>> byStatus = result.getLayerNamesByStatus(); log.info(String.format("Update layer stats: unmodified %d, updated %d, new %d, missing %d", byStatus.get(UpdateResult.Status.UNMODIFIED).size(), byStatus.get(UpdateResult.Status.UPDATED).size(), byStatus.get(UpdateResult.Status.NEW).size(), byStatus.get(UpdateResult.Status.MISSING).size())); log.info("Unmodified layers: " + byStatus.get(UpdateResult.Status.UNMODIFIED)); log.info("Updated layers: " + byStatus.get(UpdateResult.Status.UPDATED)); log.info("New layers: " + byStatus.get(UpdateResult.Status.NEW)); log.info("Missing layers: " + byStatus.get(UpdateResult.Status.MISSING)); List<Application> apps = findApplications(); for (Application application : apps) { SelectedContentCache.setApplicationCacheDirty(application, true); } Stripersist.getEntityManager().getTransaction().commit(); updatedService = new JSONObject(); updatedService.put("id", "s" + service.getId()); updatedService.put("name", service.getName()); updatedService.put("type", "service"); updatedService.put("isLeaf", service.getTopLayer() == null); updatedService.put("status", "ok");//Math.random() > 0.5 ? "ok" : "error"); updatedService.put("parentid", "c" + category.getId()); getContext().getMessages().add(new SimpleMessage("De service is geupdate")); return new ForwardResolution(JSP); } @ValidationMethod(on = "add") public void validateParams(ValidationErrors errors) { if (protocol.equals(ArcIMSService.PROTOCOL) || protocol.equals(TileService.PROTOCOL)) { if (serviceName == null) { errors.add("serviceName", new LocalizableError("validation.required.valueNotPresent")); } if (protocol.equals(TileService.PROTOCOL)) { if (resolutions == null) { errors.add("resolutions", new LocalizableError("validation.required.valueNotPresent")); } if (serviceBbox == null) { errors.add("serviceBbox", new LocalizableError("validation.required.valueNotPresent")); } if (crs == null) { errors.add("crs", new LocalizableError("validation.required.valueNotPresent")); } if (tileSize == null) { errors.add("tileSize", new LocalizableError("validation.required.valueNotPresent")); } } } } public Resolution addForm() { return new ForwardResolution(JSP); } @WaitPage(path = "/WEB-INF/jsp/waitpage.jsp", delay = 2000, refresh = 1000, ajax = "/WEB-INF/jsp/waitpageajax.jsp") public Resolution add() throws JSONException { status = new WaitPageStatus(); Map params = new HashMap(); try { if (protocol.equals(WMSService.PROTOCOL)) { params.put(WMSService.PARAM_OVERRIDE_URL, overrideUrl); params.put(WMSService.PARAM_USERNAME, username); params.put(WMSService.PARAM_PASSWORD, password); service = new WMSService().loadFromUrl(url, params, status); } else if (protocol.equals(ArcGISService.PROTOCOL)) { params.put(ArcGISService.PARAM_USERNAME, username); params.put(ArcGISService.PARAM_PASSWORD, password); params.put(ArcGISService.PARAM_ASSUME_VERSION, agsVersion); service = new ArcGISService().loadFromUrl(url, params, status); } else if (protocol.equals(ArcIMSService.PROTOCOL)) { params.put(ArcIMSService.PARAM_SERVICENAME, serviceName); params.put(ArcIMSService.PARAM_USERNAME, username); params.put(ArcIMSService.PARAM_PASSWORD, password); service = new ArcIMSService().loadFromUrl(url, params, status); } else if (protocol.equals(TileService.PROTOCOL)) { params.put(TileService.PARAM_SERVICENAME, serviceName); params.put(TileService.PARAM_RESOLUTIONS, resolutions); params.put(TileService.PARAM_SERVICEBBOX, serviceBbox); params.put(TileService.PARAM_CRS, crs); params.put(TileService.PARAM_IMAGEEXTENSION, imageExtension); params.put(TileService.PARAM_TILESIZE, tileSize); params.put(TileService.PARAM_TILINGPROTOCOL, tilingProtocol); service = new TileService().loadFromUrl(url, params, status); } else { getContext().getValidationErrors().add("protocol", new SimpleError("Ongeldig")); } } catch (Exception e) { log.error("Exception loading " + protocol + " service from url " + url, e); String s = e.toString(); if (e.getCause() != null) { s += "; cause: " + e.getCause().toString(); } getContext().getValidationErrors() .addGlobalError(new SimpleError("Fout bij het laden van de service: {2}", s)); return new ForwardResolution(JSP); } if (name != null) { service.setName(name); } if (username != null) { service.setUsername(username); } if (password != null) { service.setPassword(password); } category = Stripersist.getEntityManager().find(Category.class, category.getId()); service.setCategory(category); category.getServices().add(service); Stripersist.getEntityManager().persist(service); Stripersist.getEntityManager().getTransaction().commit(); newService = new JSONObject(); newService.put("id", "s" + service.getId()); newService.put("name", service.getName()); newService.put("type", "service"); newService.put("isLeaf", service.getTopLayer() == null); newService.put("status", "ok");//Math.random() > 0.5 ? "ok" : "error"); newService.put("parentid", "c" + category.getId()); getContext().getMessages().add(new SimpleMessage("Service is ingeladen")); return edit(); } @DontValidate public Resolution addSld() { return new ForwardResolution(JSP_EDIT_SLD); } @Before(on = "editSld") public void setSldType() { if (sld != null) { sldType = sld.getExternalUrl() != null ? "external" : "body"; } } public Resolution editSld() { if (sld != null) { return new ForwardResolution(JSP_EDIT_SLD); } else { return edit(); } } public Resolution deleteSld() { if (sld != null) { service.getStyleLibraries().remove(sld); Stripersist.getEntityManager().remove(sld); Stripersist.getEntityManager().getTransaction().commit(); getContext().getMessages().add(new SimpleMessage("SLD verwijderd")); } return edit(); } @ValidationMethod(on = "saveSld") public void validateSld() { if ("external".equals(sldType) && StringUtils.isBlank(sld.getExternalUrl())) { getContext().getValidationErrors().add("sld.externalUrl", new LocalizableError("validation.required.valueNotPresent")); sld.setSldBody(null); } if ("body".equals(sldType) && StringUtils.isBlank(sld.getSldBody())) { getContext().getValidationErrors().add("sld.sldBody", new LocalizableError("validation.required.valueNotPresent")); sld.setExternalUrl(null); } } private static final String NS_SLD = "http://www.opengis.net/sld"; private static final String NS_OGC = "http://www.opengis.net/ogc"; private static final String NS_GML = "http://www.opengis.net/gml"; public Resolution generateSld() throws Exception { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); Document sldDoc = db.newDocument(); Element sldEl = sldDoc.createElementNS(NS_SLD, "StyledLayerDescriptor"); sldDoc.appendChild(sldEl); sldEl.setAttributeNS(NS_SLD, "version", "1.0.0"); sldEl.setAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "xsi:schemaLocation", "http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd"); sldEl.setAttribute("xmlns:ogc", NS_OGC); sldEl.setAttribute("xmlns:gml", NS_GML); service.loadLayerTree(); Queue<Layer> layerStack = new LinkedList(); Layer l = service.getTopLayer(); while (l != null) { layerStack.addAll(service.getLayerChildrenCache(l)); if (l.getName() != null) { Element nlEl = sldDoc.createElementNS(NS_SLD, "NamedLayer"); sldEl.appendChild(nlEl); String title = l.getTitleAlias() != null ? l.getTitleAlias() : l.getTitle(); if (title != null) { nlEl.appendChild(sldDoc.createComment(" Layer '" + title + "' ")); } Element nEl = sldDoc.createElementNS(NS_SLD, "Name"); nEl.setTextContent(l.getName()); nlEl.appendChild(nEl); if (l.getFeatureType() != null) { String protocol = ""; if (l.getFeatureType().getFeatureSource() != null) { protocol = " (protocol " + l.getFeatureType().getFeatureSource().getProtocol() + ")"; } String ftComment = " This layer has a feature type" + protocol + " you can use in a FeatureTypeConstraint element as follows:\n"; ftComment += " <LayerFeatureConstraints>\n"; ftComment += " <FeatureTypeConstraint>\n"; ftComment += " <FeatureTypeName>" + l.getFeatureType().getTypeName() + "</FeatureTypeName>\n"; ftComment += " Add ogc:Filter or Extent element here. "; if (l.getFeatureType().getAttributes().isEmpty()) { ftComment += " No feature type attributes are known.\n"; } else { ftComment += " You can use the following feature type attributes in ogc:PropertyName elements:\n"; for (AttributeDescriptor ad : l.getFeatureType().getAttributes()) { ftComment += " <ogc:PropertyName>" + ad.getName() + "</ogc:PropertyName>"; if (ad.getAlias() != null) { ftComment += " (" + ad.getAlias() + ")"; } if (ad.getType() != null) { ftComment += " (type: " + ad.getType() + ")"; } ftComment += "\n"; } } ftComment += " </FeatureTypeConstraint>\n"; ftComment += " </LayerFeatureConstraints>\n"; ftComment += " "; nlEl.appendChild(sldDoc.createComment(ftComment)); } nlEl.appendChild(sldDoc.createComment(" Add a UserStyle or NamedStyle element here ")); String styleComment = " (no server-side named styles are known other than 'default') "; ClobElement styleDetail = l.getDetails().get(Layer.DETAIL_WMS_STYLES); if (styleDetail != null) { try { JSONArray styles = new JSONArray(styleDetail.getValue()); if (styles.length() > 0) { styleComment = " The following NamedStyles are available according to the capabilities: \n"; for (int i = 0; i < styles.length(); i++) { JSONObject jStyle = styles.getJSONObject(i); styleComment += " <NamedStyle><Name>" + jStyle.getString("name") + "</Name></NamedStyle>"; if (jStyle.has("title")) { styleComment += " (" + jStyle.getString("title") + ")"; } styleComment += "\n"; } } } catch (JSONException e) { } styleComment += " "; } nlEl.appendChild(sldDoc.createComment(styleComment)); } l = layerStack.poll(); } TransformerFactory tf = TransformerFactory.newInstance(); Transformer t = tf.newTransformer(); t.setOutputProperty(OutputKeys.INDENT, "yes"); t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); t.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); DOMSource source = new DOMSource(sldDoc); ByteArrayOutputStream bos = new ByteArrayOutputStream(); StreamResult result = new StreamResult(bos); t.transform(source, result); generatedSld = new String(bos.toByteArray(), "UTF-8"); // indent doesn't add newline after XML declaration generatedSld = generatedSld.replaceFirst("\"\\?><StyledLayerDescriptor", "\"?>\n<StyledLayerDescriptor"); return new ForwardResolution(JSP_EDIT_SLD); } @DontValidate public Resolution cqlToFilter() throws JSONException { JSONObject json = new JSONObject(); json.put("success", Boolean.FALSE); try { List<Filter> filters = CQL.toFilterList(cql); FilterTransformer filterTransformer = new FilterTransformer(); filterTransformer.setIndentation(4); filterTransformer.setOmitXMLDeclaration(true); filterTransformer.setNamespaceDeclarationEnabled(false); StringWriter sw = new StringWriter(); for (Filter filter : filters) { sw.append('\n'); filterTransformer.transform(filter, sw); } json.put("filter", sw.toString()); json.put("success", Boolean.TRUE); } catch (Exception e) { String error = ExceptionUtils.getMessage(e); if (e.getCause() != null) { error += "; cause: " + ExceptionUtils.getMessage(e.getCause()); } json.put("error", error); } return new StreamingResolution("application/json", new StringReader(json.toString())); } public Resolution validateSldXml() { Resolution jsp = new ForwardResolution(JSP_EDIT_SLD); Document sldXmlDoc = null; String stage = "Fout bij parsen XML document"; try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); sldXmlDoc = db.parse(new ByteArrayInputStream(sld.getSldBody().getBytes("UTF-8"))); stage = "Fout bij controleren SLD"; Element root = sldXmlDoc.getDocumentElement(); if (!"StyledLayerDescriptor".equals(root.getLocalName())) { throw new Exception("Root element moet StyledLayerDescriptor zijn"); } String version = root.getAttribute("version"); if (version == null || !("1.0.0".equals(version) || "1.1.0".equals(version))) { throw new Exception("Geen of ongeldige SLD versie!"); } SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema s = sf .newSchema(new URL("http://schemas.opengis.net/sld/" + version + "/StyledLayerDescriptor.xsd")); s.newValidator().validate(new DOMSource(sldXmlDoc)); } catch (Exception e) { String extra = ""; if (e instanceof SAXParseException) { SAXParseException spe = (SAXParseException) e; if (spe.getLineNumber() != -1) { extra = " (regel " + spe.getLineNumber(); if (spe.getColumnNumber() != -1) { extra += ", kolom " + spe.getColumnNumber(); } extra += ")"; } } getContext().getValidationErrors() .addGlobalError(new SimpleError("{2}: {3}{4}", stage, ExceptionUtils.getMessage(e), extra)); return jsp; } getContext().getMessages().add(new SimpleMessage("SLD is valide!")); return jsp; } public Resolution saveSld() { if (sld.getId() == null) { service.getStyleLibraries().add(sld); } if (sld.isDefaultStyle()) { for (StyleLibrary otherSld : service.getStyleLibraries()) { if (otherSld.getId() != null && !otherSld.getId().equals(sld.getId())) { otherSld.setDefaultStyle(false); } } } try { sld.setNamedLayerUserStylesJson(null); InputSource sldBody = null; if (sld.getExternalUrl() == null) { sldBody = new InputSource(new StringReader(sld.getSldBody())); } else { sldBody = new InputSource(new URL(sld.getExternalUrl()).openStream()); } sld.setNamedLayerUserStylesJson(StyleLibrary.parseSLDNamedLayerUserStyles(sldBody).toString(4)); } catch (Exception e) { log.error("Fout bij bepalen UserStyle namen van NamedLayers", e); getContext().getValidationErrors() .addGlobalError(new SimpleError("Kan geen namen van styles per layer bepalen: " + e.getClass().getName() + ": " + e.getLocalizedMessage())); } Stripersist.getEntityManager().getTransaction().commit(); getContext().getMessages().add(new SimpleMessage("SLD opgeslagen")); return edit(); } }