You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by or...@apache.org on 2018/02/24 17:58:10 UTC
qpid-broker-j git commit: QPID-8103: [Broker-J] [WMC] [Query UI] Add
ability to download results as CSV
Repository: qpid-broker-j
Updated Branches:
refs/heads/master 51472013e -> 7dbb88471
QPID-8103: [Broker-J] [WMC] [Query UI] Add ability to download results as CSV
Project: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/commit/7dbb8847
Tree: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/tree/7dbb8847
Diff: http://git-wip-us.apache.org/repos/asf/qpid-broker-j/diff/7dbb8847
Branch: refs/heads/master
Commit: 7dbb88471a414d993e4ee3bd3e8fde2f30ca2f46
Parents: 5147201
Author: Alex Rudyy <or...@apache.org>
Authored: Sat Feb 24 02:23:26 2018 +0000
Committer: Alex Rudyy <or...@apache.org>
Committed: Sat Feb 24 17:57:45 2018 +0000
----------------------------------------------------------------------
.../plugin/servlet/csv/CSVFormat.java | 320 +++++++++++++++++++
.../plugin/servlet/rest/AbstractServlet.java | 23 ++
.../plugin/servlet/rest/QueryServlet.java | 58 +++-
.../plugin/servlet/rest/RestServlet.java | 22 --
.../src/main/java/resources/css/common.css | 4 +
.../resources/js/qpid/management/Management.js | 17 +-
.../js/qpid/management/query/QueryWidget.js | 23 +-
.../main/java/resources/query/QueryWidget.html | 7 +
.../plugin/servlet/csv/CSVFormatTest.java | 84 +++++
9 files changed, 526 insertions(+), 32 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7dbb8847/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/csv/CSVFormat.java
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/csv/CSVFormat.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/csv/CSVFormat.java
new file mode 100644
index 0000000..90a5f5f
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/csv/CSVFormat.java
@@ -0,0 +1,320 @@
+/*
+ *
+ * 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.qpid.server.management.plugin.servlet.csv;
+
+
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * Simplified version of CSVFormat from Apache Commons CSV
+ */
+public final class CSVFormat
+{
+ private static final char COMMA = ',';
+
+ private static final char COMMENT = '#';
+
+ private static final char CR = '\r';
+
+ private static final String CRLF = "\r\n";
+
+ private static final Character DOUBLE_QUOTE_CHAR = '"';
+
+ private static final String EMPTY = "";
+
+ private static final char LF = '\n';
+
+ private static final char SP = ' ';
+
+ private final char _delimiter;
+
+ private final Character _escapeCharacter; // null if escaping is disabled
+
+ private final Character _quoteCharacter; // null if quoting is disabled
+
+ private final String _recordSeparator; // for outputs
+
+ public CSVFormat()
+ {
+ this(COMMA, DOUBLE_QUOTE_CHAR, null, CRLF);
+ }
+
+ /**
+ * Creates a customized CSV format.
+ *
+ * @param delimiter the char used for value separation, must not be a line break character
+ * @param quoteCharacter the Character used as value encapsulation marker, may be {@code null} to disable
+ * @param escapeCharacter the Character used to escape special characters in values, may be {@code null} to disable
+ * @param recordSeparator the line separator to use for output
+ * @throws IllegalArgumentException if the _delimiter is a line break character
+ */
+ CSVFormat(final char delimiter,
+ final Character quoteCharacter,
+ final Character escapeCharacter,
+ final String recordSeparator)
+ {
+ if (delimiter == LF || delimiter == CR)
+ {
+ throw new IllegalArgumentException("The _delimiter cannot be a line break");
+ }
+
+ if (quoteCharacter != null && delimiter == quoteCharacter)
+ {
+ throw new IllegalArgumentException(
+ "The quote character and the delimiter cannot be the same ('" + quoteCharacter + "')");
+ }
+
+ if (escapeCharacter != null && delimiter == escapeCharacter)
+ {
+ throw new IllegalArgumentException(
+ "The escape character and the delimiter cannot be the same ('" + escapeCharacter + "')");
+ }
+
+ this._delimiter = delimiter;
+ this._quoteCharacter = quoteCharacter;
+ this._escapeCharacter = escapeCharacter;
+ this._recordSeparator = recordSeparator;
+ }
+
+ public <T extends Collection<?>> void printRecord(final Appendable out, final T record) throws IOException
+ {
+ boolean newRecord = true;
+ for (Object item : record)
+ {
+ print(out, item, newRecord);
+ newRecord = false;
+ }
+ println(out);
+ }
+
+ public <C extends Collection<? extends Collection<?>>> void printRecords(final Appendable out, final C records)
+ throws IOException
+ {
+ for (Collection<?> record : records)
+ {
+ printRecord(out, record);
+ }
+ }
+
+
+ public void println(final Appendable out) throws IOException
+ {
+ if (_recordSeparator != null)
+ {
+ out.append(_recordSeparator);
+ }
+ }
+
+ public void print(final Appendable out, final Object value, final boolean newRecord) throws IOException
+ {
+ CharSequence charSequence;
+ if (value == null)
+ {
+ charSequence = EMPTY;
+ }
+ else
+ {
+ charSequence = value instanceof CharSequence ? (CharSequence) value : value.toString();
+ }
+ this.print(out, value, charSequence, 0, charSequence.length(), newRecord);
+ }
+
+
+ public void printComments(final Appendable out,
+ final String... comments) throws IOException
+ {
+ for (String comment: comments)
+ {
+ out.append(COMMENT).append(SP).append(comment);
+ println(out);
+ }
+ }
+
+ private void print(final Appendable out,
+ final Object object,
+ final CharSequence value,
+ final int offset,
+ final int len,
+ final boolean newRecord) throws IOException
+ {
+ if (!newRecord)
+ {
+ out.append(_delimiter);
+ }
+ if (object == null)
+ {
+ out.append(value);
+ }
+ else if (_quoteCharacter != null)
+ {
+ printAndQuote(value, offset, len, out, newRecord);
+ }
+ else if (_escapeCharacter != null)
+ {
+ printAndEscape(out, value, offset, len);
+ }
+ else
+ {
+ out.append(value, offset, offset + len);
+ }
+ }
+
+ private void printAndEscape(final Appendable out,
+ final CharSequence value,
+ final int offset,
+ final int len)
+ throws IOException
+ {
+ int start = offset;
+ int pos = offset;
+ final int end = offset + len;
+
+ final char escape = _escapeCharacter;
+
+ while (pos < end)
+ {
+ char c = value.charAt(pos);
+ if (c == CR || c == LF || c == _delimiter || c == escape)
+ {
+ // write out segment up until this char
+ if (pos > start)
+ {
+ out.append(value, start, pos);
+ }
+ if (c == LF)
+ {
+ c = 'n';
+ }
+ else if (c == CR)
+ {
+ c = 'r';
+ }
+
+ out.append(escape);
+ out.append(c);
+
+ start = pos + 1; // start on the current char after this one
+ }
+
+ pos++;
+ }
+
+ // write last segment
+ if (pos > start)
+ {
+ out.append(value, start, pos);
+ }
+ }
+
+ private void printAndQuote(final CharSequence value, final int offset, final int len,
+ final Appendable out, final boolean newRecord) throws IOException
+ {
+ boolean quote = false;
+ int start = offset;
+ int pos = offset;
+ final int end = offset + len;
+
+ final char quoteChar = _quoteCharacter;
+
+ if (len <= 0)
+ {
+ // always quote an empty token that is the first
+ // on the line, as it may be the only thing on the
+ // line. If it were not quoted in that case,
+ // an empty line has no tokens.
+ if (newRecord)
+ {
+ quote = true;
+ }
+ }
+ else
+ {
+ char c = value.charAt(pos);
+
+ if (c <= COMMENT)
+ {
+ // Some other chars at the start of a value caused the parser to fail, so for now
+ // encapsulate if we start in anything less than '#'. We are being conservative
+ // by including the default comment char too.
+ quote = true;
+ }
+ else
+ {
+ while (pos < end)
+ {
+ c = value.charAt(pos);
+ if (c == LF || c == CR || c == quoteChar || c == _delimiter)
+ {
+ quote = true;
+ break;
+ }
+ pos++;
+ }
+
+ if (!quote)
+ {
+ pos = end - 1;
+ c = value.charAt(pos);
+ // Some other chars at the end caused the parser to fail, so for now
+ // encapsulate if we end in anything less than ' '
+ if (c <= SP)
+ {
+ quote = true;
+ }
+ }
+ }
+ }
+
+ if (!quote)
+ {
+ // no encapsulation needed - write out the original value
+ out.append(value, start, end);
+ return;
+ }
+
+ // we hit something that needed encapsulation
+ out.append(quoteChar);
+
+ // Pick up where we left off: pos should be positioned on the first character that caused
+ // the need for encapsulation.
+ while (pos < end)
+ {
+ final char c = value.charAt(pos);
+ if (c == quoteChar)
+ {
+ // write out the chunk up until this point
+
+ // add 1 to the length to write out the encapsulator also
+ out.append(value, start, pos + 1);
+ // put the next starting position on the encapsulator so we will
+ // write it out again with the next string (effectively doubling it)
+ start = pos;
+ }
+ pos++;
+ }
+
+ // write the last segment
+ out.append(value, start, pos);
+ out.append(quoteChar);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7dbb8847/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
index 4403200..76d87f1 100644
--- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
@@ -22,6 +22,7 @@ package org.apache.qpid.server.management.plugin.servlet.rest;
import static org.apache.qpid.server.management.plugin.HttpManagementUtil.CONTENT_ENCODING_HEADER;
import static org.apache.qpid.server.management.plugin.HttpManagementUtil.GZIP_CONTENT_ENCODING;
+import static org.apache.qpid.server.management.plugin.HttpManagementUtil.ensureFilenameIsRfc2183;
import java.io.IOException;
import java.io.OutputStream;
@@ -66,6 +67,11 @@ import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
public abstract class AbstractServlet extends HttpServlet
{
public static final int SC_UNPROCESSABLE_ENTITY = 422;
+ /**
+ * Signifies that the agent wishes the servlet to set the Content-Disposition on the
+ * response with the value attachment. This filename will be derived from the parameter value.
+ */
+ public static final String CONTENT_DISPOSITION_ATTACHMENT_FILENAME_PARAM = "contentDispositionAttachmentFilename";
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractServlet.class);
public static final String CONTENT_DISPOSITION = "Content-Disposition";
@@ -158,6 +164,23 @@ public abstract class AbstractServlet extends HttpServlet
}
}
+ protected void setContentDispositionHeaderIfNecessary(final HttpServletResponse response,
+ final String attachmentFilename)
+ {
+ if (attachmentFilename != null)
+ {
+ String filenameRfc2183 = ensureFilenameIsRfc2183(attachmentFilename);
+ if (filenameRfc2183.length() > 0)
+ {
+ response.setHeader(CONTENT_DISPOSITION, String.format("attachment; filename=\"%s\"", filenameRfc2183));
+ }
+ else
+ {
+ response.setHeader(CONTENT_DISPOSITION, "attachment"); // Agent will allow user to choose a name
+ }
+ }
+ }
+
protected void doPut(HttpServletRequest req,
HttpServletResponse resp,
final ConfiguredObject<?> managedObject) throws ServletException, IOException
http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7dbb8847/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueryServlet.java
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueryServlet.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueryServlet.java
index 2b72295..8ae06f8 100644
--- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueryServlet.java
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueryServlet.java
@@ -21,6 +21,8 @@
package org.apache.qpid.server.management.plugin.servlet.rest;
import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -33,15 +35,18 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.qpid.server.filter.SelectorParsingException;
+import org.apache.qpid.server.management.plugin.servlet.csv.CSVFormat;
import org.apache.qpid.server.management.plugin.servlet.query.ConfiguredObjectQuery;
import org.apache.qpid.server.management.plugin.servlet.query.EvaluationException;
import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Container;
import org.apache.qpid.server.model.Model;
public abstract class QueryServlet<X extends ConfiguredObject<?>> extends AbstractServlet
{
private static final Logger LOGGER = LoggerFactory.getLogger(QueryServlet.class);
+ private static final CSVFormat CSV_FORMAT = new CSVFormat();
@Override
protected void doGet(HttpServletRequest request,
@@ -78,7 +83,6 @@ public abstract class QueryServlet<X extends ConfiguredObject<?>> extends Abstra
if (category != null)
{
List<ConfiguredObject<?>> objects = getAllObjects(parent, category, request);
- Map<String, Object> resultsObject = new LinkedHashMap<>();
try
{
@@ -89,10 +93,26 @@ public abstract class QueryServlet<X extends ConfiguredObject<?>> extends Abstra
request.getParameter("limit"),
request.getParameter("offset"));
- resultsObject.put("headers", query.getHeaders());
- resultsObject.put("results", query.getResults());
- resultsObject.put("total", query.getTotalNumberOfRows());
- sendJsonResponse(resultsObject, request, response);
+
+ String attachmentFilename = request.getParameter(CONTENT_DISPOSITION_ATTACHMENT_FILENAME_PARAM);
+ if (attachmentFilename != null)
+ {
+ setContentDispositionHeaderIfNecessary(response, attachmentFilename);
+ }
+
+ if ("csv".equalsIgnoreCase(request.getParameter("format")))
+ {
+ sendCsvResponse(categoryName, parent, query, request, response);
+ }
+ else
+ {
+ Map<String, Object> resultsObject = new LinkedHashMap<>();
+ resultsObject.put("headers", query.getHeaders());
+ resultsObject.put("results", query.getResults());
+ resultsObject.put("total", query.getTotalNumberOfRows());
+
+ sendJsonResponse(resultsObject, request, response);
+ }
}
catch (SelectorParsingException e)
{
@@ -125,6 +145,34 @@ public abstract class QueryServlet<X extends ConfiguredObject<?>> extends Abstra
}
+ private void sendCsvResponse(final String categoryName,
+ final X parent,
+ final ConfiguredObjectQuery query,
+ final HttpServletRequest request,
+ final HttpServletResponse response)
+ throws IOException
+ {
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentType("text/csv;charset=utf-8;");
+ response.setCharacterEncoding(StandardCharsets.UTF_8.name());
+ sendCachingHeadersOnResponse(response);
+ try (PrintWriter writer = response.getWriter())
+ {
+ CSV_FORMAT.printComments(writer,
+ String.format("parent : %s %s ",
+ parent.getCategoryClass().getSimpleName(),
+ (parent instanceof Container
+ ? ""
+ : parent.getName())),
+ String.format("category : %s", categoryName),
+ String.format("select : %s", request.getParameter("select")),
+ String.format("where : %s", request.getParameter("where")),
+ String.format("order by : %s", request.getParameter("orderBy")));
+ CSV_FORMAT.printRecord(writer, query.getHeaders());
+ CSV_FORMAT.printRecords(writer, query.getResults());
+ }
+ }
+
abstract protected X getParent(final HttpServletRequest request, final ConfiguredObject<?> managedObject);
abstract protected Class<? extends ConfiguredObject> getSupportedCategory(final String categoryName,
http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7dbb8847/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
index 8361886..4e5e524 100644
--- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
@@ -81,11 +81,6 @@ public class RestServlet extends AbstractServlet
public static final String EXTRACT_INITIAL_CONFIG_PARAM = "extractInitialConfig";
public static final String EXCLUDE_INHERITED_CONTEXT_PARAM = "excludeInheritedContext";
private static final String SINGLETON_MODEL_OBJECT_RESPONSE_AS_LIST = "singletonModelObjectResponseAsList";
- /**
- * Signifies that the agent wishes the servlet to set the Content-Disposition on the
- * response with the value attachment. This filename will be derived from the parameter value.
- */
- public static final String CONTENT_DISPOSITION_ATTACHMENT_FILENAME_PARAM = "contentDispositionAttachmentFilename";
public static final Set<String> RESERVED_PARAMS =
new HashSet<>(Arrays.asList(DEPTH_PARAM,
SORT_PARAM,
@@ -313,23 +308,6 @@ public class RestServlet extends AbstractServlet
return false;
}
- private void setContentDispositionHeaderIfNecessary(final HttpServletResponse response,
- final String attachmentFilename)
- {
- if (attachmentFilename != null)
- {
- String filenameRfc2183 = ensureFilenameIsRfc2183(attachmentFilename);
- if (filenameRfc2183.length() > 0)
- {
- response.setHeader(CONTENT_DISPOSITION, String.format("attachment; filename=\"%s\"", filenameRfc2183));
- }
- else
- {
- response.setHeader(CONTENT_DISPOSITION, "attachment"); // Agent will allow user to choose a name
- }
- }
- }
-
private Class<? extends ConfiguredObject> getConfiguredClass(HttpServletRequest request, ConfiguredObject<?> managedObject)
{
final String[] servletPathElements = request.getServletPath().split("/");
http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7dbb8847/broker-plugins/management-http/src/main/java/resources/css/common.css
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/css/common.css b/broker-plugins/management-http/src/main/java/resources/css/common.css
index e4b2511..b2577c7 100644
--- a/broker-plugins/management-http/src/main/java/resources/css/common.css
+++ b/broker-plugins/management-http/src/main/java/resources/css/common.css
@@ -611,6 +611,10 @@ td.advancedSearchField, col.autoWidth {
background-position: -180px -98px;
}
+.exportIcon.ui-icon {
+ background-position: -112px -112px;
+}
+
.claro .searchBox {
padding-right: 16px;
padding-left: 16px;
http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7dbb8847/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Management.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Management.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Management.js
index 5570636..bf56bf4 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Management.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Management.js
@@ -612,17 +612,26 @@ define(["dojo/_base/lang",
// Promise returned by dojo.request.xhr with modified then method allowing to use default error handler if none is specified.
Management.prototype.query = function (query)
{
- var url = "api/latest/" + (query.parent && query.parent.type === "virtualhost" ? "queryvhost/"
- + this.objectToPath({parent: query.parent}) : "querybroker") + (query.category ? "/"
- + query.category : "");
var request = {
- url: this.getFullUrl(url),
+ url: this.getQueryUrl(query),
query: {}
};
shallowCopy(query, request.query, ["parent", "category"]);
return this.get(request);
};
+ Management.prototype.getQueryUrl = function (query, parameters)
+ {
+ var url = "api/latest/" + (query.parent && query.parent.type === "virtualhost" ? "queryvhost/"
+ + this.objectToPath({parent: query.parent}) : "querybroker") + (query.category ? "/"
+ + query.category : "");
+ if (parameters)
+ {
+ url = url + "?" + ioQuery.objectToQuery(parameters);
+ }
+ return this.getFullUrl(url);
+ };
+
Management.prototype.savePreference = function(parentObject, preference)
{
var url = this.buildPreferenceUrl(parentObject, preference.type);
http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7dbb8847/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryWidget.js
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryWidget.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryWidget.js
index 4f6dad6..799ec67 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryWidget.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/QueryWidget.js
@@ -35,6 +35,7 @@ define(["dojo/_base/declare",
"dgrid/extensions/ColumnHider",
"qpid/management/query/QueryGrid",
"qpid/common/MessageDialog",
+ "dojox/uuid/generateRandomUuid",
"qpid/management/query/DropDownSelect",
"qpid/management/query/WhereExpression",
"dijit/_WidgetBase",
@@ -61,7 +62,8 @@ define(["dojo/_base/declare",
ColumnReorder,
ColumnHider,
QueryGrid,
- MessageDialog)
+ MessageDialog,
+ uuid)
{
var QueryCloneDialogForm = declare("qpid.management.query.QueryCloneDialogForm",
@@ -183,6 +185,8 @@ define(["dojo/_base/declare",
cloneButtonTooltip: null,
deleteButtonTooltip: null,
searchForm: null,
+ exportButton: null,
+ exportButtonTooltip: null,
/**
* constructor parameter
@@ -241,6 +245,7 @@ define(["dojo/_base/declare",
this.saveButton.on("click", lang.hitch(this, this._saveQuery));
this.cloneButton.on("click", lang.hitch(this, this._cloneQuery));
this.deleteButton.on("click", lang.hitch(this, this._deleteQuery));
+ this.exportButton.on("click", lang.hitch(this, this._exportQueryResults));
this._ownQuery = !this.preference
|| !this.preference.owner
@@ -248,6 +253,7 @@ define(["dojo/_base/declare",
var newQuery = !this.preference || !this.preference.createdDate;
this.saveButton.set("disabled", !this._ownQuery);
this.deleteButton.set("disabled", !this._ownQuery || newQuery);
+ this.exportButton.set("disabled", true);
if (!this._ownQuery)
{
@@ -537,6 +543,7 @@ define(["dojo/_base/declare",
zeroBased: false,
rowsPerPage: rowsPerPage,
_currentPage: currentPage,
+ allowTextSelection: true,
transformer: function (data)
{
var dataResults = data.results;
@@ -585,6 +592,7 @@ define(["dojo/_base/declare",
_queryCompleted: function (e)
{
this._buildColumnsIfHeadersChanged(e.data);
+ this.exportButton.set("disabled", !(e.data.total && e.data.total > 0));
},
_buildColumnsIfHeadersChanged: function (data)
{
@@ -977,6 +985,19 @@ define(["dojo/_base/declare",
this.emit("change", {preference: pref});
}
}
+ },
+ _exportQueryResults: function () {
+ var query = this._getQuery();
+ query.format = "csv";
+ var id = uuid();
+ query.contentDispositionAttachmentFilename ="query-results-" + id + ".csv";
+ delete query.category;
+ var url = this.management.getQueryUrl({category: this.categoryName, parent: this.parentObject}, query);
+ var iframe = document.createElement('iframe');
+ iframe.id = "query_downloader_" + id;
+ iframe.style.display = "none";
+ document.body.appendChild(iframe);
+ iframe.src = url;
}
});
http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7dbb8847/broker-plugins/management-http/src/main/java/resources/query/QueryWidget.html
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/main/java/resources/query/QueryWidget.html b/broker-plugins/management-http/src/main/java/resources/query/QueryWidget.html
index ff1b471..0a28eac 100644
--- a/broker-plugins/management-http/src/main/java/resources/query/QueryWidget.html
+++ b/broker-plugins/management-http/src/main/java/resources/query/QueryWidget.html
@@ -40,6 +40,13 @@
<div data-dojo-attach-point="deleteButtonTooltip"
data-dojo-type="dijit/Tooltip"
data-dojo-props="connectId:'deleteButton_${id}',position:['below']">Delete query from preferences and close the tab</div>
+ <div id="exportButton_${id}"
+ data-dojo-type="dijit/form/Button"
+ data-dojo-attach-point="exportButton"
+ data-dojo-props="iconClass: 'exportIcon ui-icon'">Export</div>
+ <div data-dojo-attach-point="exportButtonTooltip"
+ data-dojo-type="dijit/Tooltip"
+ data-dojo-props="connectId:'exportButton_${id}',position:['below']">Export query results into CSV format</div>
<div data-dojo-type="dijit/form/Button"
data-dojo-attach-point="modeButton"
data-dojo-props="iconClass: 'advancedViewIcon ui-icon', title:'Switch to \'Advanced View\' search using SQL-like expressions'"
http://git-wip-us.apache.org/repos/asf/qpid-broker-j/blob/7dbb8847/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/csv/CSVFormatTest.java
----------------------------------------------------------------------
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/csv/CSVFormatTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/csv/CSVFormatTest.java
new file mode 100644
index 0000000..4adb0b7
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/csv/CSVFormatTest.java
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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.qpid.server.management.plugin.servlet.csv;
+
+import java.io.StringWriter;
+import java.util.Arrays;
+
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class CSVFormatTest extends QpidTestCase
+{
+
+ public void testPrintRecord() throws Exception
+ {
+ CSVFormat csvFormat = new CSVFormat();
+ final StringWriter out = new StringWriter();
+ csvFormat.printRecord(out, Arrays.asList("test", 1, true, "\"quoted\" test"));
+ assertEquals("Unexpected format",
+ String.format("%s,%d,%b,%s%s", "test", 1, true, "\"\"\"quoted\"\" test\"", "\r\n"),
+ out.toString());
+ }
+
+ public void testPrintRecords() throws Exception
+ {
+ CSVFormat csvFormat = new CSVFormat();
+ final StringWriter out = new StringWriter();
+ csvFormat.printRecords(out, Arrays.asList(Arrays.asList("test", 1, true, "\"quoted\" test"),
+ Arrays.asList("delimeter,test", 1.0f, false,
+ "quote\" in the middle")));
+ assertEquals("Unexpected format",
+ String.format("%s,%d,%b,%s%s%s,%s,%b,%s%s", "test", 1, true, "\"\"\"quoted\"\" test\"", "\r\n",
+ "\"delimeter,test\"", "1.0", false, "\"quote\"\" in the middle\"", "\r\n"),
+ out.toString());
+ }
+
+ public void testPrintln() throws Exception
+ {
+ CSVFormat csvFormat = new CSVFormat();
+ final StringWriter out = new StringWriter();
+ csvFormat.println(out);
+ assertEquals("Unexpected new line", "\r\n", out.toString());
+ }
+
+ public void testPrint() throws Exception
+ {
+ CSVFormat csvFormat = new CSVFormat();
+ final StringWriter out = new StringWriter();
+ csvFormat.print(out, "test", true);
+ csvFormat.print(out, 1, false);
+ csvFormat.print(out, true, false);
+ csvFormat.print(out, "\"quoted\" test", false);
+ assertEquals("Unexpected format ",
+ String.format("%s,%d,%b,%s", "test", 1, true, "\"\"\"quoted\"\" test\""),
+ out.toString());
+ }
+
+ public void testPrintComments() throws Exception
+ {
+ CSVFormat csvFormat = new CSVFormat();
+ final StringWriter out = new StringWriter();
+ csvFormat.printComments(out, "comment1", "comment2");
+ assertEquals("Unexpected format of comments",
+ String.format("# %s%s# %s%s", "comment1", "\r\n", "comment2", "\r\n"),
+ out.toString());
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org