NIFI-317: - Adding support for exporting the lineage graph as SVG. - Removing support to convert to PNG.
Project: http://git-wip-us.apache.org/repos/asf/incubator-nifi/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-nifi/commit/4e85e34c Tree: http://git-wip-us.apache.org/repos/asf/incubator-nifi/tree/4e85e34c Diff: http://git-wip-us.apache.org/repos/asf/incubator-nifi/diff/4e85e34c Branch: refs/heads/NIFI-250 Commit: 4e85e34c319c847632574c9589b3aa0fdbc355b6 Parents: b0b14ed Author: Matt Gilman <[email protected]> Authored: Wed Feb 4 09:05:18 2015 -0500 Committer: Matt Gilman <[email protected]> Committed: Wed Feb 4 09:05:18 2015 -0500 ---------------------------------------------------------------------- .../nifi-framework/nifi-web/nifi-web-ui/pom.xml | 12 -- .../org/apache/nifi/web/servlet/ConvertSvg.java | 117 ------------------- .../apache/nifi/web/servlet/DownloadSvg.java | 93 +++++++++++++++ .../nifi-web-ui/src/main/webapp/WEB-INF/web.xml | 30 ++++- .../js/nf/provenance/nf-provenance-lineage.js | 15 ++- 5 files changed, 132 insertions(+), 135 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/4e85e34c/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml index 9eaa1b9..f01cbea 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/pom.xml @@ -610,18 +610,6 @@ <scope>provided</scope> </dependency> <dependency> - <groupId>batik</groupId> - <artifactId>batik-transcoder</artifactId> - <version>1.6-1</version> - <exclusions> - <exclusion> - <groupId>fop</groupId> - <artifactId>fop</artifactId> - </exclusion> - </exclusions> - </dependency> - - <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <scope>provided</scope> http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/4e85e34c/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/servlet/ConvertSvg.java ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/servlet/ConvertSvg.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/servlet/ConvertSvg.java deleted file mode 100644 index 6282f41..0000000 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/servlet/ConvertSvg.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.nifi.web.servlet; - -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.StringReader; -import java.net.URLDecoder; -import javax.servlet.ServletException; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.apache.batik.dom.svg.SAXSVGDocumentFactory; -import org.apache.batik.transcoder.TranscoderInput; -import org.apache.batik.transcoder.TranscoderOutput; -import org.apache.batik.transcoder.image.PNGTranscoder; -import org.apache.batik.util.XMLResourceDescriptor; -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.svg.SVGDocument; - -/** - * - */ -@WebServlet(name = "ConvertSvg", urlPatterns = {"/convert-svg"}) -public class ConvertSvg extends HttpServlet { - - private static final Logger logger = LoggerFactory.getLogger(ConvertSvg.class); - - /** - * - * @param request servlet request - * @param response servlet response - * @throws ServletException if a servlet-specific error occurs - * @throws IOException if an I/O error occurs - */ - @Override - protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - final String uri = request.getRequestURL().toString(); - final String rawSvg = request.getParameter("svg"); - - // ensure the image markup has been included - if (rawSvg == null) { - // set the response status - response.setContentType("text/plain"); - response.setStatus(HttpServletResponse.SC_BAD_REQUEST); - - // write the response message - PrintWriter out = response.getWriter(); - out.println("SVG must be specified."); - return; - } - - OutputStream bufferedOut = null; - try { - // get the svg and decode it, +'s need to be converted - final String svg = URLDecoder.decode(rawSvg.replace("+", "%2B"), "UTF-8"); - - if (logger.isDebugEnabled()) { - logger.debug(svg); - } - - String filename = request.getParameter("filename"); - if (filename == null) { - filename = "image.png"; - } else if (!filename.endsWith(".png")) { - filename += ".png"; - } - - final StringReader reader = new StringReader(svg); - final String parser = XMLResourceDescriptor.getXMLParserClassName(); - final SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser); - final SVGDocument doc = f.createSVGDocument(uri, reader); - - response.setContentType("image/png"); - response.setHeader("Content-Disposition", "attachment; filename=" + filename); - response.setStatus(HttpServletResponse.SC_OK); - - bufferedOut = new BufferedOutputStream(response.getOutputStream()); - final TranscoderInput transcoderInput = new TranscoderInput(doc); - final TranscoderOutput transcoderOutput = new TranscoderOutput(bufferedOut); - - final PNGTranscoder transcoder = new PNGTranscoder(); - transcoder.transcode(transcoderInput, transcoderOutput); - } catch (final Exception e) { - logger.error(e.getMessage(), e); - - // set the response status - response.setContentType("text/plain"); - response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - - // write the response message - PrintWriter out = response.getWriter(); - out.println("Unable to export image as a PNG."); - } finally { - IOUtils.closeQuietly(bufferedOut); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/4e85e34c/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/servlet/DownloadSvg.java ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/servlet/DownloadSvg.java b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/servlet/DownloadSvg.java new file mode 100644 index 0000000..ab76d4e --- /dev/null +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/servlet/DownloadSvg.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.web.servlet; + +import java.io.IOException; +import java.io.PrintWriter; +import java.net.URLDecoder; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + */ +@WebServlet(name = "DownloadSvg", urlPatterns = {"/download-svg"}) +public class DownloadSvg extends HttpServlet { + + private static final Logger logger = LoggerFactory.getLogger(DownloadSvg.class); + + /** + * + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + final String rawSvg = request.getParameter("svg"); + + // ensure the image markup has been included + if (rawSvg == null) { + // set the response status + response.setContentType("text/plain"); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + + // write the response message + PrintWriter out = response.getWriter(); + out.println("SVG must be specified."); + return; + } + + try { + // get the svg and decode it, +'s need to be converted + final String svg = URLDecoder.decode(rawSvg.replace("+", "%2B"), "UTF-8"); + + if (logger.isDebugEnabled()) { + logger.debug(svg); + } + + String filename = request.getParameter("filename"); + if (filename == null) { + filename = "image.svg"; + } else if (!filename.endsWith(".svg")) { + filename += ".svg"; + } + + response.setContentType("image/svg+xml"); + response.setHeader("Content-Disposition", "attachment; filename=" + filename); + response.setStatus(HttpServletResponse.SC_OK); + + response.getWriter().print(svg); + } catch (final Exception e) { + logger.error(e.getMessage(), e); + + // set the response status + response.setContentType("text/plain"); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + + // write the response message + PrintWriter out = response.getWriter(); + out.println("Unable to export image as a SVG."); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/4e85e34c/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/web.xml ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/web.xml b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/web.xml index 8cae6e5..eff7b8d 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/web.xml +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/web.xml @@ -15,7 +15,9 @@ --> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <display-name>nifi</display-name> + <!-- servlet to map to canvas page --> + <servlet> <servlet-name>NiFiCanvas</servlet-name> <jsp-file>/WEB-INF/pages/canvas.jsp</jsp-file> @@ -24,7 +26,9 @@ <servlet-name>NiFiCanvas</servlet-name> <url-pattern>/canvas</url-pattern> </servlet-mapping> + <!-- servlet to map to summary page --> + <servlet> <servlet-name>NiFiSummary</servlet-name> <jsp-file>/WEB-INF/pages/summary.jsp</jsp-file> @@ -33,7 +37,9 @@ <servlet-name>NiFiSummary</servlet-name> <url-pattern>/summary</url-pattern> </servlet-mapping> + <!-- servlet to map to history page --> + <servlet> <servlet-name>NiFiHistory</servlet-name> <jsp-file>/WEB-INF/pages/history.jsp</jsp-file> @@ -42,7 +48,9 @@ <servlet-name>NiFiHistory</servlet-name> <url-pattern>/history</url-pattern> </servlet-mapping> + <!-- servlet to map to provenance page --> + <servlet> <servlet-name>NiFiProvenance</servlet-name> <jsp-file>/WEB-INF/pages/provenance.jsp</jsp-file> @@ -51,7 +59,9 @@ <servlet-name>NiFiProvenance</servlet-name> <url-pattern>/provenance</url-pattern> </servlet-mapping> + <!-- servlet to map to counters page --> + <servlet> <servlet-name>NiFiCounters</servlet-name> <jsp-file>/WEB-INF/pages/counters.jsp</jsp-file> @@ -60,7 +70,9 @@ <servlet-name>NiFiCounters</servlet-name> <url-pattern>/counters</url-pattern> </servlet-mapping> + <!-- servlet to map to templates page --> + <servlet> <servlet-name>NiFiTemplates</servlet-name> <jsp-file>/WEB-INF/pages/templates.jsp</jsp-file> @@ -69,7 +81,9 @@ <servlet-name>NiFiTemplates</servlet-name> <url-pattern>/templates</url-pattern> </servlet-mapping> + <!-- servlet to map to users page --> + <servlet> <servlet-name>NiFiUsers</servlet-name> <jsp-file>/WEB-INF/pages/users.jsp</jsp-file> @@ -78,7 +92,9 @@ <servlet-name>NiFiUsers</servlet-name> <url-pattern>/users</url-pattern> </servlet-mapping> + <!-- servlet to map to cluster page --> + <servlet> <servlet-name>NiFiCluster</servlet-name> <jsp-file>/WEB-INF/pages/cluster.jsp</jsp-file> @@ -87,7 +103,9 @@ <servlet-name>NiFiCluster</servlet-name> <url-pattern>/cluster</url-pattern> </servlet-mapping> + <!-- servlet to map to bulletin board page --> + <servlet> <servlet-name>BulletinBoard</servlet-name> <jsp-file>/WEB-INF/pages/bulletin-board.jsp</jsp-file> @@ -96,15 +114,18 @@ <servlet-name>BulletinBoard</servlet-name> <url-pattern>/bulletin-board</url-pattern> </servlet-mapping> + <!-- servlet to support image downloading --> + <servlet> - <servlet-name>ConvertSvg</servlet-name> - <servlet-class>org.apache.nifi.web.servlet.ConvertSvg</servlet-class> + <servlet-name>DownloadSvg</servlet-name> + <servlet-class>org.apache.nifi.web.servlet.DownloadSvg</servlet-class> </servlet> <servlet-mapping> - <servlet-name>ConvertSvg</servlet-name> - <url-pattern>/convert-svg</url-pattern> + <servlet-name>DownloadSvg</servlet-name> + <url-pattern>/download-svg</url-pattern> </servlet-mapping> + <filter> <filter-name>IeEdgeHeader</filter-name> <filter-class>org.apache.nifi.web.filter.IeEdgeHeader</filter-class> @@ -113,6 +134,7 @@ <filter-name>IeEdgeHeader</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> + <welcome-file-list> <welcome-file>canvas.jsp</welcome-file> <welcome-file>/WEB-INF/pages/canvas.jsp</welcome-file> http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/4e85e34c/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js ---------------------------------------------------------------------- diff --git a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js index 1f05caa..03b08f0 100644 --- a/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js +++ b/nifi/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/provenance/nf-provenance-lineage.js @@ -531,6 +531,10 @@ nf.ProvenanceLineage = (function () { var svg = d3.select('#provenance-lineage-container').append('svg:svg') .attr('width', width) .attr('height', height) + .style({ + 'font-family': 'Verdana, Arial, sans-serif', + 'font-size': '10px' + }) .call(lineageZoom) .on('dblclick.zoom', null) .on('mousedown', function (d) { @@ -1210,7 +1214,7 @@ nf.ProvenanceLineage = (function () { // add the initial lineage addLineage(lineageResults.nodes, lineageResults.links); }; - + return { /** * Initializes the lineage graph. @@ -1276,7 +1280,14 @@ nf.ProvenanceLineage = (function () { return '<g' + before + 'transform="translate(' + x + ',' + y + ')"' + after + '>'; }); - nf.Common.submit('POST', './convert-svg', { + // namespaces + svg = svg.replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"'); + + // doctype + svg = '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n' + svg; + + // send to server to initiate download... client side only support is too browser specific at this point + nf.Common.submit('POST', './download-svg', { 'filename': 'provenance', 'svg': encodeURIComponent(svg) });
